From 53d40df292b5771bf6637704d948d441093aa2a4 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 3 Jun 2023 21:53:29 -0700 Subject: [PATCH 01/33] packaging: add appimage update capability Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> packaging(linux): use vars when refrencing qt install dir Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> packaging(appimage): dont use rsync Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> packaging: use runner.workspace when copying files Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> packaging(appimage): put zsync in relase:x Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> use with:token insted of env for GITHUB_TOKEN (which is depricated) Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> fix: appimage zsync needs consistant filenames across verisons Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> upload proper zsync Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> fix: non versioned appimage filename Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 32 +++++++++++++++++++++++---- .github/workflows/trigger_release.yml | 9 ++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a6a6eceaa..76833f7b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -249,6 +249,8 @@ jobs: wget "https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage" wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage" + wget "https://github.com/AppImageCommunity/AppImageUpdate/releases/download/continuous/AppImageUpdate-x86_64.AppImage" + ${{ github.workspace }}/.github/scripts/prepare_JREs.sh - name: Add QT_HOST_PATH var (Windows MSVC arm64) @@ -386,8 +388,8 @@ jobs: cd ${{ env.INSTALL_DIR }} if ("${{ matrix.qt_ver }}" -eq "5") { - Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll - Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll + Copy-Item ${{ runner.workspace }}/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll + Copy-Item ${{ runner.workspace }}/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll } cd ${{ github.workspace }} @@ -468,7 +470,7 @@ jobs: run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr - export OUTPUT="PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage" + export OUTPUT="PrismLauncher-Linux-x86_64.AppImage" chmod +x linuxdeploy-*.AppImage @@ -479,7 +481,7 @@ jobs: cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk - cp -r /home/runner/work/PrismLauncher/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines + cp -r ${{ runner.workspace }}/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}//usr/lib/ @@ -491,7 +493,22 @@ jobs: LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib" export LD_LIBRARY_PATH + chmod +x AppImageUpdate-x86_64.AppImage + ./AppImageUpdate-x86_64.AppImage --appimage-extract + + mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/optional + mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins + + cp -r squashfs-root/usr/bin/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin + cp -r squashfs-root/usr/lib/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib + cp -r squashfs-root/usr/optional/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/optional + cp -r squashfs-root/usr/optional/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins + + export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-x86_64.AppImage.zsync" + ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg + + mv "PrismLauncher-Linux-x86_64.AppImage" "PrismLauncher-Linux-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage" ## # UPLOAD BUILDS @@ -559,6 +576,13 @@ jobs: with: name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage + + - name: Upload AppImage Zsync (Linux) + if: runner.os == 'Linux' && matrix.qt_ver != 5 + uses: actions/upload-artifact@v3 + with: + name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage.zsync + path: PrismLauncher-Linux-x86_64.AppImage.zsync - name: ccache stats (Windows MinGW-w64) if: runner.os == 'Windows' && matrix.msystem != '' diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index f19b83986..2a46ff5e7 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -43,7 +43,8 @@ jobs: mv PrismLauncher-Linux-Qt6*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz mv PrismLauncher-Linux-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz mv PrismLauncher-Linux*/PrismLauncher.tar.gz PrismLauncher-Linux-${{ env.VERSION }}.tar.gz - mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage + mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-x86_64.AppImage + mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync mv PrismLauncher-macOS-Legacy*/PrismLauncher.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz mv PrismLauncher-macOS*/PrismLauncher.tar.gz PrismLauncher-macOS-${{ env.VERSION }}.tar.gz @@ -78,9 +79,8 @@ jobs: - name: Create release id: create_release uses: softprops/action-gh-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: + token: ${{ secrets.GITHUB_TOKEN }} tag_name: ${{ github.ref }} name: Prism Launcher ${{ env.VERSION }} draft: true @@ -88,7 +88,8 @@ jobs: files: | PrismLauncher-Linux-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz - PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage + PrismLauncher-Linux-x86_64.AppImage + PrismLauncher-Linux-x86_64.AppImage.zsync PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip From 66858100810fd9072237d22624efdce948ce46cf Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 19 Jun 2023 01:26:04 -0700 Subject: [PATCH 02/33] packaging: sign appimages with gpg Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 76833f7b0..d57b04e4f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,6 +24,12 @@ on: CACHIX_AUTH_TOKEN: description: Private token for authenticating against Cachix cache required: false + GPG_PRIVATE_KEY: + description: Private key for AppImage signing + required: false + GPG_PRIVATE_KEY_ID: + description: ID for the GPG_PRIVATE_KEY, to select the signign key + required: false jobs: build: @@ -426,7 +432,7 @@ jobs: run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - + Get-ChildItem ${{ env.INSTALL_PORTABLE_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_PORTABLE_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows, installer) @@ -467,6 +473,8 @@ jobs: - name: Package AppImage (Linux) if: runner.os == 'Linux' && matrix.qt_ver != 5 shell: bash + env: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr @@ -482,7 +490,7 @@ jobs: cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk cp -r ${{ runner.workspace }}/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines - + cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}//usr/lib/ @@ -506,8 +514,18 @@ jobs: export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-x86_64.AppImage.zsync" + if [ '${{ secrets.GPG_PRIVATE_KEY_ID }}' != '' ]; then + export SIGN=1 + export SIGN_KEY=${{ secrets.GPG_PRIVATE_KEY_ID }} + mkdir -p ~/.gnupg/ + printf "$GPG_PRIVATE_KEY" | base64 --decode > ~/.gnupg/private.key + gpg --import ~/.gnupg/private.key + else + echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $env:GITHUB_STEP_SUMMARY + fi + ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg - + mv "PrismLauncher-Linux-x86_64.AppImage" "PrismLauncher-Linux-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage" ## From 6ccc7e77f918503125c363eb8ac9455aa9fc095e Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 19 Jun 2023 22:42:27 +0100 Subject: [PATCH 03/33] Basic, unfinished & broken impl Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 3 + launcher/resources/multimc/multimc.qrc | 4 + .../multimc/scalable/fabric-loader.svg | 1 + .../multimc/scalable/forge-loader.svg | 1 + .../multimc/scalable/quilt-loader.svg | 70 +++++++++ launcher/ui/InstanceWindow.cpp | 5 + launcher/ui/InstanceWindow.h | 1 + launcher/ui/dialogs/InstallLoaderDialog.cpp | 121 +++++++++++++++ launcher/ui/dialogs/InstallLoaderDialog.h | 42 ++++++ .../ui/dialogs/ResourceDownloadDialog.cpp | 26 +--- launcher/ui/dialogs/ResourceDownloadDialog.h | 3 +- launcher/ui/pages/BasePageContainer.h | 1 + launcher/ui/pages/instance/VersionPage.cpp | 140 +----------------- launcher/ui/pages/instance/VersionPage.h | 5 +- launcher/ui/pages/instance/VersionPage.ui | 71 +++------ .../ui/pages/modplatform/ResourcePage.cpp | 2 +- launcher/ui/widgets/PageContainer.cpp | 5 + launcher/ui/widgets/PageContainer.h | 3 +- 18 files changed, 287 insertions(+), 217 deletions(-) create mode 100644 launcher/resources/multimc/scalable/fabric-loader.svg create mode 100644 launcher/resources/multimc/scalable/forge-loader.svg create mode 100644 launcher/resources/multimc/scalable/quilt-loader.svg create mode 100644 launcher/ui/dialogs/InstallLoaderDialog.cpp create mode 100644 launcher/ui/dialogs/InstallLoaderDialog.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ce2771a49..d09895773 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -944,6 +944,8 @@ SET(LAUNCHER_SOURCES ui/dialogs/ChooseProviderDialog.cpp ui/dialogs/ModUpdateDialog.cpp ui/dialogs/ModUpdateDialog.h + ui/dialogs/InstallLoaderDialog.cpp + ui/dialogs/InstallLoaderDialog.h # GUI - widgets ui/widgets/Common.cpp @@ -1066,6 +1068,7 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ScrollMessageBox.ui ui/dialogs/BlockedModsDialog.ui ui/dialogs/ChooseProviderDialog.ui + ui/dialogs/InstallLoaderDialog.ui ) qt_add_resources(LAUNCHER_RESOURCES diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index 2c00f28fa..f018e8748 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -347,5 +347,9 @@ scalable/export.svg scalable/launch.svg scalable/server.svg + + scalable/fabric-loader.svg + scalable/quilt-loader.svg + scalable/forge-loader.svg diff --git a/launcher/resources/multimc/scalable/fabric-loader.svg b/launcher/resources/multimc/scalable/fabric-loader.svg new file mode 100644 index 000000000..06aa7801e --- /dev/null +++ b/launcher/resources/multimc/scalable/fabric-loader.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/launcher/resources/multimc/scalable/forge-loader.svg b/launcher/resources/multimc/scalable/forge-loader.svg new file mode 100644 index 000000000..b73360b86 --- /dev/null +++ b/launcher/resources/multimc/scalable/forge-loader.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/launcher/resources/multimc/scalable/quilt-loader.svg b/launcher/resources/multimc/scalable/quilt-loader.svg new file mode 100644 index 000000000..fd6faea4b --- /dev/null +++ b/launcher/resources/multimc/scalable/quilt-loader.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index c62b370fd..d9a21f6f2 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -263,6 +263,11 @@ bool InstanceWindow::selectPage(QString pageId) return m_container->selectPage(pageId); } +BasePage* InstanceWindow::selectedPage() +{ + return m_container->selectedPage(); +} + void InstanceWindow::refreshContainer() { m_container->refreshContainer(); diff --git a/launcher/ui/InstanceWindow.h b/launcher/ui/InstanceWindow.h index 554c4c740..78d7474da 100644 --- a/launcher/ui/InstanceWindow.h +++ b/launcher/ui/InstanceWindow.h @@ -56,6 +56,7 @@ public: virtual ~InstanceWindow(); bool selectPage(QString pageId) override; + BasePage* selectedPage() override; void refreshContainer() override; QString instanceId(); diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp new file mode 100644 index 000000000..34c91c681 --- /dev/null +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -0,0 +1,121 @@ +#include "InstallLoaderDialog.h" + +#include +#include +#include +#include "Application.h" +#include "BuildConfig.h" +#include "DesktopServices.h" +#include "meta/Index.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/PackProfile.h" +#include "ui/widgets/PageContainer.h" +#include "ui/widgets/VersionSelectWidget.h" + +class LoaderPage : public VersionSelectWidget, public BasePage { + public: + LoaderPage(const QString&& id, + const QString&& icon, + const QString&& name, + // "lightweight" loaders are independent to any game version + const bool lightweight, + const std::shared_ptr profile, + QWidget* parent = nullptr) + : VersionSelectWidget(parent), m_id(std::move(id)), m_icon(std::move(icon)), m_name(std::move(name)) + { + const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); + setEmptyErrorString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); + if (!lightweight) + setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); + + if (const QString currentVersion = profile->getComponentVersion(id); !currentVersion.isNull()) + setCurrentVersion(currentVersion); + } + + QString id() const override { return m_id; } + QString displayName() const override { return m_name; } + QIcon icon() const override { return APPLICATION->getThemedIcon(m_icon); } + + void openedImpl() override + { + if (m_loaded) + return; + + const auto versions = APPLICATION->metadataIndex()->get(m_id); + if (!versions) + return; + + initialize(versions.get()); + m_loaded = true; + } + + private: + const QString m_id; + const QString m_icon; + const QString m_name; + bool m_loaded = false; +}; + +InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, QWidget* parent) + : QDialog(parent), m_profile(profile), m_container(new PageContainer(this)) +{ + auto layout = new QVBoxLayout(this); + + m_container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + layout->addWidget(m_container); + + auto buttonLayout = new QHBoxLayout(this); + + auto refreshButton = new QPushButton(tr("&Refresh"), this); + connect(refreshButton, &QPushButton::pressed, this, [this] { + LoaderPage* page = dynamic_cast(m_container->selectedPage()); + Q_ASSERT(page != nullptr); + page->loadList(); + }); + buttonLayout->addWidget(refreshButton); + + auto buttons = new QDialogButtonBox(this); + buttons->setOrientation(Qt::Horizontal); + buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + buttonLayout->addWidget(buttons); + + layout->addLayout(buttonLayout); + + setWindowTitle(dialogTitle()); + resize(650, 400); +} + +QList InstallLoaderDialog::getPages() +{ + return { // Fabric + new LoaderPage("net.fabricmc.fabric-loader", "fabric-loader", tr("Fabric"), true, m_profile, this), + // Quilt + new LoaderPage("org.quiltmc.quilt-loader", "quilt-loader", tr("Quilt"), true, m_profile, this), + // Forge + new LoaderPage("net.minecraftforge", "forge-loader", tr("Forge"), false, m_profile, this), + // LiteLoader + new LoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) + }; +} + +QString InstallLoaderDialog::dialogTitle() +{ + return tr("Install Loader"); +} + +void InstallLoaderDialog::done(int result) +{ + if (result == Accepted) { + LoaderPage* page = dynamic_cast(m_container->selectedPage()); + Q_ASSERT(page != nullptr); + + if (page->selectedVersion()) { + m_profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); + m_profile->resolve(Net::Mode::Online); + } + } + + QDialog::done(result); +} diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h new file mode 100644 index 000000000..26b39e4a9 --- /dev/null +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include "ui/pages/BasePageProvider.h" + +class MinecraftInstance; +class PageContainer; +class PackProfile; + +class InstallLoaderDialog : public QDialog, public BasePageProvider { + Q_OBJECT + + public: + explicit InstallLoaderDialog(std::shared_ptr instance, QWidget* parent = nullptr); + + QList getPages() override; + QString dialogTitle() override; + + void done(int result) override; + + private: + std::shared_ptr m_profile; + PageContainer* m_container; +}; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 6d90480ff..784662a07 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -148,15 +148,17 @@ bool ResourceDownloadDialog::selectPage(QString pageId) return m_container->selectPage(pageId); } -ResourcePage* ResourceDownloadDialog::getSelectedPage() +ResourcePage* ResourceDownloadDialog::selectedPage() { - return m_selectedPage; + ResourcePage* result = dynamic_cast(m_container->selectedPage()); + Q_ASSERT(result != nullptr); + return result; } void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& ver) { removeResource(pack->name); - m_selectedPage->addResourceToPage(pack, ver, getBaseModel()); + selectedPage()->addResourceToPage(pack, ver, getBaseModel()); setButtonStatus(); } @@ -196,14 +198,8 @@ void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* s return; } - m_selectedPage = dynamic_cast(selected); - if (!m_selectedPage) { - qCritical() << "Page '" << selected->displayName() << "' in ResourceDownloadDialog is not a ResourcePage!"; - return; - } - // Same effect as having a global search bar - m_selectedPage->setSearchTerm(prev_page->getSearchTerm()); + selectedPage()->setSearchTerm(prev_page->getSearchTerm()); } ModDownloadDialog::ModDownloadDialog(QWidget* parent, const std::shared_ptr& mods, BaseInstance* instance) @@ -226,8 +222,6 @@ QList ModDownloadDialog::getPages() if (APPLICATION->capabilities() & Application::SupportsFlame) pages.append(FlameModPage::create(this, *m_instance)); - m_selectedPage = dynamic_cast(pages[0]); - return pages; } @@ -253,8 +247,6 @@ QList ResourcePackDownloadDialog::getPages() if (APPLICATION->capabilities() & Application::SupportsFlame) pages.append(FlameResourcePackPage::create(this, *m_instance)); - m_selectedPage = dynamic_cast(pages[0]); - return pages; } @@ -280,8 +272,6 @@ QList TexturePackDownloadDialog::getPages() if (APPLICATION->capabilities() & Application::SupportsFlame) pages.append(FlameTexturePackPage::create(this, *m_instance)); - m_selectedPage = dynamic_cast(pages[0]); - return pages; } @@ -302,11 +292,7 @@ ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent, QList ShaderPackDownloadDialog::getPages() { QList pages; - pages.append(ModrinthShaderPackPage::create(this, *m_instance)); - - m_selectedPage = dynamic_cast(pages[0]); - return pages; } diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 5b5b48c63..5077b2ca0 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -60,7 +60,7 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { QString dialogTitle() override { return tr("Download %1").arg(resourcesString()); }; bool selectPage(QString pageId); - ResourcePage* getSelectedPage(); + ResourcePage* selectedPage(); void addResource(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&); void removeResource(const QString&); @@ -85,7 +85,6 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { const std::shared_ptr m_base_model; PageContainer* m_container = nullptr; - ResourcePage* m_selectedPage = nullptr; QDialogButtonBox m_buttons; QVBoxLayout m_vertical_layout; diff --git a/launcher/ui/pages/BasePageContainer.h b/launcher/ui/pages/BasePageContainer.h index b41fe12af..4cb7fe29c 100644 --- a/launcher/ui/pages/BasePageContainer.h +++ b/launcher/ui/pages/BasePageContainer.h @@ -7,6 +7,7 @@ class BasePageContainer public: virtual ~BasePageContainer(){}; virtual bool selectPage(QString pageId) = 0; + virtual BasePage* selectedPage() = 0; virtual BasePage* getPage(QString pageId) { return nullptr; }; virtual void refreshContainer() = 0; virtual bool requestClose() = 0; diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 74b7ec7c2..97a6bbe4a 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -52,6 +52,7 @@ #include #include "VersionPage.h" +#include "ui/dialogs/InstallLoaderDialog.h" #include "ui_VersionPage.h" #include "ui/dialogs/CustomMessageBox.h" @@ -254,20 +255,6 @@ void VersionPage::updateRunningStatus(bool running) void VersionPage::updateVersionControls() { - // FIXME: this is a dirty hack - auto minecraftVersion = Version(m_profile->getComponentVersion("net.minecraft")); - - ui->actionInstall_Forge->setEnabled(controlsEnabled); - - bool supportsFabric = minecraftVersion >= Version("1.14"); - ui->actionInstall_Fabric->setEnabled(controlsEnabled && supportsFabric); - - bool supportsQuilt = minecraftVersion >= Version("1.14"); - ui->actionInstall_Quilt->setEnabled(controlsEnabled && supportsQuilt); - - bool supportsLiteLoader = minecraftVersion <= Version("1.12.2"); - ui->actionInstall_LiteLoader->setEnabled(controlsEnabled && supportsLiteLoader); - updateButtons(); } @@ -287,7 +274,6 @@ void VersionPage::updateButtons(int row) ui->actionAdd_Empty->setEnabled(controlsEnabled); ui->actionImport_Components->setEnabled(controlsEnabled); ui->actionReload->setEnabled(controlsEnabled); - ui->actionInstall_mods->setEnabled(controlsEnabled); ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled); ui->actionAdd_to_Minecraft_jar->setEnabled(controlsEnabled); ui->actionAdd_Agents->setEnabled(controlsEnabled); @@ -446,17 +432,6 @@ void VersionPage::on_actionChange_version_triggered() return; } auto uid = list->uid(); - // FIXME: this is a horrible HACK. Get version filtering information from the actual metadata... - if(uid == "net.minecraftforge") - { - on_actionInstall_Forge_triggered(); - return; - } - else if (uid == "com.mumfrey.liteloader") - { - on_actionInstall_LiteLoader_triggered(); - return; - } VersionSelectDialog vselect(list.get(), tr("Change %1 version").arg(name), this); if (uid == "net.fabricmc.intermediary" || uid == "org.quiltmc.hashed") { @@ -508,87 +483,11 @@ void VersionPage::on_actionDownload_All_triggered() m_container->refreshContainer(); } -void VersionPage::on_actionInstall_Forge_triggered() +void VersionPage::on_actionInstall_Loader_triggered() { - auto vlist = APPLICATION->metadataIndex()->get("net.minecraftforge"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select Forge version"), this); - vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyErrorString(tr("Couldn't load or download the Forge version lists!")); - - auto currentVersion = m_profile->getComponentVersion("net.minecraftforge"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("net.minecraftforge", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - // m_profile->installVersion(); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } -} - -void VersionPage::on_actionInstall_Fabric_triggered() -{ - auto vlist = APPLICATION->metadataIndex()->get("net.fabricmc.fabric-loader"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select Fabric Loader version"), this); - vselect.setEmptyString(tr("No Fabric Loader versions are currently available.")); - vselect.setEmptyErrorString(tr("Couldn't load or download the Fabric Loader version lists!")); - - auto currentVersion = m_profile->getComponentVersion("net.fabricmc.fabric-loader"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("net.fabricmc.fabric-loader", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } -} - -void VersionPage::on_actionInstall_Quilt_triggered() -{ - auto vlist = APPLICATION->metadataIndex()->get("org.quiltmc.quilt-loader"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select Quilt Loader version"), this); - vselect.setEmptyString(tr("No Quilt Loader versions are currently available.")); - vselect.setEmptyErrorString(tr("Couldn't load or download the Quilt Loader version lists!")); - - auto currentVersion = m_profile->getComponentVersion("org.quiltmc.quilt-loader"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("org.quiltmc.quilt-loader", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } + InstallLoaderDialog dialog(m_inst->getPackProfile(), this); + dialog.exec(); + m_container->refreshContainer(); } void VersionPage::on_actionAdd_Empty_triggered() @@ -609,35 +508,6 @@ void VersionPage::on_actionAdd_Empty_triggered() } } -void VersionPage::on_actionInstall_LiteLoader_triggered() -{ - auto vlist = APPLICATION->metadataIndex()->get("com.mumfrey.liteloader"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select LiteLoader version"), this); - vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyErrorString(tr("Couldn't load or download the LiteLoader version lists!")); - - auto currentVersion = m_profile->getComponentVersion("com.mumfrey.liteloader"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("com.mumfrey.liteloader", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - // m_profile->installVersion(vselect.selectedVersion()); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } -} - void VersionPage::on_actionLibrariesFolder_triggered() { DesktopServices::openDirectory(m_inst->getLocalLibraryPath(), true); diff --git a/launcher/ui/pages/instance/VersionPage.h b/launcher/ui/pages/instance/VersionPage.h index d00877142..0dcb4635a 100644 --- a/launcher/ui/pages/instance/VersionPage.h +++ b/launcher/ui/pages/instance/VersionPage.h @@ -79,11 +79,8 @@ public: private slots: void on_actionChange_version_triggered(); - void on_actionInstall_Forge_triggered(); - void on_actionInstall_Fabric_triggered(); - void on_actionInstall_Quilt_triggered(); + void on_actionInstall_Loader_triggered(); void on_actionAdd_Empty_triggered(); - void on_actionInstall_LiteLoader_triggered(); void on_actionReload_triggered(); void on_actionRemove_triggered(); void on_actionMove_up_triggered(); diff --git a/launcher/ui/pages/instance/VersionPage.ui b/launcher/ui/pages/instance/VersionPage.ui index 4777eafe0..cf7c659bc 100644 --- a/launcher/ui/pages/instance/VersionPage.ui +++ b/launcher/ui/pages/instance/VersionPage.ui @@ -98,12 +98,7 @@ - - - - - - + @@ -118,26 +113,26 @@ - Change version + Change Version - Change version of the selected package. + Change version of the selected component. - Move up + Move Up - Make the selected package apply sooner. + Make the selected component apply sooner. - Move down + Move Down - Make the selected package apply later. + Make the selected component apply later. @@ -145,7 +140,7 @@ Remove - Remove selected package from the instance. + Remove selected component from the instance. @@ -153,7 +148,7 @@ Customize - Customize selected package. + Customize selected component. @@ -161,7 +156,7 @@ Edit - Edit selected package. + Edit selected component. @@ -169,47 +164,15 @@ Revert - Revert the selected package to default. + Revert the selected component to default. - + - Install Forge + Install Loader - Install the Minecraft Forge package. - - - - - Install Fabric - - - Install the Fabric Loader package. - - - - - Install Quilt - - - Install the Quilt Loader package. - - - - - Install LiteLoader - - - Install the LiteLoader package. - - - - - Install mods - - - Install normal mods. + Install a mod loader. @@ -238,7 +201,7 @@ Add Empty - Add an empty custom package. + Add an empty custom component. @@ -246,12 +209,12 @@ Reload - Reload all packages. + Reload all components. - Download All + Download all Download the files needed to launch the instance now. diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 1d2509d80..91d722fca 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -389,7 +389,7 @@ void ResourcePage::openUrl(const QUrl& url) if (slug != getCurrentPack()->slug) { m_parent_dialog->selectPage(page); - auto newPage = m_parent_dialog->getSelectedPage(); + auto newPage = m_parent_dialog->selectedPage(); QLineEdit* searchEdit = newPage->m_ui->searchEdit; auto model = newPage->m_model; diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 38a228973..c3606b789 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -137,6 +137,11 @@ BasePage* PageContainer::getPage(QString pageId) return m_model->findPageEntryById(pageId); } +BasePage* PageContainer::selectedPage() +{ + return m_currentPage; +} + const QList PageContainer::getPages() const { return m_model->pages(); diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index ad74d43a2..89c3343ed 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -78,7 +78,8 @@ public: return false; } - virtual bool selectPage(QString pageId) override; + bool selectPage(QString pageId) override; + BasePage* selectedPage() override; BasePage* getPage(QString pageId) override; const QList getPages() const; From 82d3755e25fc01e3468e6940abab9dcc0a819e22 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 19 Jun 2023 23:36:18 +0100 Subject: [PATCH 04/33] License all the things Signed-off-by: TheKodeToad --- launcher/ui/InstanceWindow.cpp | 3 ++- launcher/ui/InstanceWindow.h | 3 ++- launcher/ui/dialogs/InstallLoaderDialog.cpp | 18 ++++++++++++++++++ launcher/ui/dialogs/InstallLoaderDialog.h | 2 +- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 2 +- launcher/ui/dialogs/ResourceDownloadDialog.h | 2 +- launcher/ui/pages/instance/VersionPage.cpp | 2 +- launcher/ui/pages/modplatform/ResourcePage.cpp | 2 +- launcher/ui/widgets/PageContainer.cpp | 3 ++- launcher/ui/widgets/PageContainer.h | 3 ++- 10 files changed, 31 insertions(+), 9 deletions(-) diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index d9a21f6f2..30a215e33 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/InstanceWindow.h b/launcher/ui/InstanceWindow.h index 78d7474da..adbc46ace 100644 --- a/launcher/ui/InstanceWindow.h +++ b/launcher/ui/InstanceWindow.h @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 34c91c681..1b003e522 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "InstallLoaderDialog.h" #include diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index 26b39e4a9..7a32e4274 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 784662a07..8d4e51b24 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 5077b2ca0..b56a9adc0 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 97a6bbe4a..53a710083 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -6,7 +6,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022-2023 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 91d722fca..ace7fb1b2 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -4,7 +4,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index c3606b789..308fad6b3 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2022 Jamie Mansfield + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index 89c3343ed..1da269ced 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From a389983d7dfb78a2bf6c1b85e5837dcdac789070 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 20 Jun 2023 00:28:42 +0100 Subject: [PATCH 05/33] Just use the old ordering Signed-off-by: TheKodeToad --- launcher/resources/multimc/multimc.qrc | 2 +- launcher/ui/dialogs/InstallLoaderDialog.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index f018e8748..13052760b 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -348,8 +348,8 @@ scalable/launch.svg scalable/server.svg + scalable/forge-loader.svg scalable/fabric-loader.svg scalable/quilt-loader.svg - scalable/forge-loader.svg diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 1b003e522..5df27dba2 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -107,12 +107,12 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q QList InstallLoaderDialog::getPages() { - return { // Fabric + return { // Forge + new LoaderPage("net.minecraftforge", "forge-loader", tr("Forge"), false, m_profile, this), + // Fabric new LoaderPage("net.fabricmc.fabric-loader", "fabric-loader", tr("Fabric"), true, m_profile, this), // Quilt new LoaderPage("org.quiltmc.quilt-loader", "quilt-loader", tr("Quilt"), true, m_profile, this), - // Forge - new LoaderPage("net.minecraftforge", "forge-loader", tr("Forge"), false, m_profile, this), // LiteLoader new LoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) }; From 94510edd722b72e375011c6d4a6629c478728c72 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 20 Jun 2023 19:57:15 +0100 Subject: [PATCH 06/33] Rework icons (Fabric is blurry now but looks better) Signed-off-by: TheKodeToad --- .../multimc/128x128/instances/fabricmc.png | Bin 0 -> 4839 bytes .../multimc/128x128/instances/liteloader.png | Bin 0 -> 20337 bytes .../multimc/22x22/fabricmc-small.png | Bin 0 -> 5672 bytes launcher/resources/multimc/multimc.qrc | 8 +- .../multimc/scalable/fabric-loader.svg | 1 - .../multimc/scalable/forge-loader.svg | 1 - .../multimc/scalable/instances/forge.svg | 43 ++++++++ .../multimc/scalable/instances/quiltmc.svg | 98 ++++++++++++++++++ .../multimc/scalable/quilt-loader.svg | 70 ------------- launcher/ui/dialogs/InstallLoaderDialog.cpp | 8 +- 10 files changed, 150 insertions(+), 79 deletions(-) create mode 100644 launcher/resources/multimc/128x128/instances/fabricmc.png create mode 100644 launcher/resources/multimc/128x128/instances/liteloader.png create mode 100644 launcher/resources/multimc/22x22/fabricmc-small.png delete mode 100644 launcher/resources/multimc/scalable/fabric-loader.svg delete mode 100644 launcher/resources/multimc/scalable/forge-loader.svg create mode 100644 launcher/resources/multimc/scalable/instances/forge.svg create mode 100644 launcher/resources/multimc/scalable/instances/quiltmc.svg delete mode 100644 launcher/resources/multimc/scalable/quilt-loader.svg diff --git a/launcher/resources/multimc/128x128/instances/fabricmc.png b/launcher/resources/multimc/128x128/instances/fabricmc.png new file mode 100644 index 0000000000000000000000000000000000000000..c78543aeebf2b630810d2f5c8bd4d58ea6949ef7 GIT binary patch literal 4839 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 Mp00i_>zopr0Ll1@YXATM literal 0 HcmV?d00001 diff --git a/launcher/resources/multimc/128x128/instances/liteloader.png b/launcher/resources/multimc/128x128/instances/liteloader.png new file mode 100644 index 0000000000000000000000000000000000000000..88295e6448fdea083a04969c0e2cc7eae0fbc259 GIT binary patch literal 20337 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 tWH3oAU^(dE^0MN%U?(>y)37&sUh7`Pc2 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 SJD!t4BW9kielF{r5}E+3v=b-* literal 0 HcmV?d00001 diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index 13052760b..907fbb5d3 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -348,8 +348,10 @@ scalable/launch.svg scalable/server.svg - scalable/forge-loader.svg - scalable/fabric-loader.svg - scalable/quilt-loader.svg + scalable/instances/forge.svg + scalable/instances/quiltmc.svg + 22x22/fabricmc-small.png + 128x128/instances/fabricmc.png + 128x128/instances/liteloader.png diff --git a/launcher/resources/multimc/scalable/fabric-loader.svg b/launcher/resources/multimc/scalable/fabric-loader.svg deleted file mode 100644 index 06aa7801e..000000000 --- a/launcher/resources/multimc/scalable/fabric-loader.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/launcher/resources/multimc/scalable/forge-loader.svg b/launcher/resources/multimc/scalable/forge-loader.svg deleted file mode 100644 index b73360b86..000000000 --- a/launcher/resources/multimc/scalable/forge-loader.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/launcher/resources/multimc/scalable/instances/forge.svg b/launcher/resources/multimc/scalable/instances/forge.svg new file mode 100644 index 000000000..ea402c5b2 --- /dev/null +++ b/launcher/resources/multimc/scalable/instances/forge.svg @@ -0,0 +1,43 @@ + + diff --git a/launcher/resources/multimc/scalable/instances/quiltmc.svg b/launcher/resources/multimc/scalable/instances/quiltmc.svg new file mode 100644 index 000000000..a7aaca53f --- /dev/null +++ b/launcher/resources/multimc/scalable/instances/quiltmc.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + diff --git a/launcher/resources/multimc/scalable/quilt-loader.svg b/launcher/resources/multimc/scalable/quilt-loader.svg deleted file mode 100644 index fd6faea4b..000000000 --- a/launcher/resources/multimc/scalable/quilt-loader.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 5df27dba2..a9d08fc55 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -42,7 +42,7 @@ class LoaderPage : public VersionSelectWidget, public BasePage { : VersionSelectWidget(parent), m_id(std::move(id)), m_icon(std::move(icon)), m_name(std::move(name)) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); - setEmptyErrorString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); + setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); if (!lightweight) setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); @@ -108,11 +108,11 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q QList InstallLoaderDialog::getPages() { return { // Forge - new LoaderPage("net.minecraftforge", "forge-loader", tr("Forge"), false, m_profile, this), + new LoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile, this), // Fabric - new LoaderPage("net.fabricmc.fabric-loader", "fabric-loader", tr("Fabric"), true, m_profile, this), + new LoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile, this), // Quilt - new LoaderPage("org.quiltmc.quilt-loader", "quilt-loader", tr("Quilt"), true, m_profile, this), + new LoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile, this), // LiteLoader new LoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) }; From 1f16380efce61fa028d6c25308c8cac7925da72a Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 22 Jun 2023 12:56:47 +0100 Subject: [PATCH 07/33] Fix I could use rvalue references and fix my brain fart, but i think regular references are more readable and safer here. Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index a9d08fc55..cc8d7e546 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -32,14 +32,14 @@ class LoaderPage : public VersionSelectWidget, public BasePage { public: - LoaderPage(const QString&& id, - const QString&& icon, - const QString&& name, + LoaderPage(const QString& id, + const QString& icon, + const QString& name, // "lightweight" loaders are independent to any game version const bool lightweight, const std::shared_ptr profile, QWidget* parent = nullptr) - : VersionSelectWidget(parent), m_id(std::move(id)), m_icon(std::move(icon)), m_name(std::move(name)) + : VersionSelectWidget(parent), m_id(id), m_icon(icon), m_name(name) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); From dea33a3c1d3936cc5cfdd0917673af84e94d70de Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 22 Jun 2023 13:11:55 +0100 Subject: [PATCH 08/33] =?UTF-8?q?Make=20`selectedPage`=20const=20?= =?UTF-8?q?=F0=9F=A4=A6=E2=80=8D=E2=99=80=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TheKodeToad --- launcher/ui/InstanceWindow.cpp | 2 +- launcher/ui/InstanceWindow.h | 2 +- launcher/ui/pages/BasePageContainer.h | 2 +- launcher/ui/widgets/PageContainer.cpp | 2 +- launcher/ui/widgets/PageContainer.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index 30a215e33..d784a40fc 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -264,7 +264,7 @@ bool InstanceWindow::selectPage(QString pageId) return m_container->selectPage(pageId); } -BasePage* InstanceWindow::selectedPage() +BasePage* InstanceWindow::selectedPage() const { return m_container->selectedPage(); } diff --git a/launcher/ui/InstanceWindow.h b/launcher/ui/InstanceWindow.h index adbc46ace..582cff138 100644 --- a/launcher/ui/InstanceWindow.h +++ b/launcher/ui/InstanceWindow.h @@ -57,7 +57,7 @@ public: virtual ~InstanceWindow(); bool selectPage(QString pageId) override; - BasePage* selectedPage() override; + BasePage* selectedPage() const override; void refreshContainer() override; QString instanceId(); diff --git a/launcher/ui/pages/BasePageContainer.h b/launcher/ui/pages/BasePageContainer.h index 4cb7fe29c..eb3c94272 100644 --- a/launcher/ui/pages/BasePageContainer.h +++ b/launcher/ui/pages/BasePageContainer.h @@ -7,7 +7,7 @@ class BasePageContainer public: virtual ~BasePageContainer(){}; virtual bool selectPage(QString pageId) = 0; - virtual BasePage* selectedPage() = 0; + virtual BasePage* selectedPage() const = 0; virtual BasePage* getPage(QString pageId) { return nullptr; }; virtual void refreshContainer() = 0; virtual bool requestClose() = 0; diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 308fad6b3..7b5b26b74 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -138,7 +138,7 @@ BasePage* PageContainer::getPage(QString pageId) return m_model->findPageEntryById(pageId); } -BasePage* PageContainer::selectedPage() +BasePage* PageContainer::selectedPage() const { return m_currentPage; } diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index 1da269ced..bb365c826 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -80,7 +80,7 @@ public: } bool selectPage(QString pageId) override; - BasePage* selectedPage() override; + BasePage* selectedPage() const override; BasePage* getPage(QString pageId) override; const QList getPages() const; From 05d2c1f0b06519eba9cc5ad22848106b49f9bd15 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 22 Jun 2023 18:18:33 +0100 Subject: [PATCH 09/33] Dynamic button text Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 23 ++++++++++++++------- launcher/ui/dialogs/InstallLoaderDialog.h | 3 +++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index cc8d7e546..6e1ad1c04 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -75,7 +75,7 @@ class LoaderPage : public VersionSelectWidget, public BasePage { }; InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, QWidget* parent) - : QDialog(parent), m_profile(profile), m_container(new PageContainer(this)) + : QDialog(parent), m_profile(profile), m_container(new PageContainer(this)), m_buttons(new QDialogButtonBox(this)) { auto layout = new QVBoxLayout(this); @@ -92,17 +92,20 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q }); buttonLayout->addWidget(refreshButton); - auto buttons = new QDialogButtonBox(this); - buttons->setOrientation(Qt::Horizontal); - buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); - buttonLayout->addWidget(buttons); + m_buttons->setOrientation(Qt::Horizontal); + m_buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + connect(m_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + buttonLayout->addWidget(m_buttons); layout->addLayout(buttonLayout); setWindowTitle(dialogTitle()); resize(650, 400); + + connect(m_container, &PageContainer::selectedPageChanged, this, + [this](BasePage* previous, BasePage* selected) { updateAcceptButton(selected); }); + updateAcceptButton(m_container->selectedPage()); } QList InstallLoaderDialog::getPages() @@ -123,6 +126,12 @@ QString InstallLoaderDialog::dialogTitle() return tr("Install Loader"); } +void InstallLoaderDialog::updateAcceptButton(const BasePage* page) +{ + auto installed = !m_profile->getComponentVersion(page->id()).isNull(); + m_buttons->button(QDialogButtonBox::Ok)->setText(installed ? tr("&Update") : tr("&Install")); +} + void InstallLoaderDialog::done(int result) { if (result == Accepted) { diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index 7a32e4274..6c8762dc0 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -24,6 +24,7 @@ class MinecraftInstance; class PageContainer; class PackProfile; +class QDialogButtonBox; class InstallLoaderDialog : public QDialog, public BasePageProvider { Q_OBJECT @@ -34,9 +35,11 @@ class InstallLoaderDialog : public QDialog, public BasePageProvider { QList getPages() override; QString dialogTitle() override; + void updateAcceptButton(const BasePage* page); void done(int result) override; private: std::shared_ptr m_profile; PageContainer* m_container; + QDialogButtonBox* m_buttons; }; From 0e7f43592191ecd7946366f2807c89dbaa5d5caf Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 23 Jun 2023 20:56:07 -0700 Subject: [PATCH 10/33] echo to correct var for summary Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a752afb77..fa6f0f61b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -526,7 +526,7 @@ jobs: printf "$GPG_PRIVATE_KEY" | base64 --decode > ~/.gnupg/private.key gpg --import ~/.gnupg/private.key else - echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $env:GITHUB_STEP_SUMMARY + echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $GITHUB_STEP_SUMMARY fi ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg From 4332b62a6268e3093c957dfcbd652c5275228546 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 1 Jul 2023 16:39:21 +0100 Subject: [PATCH 11/33] Fix search focusing Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 22 ++++++++++----------- launcher/ui/dialogs/VersionSelectDialog.cpp | 3 ++- launcher/ui/widgets/JavaSettingsWidget.cpp | 3 ++- launcher/ui/widgets/VersionSelectWidget.cpp | 14 ++++++------- launcher/ui/widgets/VersionSelectWidget.h | 4 ++-- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 6e1ad1c04..f62fb8c47 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -30,9 +30,9 @@ #include "ui/widgets/PageContainer.h" #include "ui/widgets/VersionSelectWidget.h" -class LoaderPage : public VersionSelectWidget, public BasePage { +class InstallLoaderPage : public VersionSelectWidget, public BasePage { public: - LoaderPage(const QString& id, + InstallLoaderPage(const QString& id, const QString& icon, const QString& name, // "lightweight" loaders are independent to any game version @@ -86,9 +86,7 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q auto refreshButton = new QPushButton(tr("&Refresh"), this); connect(refreshButton, &QPushButton::pressed, this, [this] { - LoaderPage* page = dynamic_cast(m_container->selectedPage()); - Q_ASSERT(page != nullptr); - page->loadList(); + dynamic_cast(m_container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); @@ -106,18 +104,20 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q connect(m_container, &PageContainer::selectedPageChanged, this, [this](BasePage* previous, BasePage* selected) { updateAcceptButton(selected); }); updateAcceptButton(m_container->selectedPage()); + + dynamic_cast(m_container->selectedPage())->selectSearch(); } QList InstallLoaderDialog::getPages() { return { // Forge - new LoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile, this), + new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile, this), // Fabric - new LoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile, this), + new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile, this), // Quilt - new LoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile, this), + new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile, this), // LiteLoader - new LoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) + new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) }; } @@ -135,9 +135,7 @@ void InstallLoaderDialog::updateAcceptButton(const BasePage* page) void InstallLoaderDialog::done(int result) { if (result == Accepted) { - LoaderPage* page = dynamic_cast(m_container->selectedPage()); - Q_ASSERT(page != nullptr); - + auto* page = dynamic_cast(m_container->selectedPage()); if (page->selectedVersion()) { m_profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); m_profile->resolve(Net::Mode::Online); diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index 5feb70d20..dec85550f 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -55,7 +55,7 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, m_verticalLayout = new QVBoxLayout(this); m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); - m_versionWidget = new VersionSelectWidget(true, parent); + m_versionWidget = new VersionSelectWidget(parent); m_verticalLayout->addWidget(m_versionWidget); m_horizontalLayout = new QHBoxLayout(); @@ -123,6 +123,7 @@ int VersionSelectDialog::exec() { QDialog::open(); m_versionWidget->initialize(m_vlist); + m_versionWidget->selectSearch(); if(resizeOnColumn != -1) { m_versionWidget->setResizeOn(resizeOnColumn); diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index c94fdd8d5..d77e0fa00 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -46,7 +46,7 @@ void JavaSettingsWidget::setupUi() m_verticalLayout = new QVBoxLayout(this); m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); - m_versionWidget = new VersionSelectWidget(true, this); + m_versionWidget = new VersionSelectWidget(this); m_verticalLayout->addWidget(m_versionWidget); m_horizontalLayout = new QHBoxLayout(); @@ -126,6 +126,7 @@ void JavaSettingsWidget::setupUi() void JavaSettingsWidget::initialize() { m_versionWidget->initialize(APPLICATION->javalist().get()); + m_versionWidget->selectSearch(); m_versionWidget->setResizeOn(2); auto s = APPLICATION->settings(); // Memory diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index a956ddb3c..efc9c4124 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -11,10 +11,8 @@ #include "ui/dialogs/CustomMessageBox.h" -VersionSelectWidget::VersionSelectWidget(QWidget* parent) : VersionSelectWidget(false, parent) {} - -VersionSelectWidget::VersionSelectWidget(bool focusSearch, QWidget* parent) - : QWidget(parent), focusSearch(focusSearch) +VersionSelectWidget::VersionSelectWidget(QWidget* parent) + : QWidget(parent) { setObjectName(QStringLiteral("VersionSelectWidget")); verticalLayout = new QVBoxLayout(this); @@ -116,9 +114,6 @@ void VersionSelectWidget::initialize(BaseVersionList *vlist) listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); - if (focusSearch) - search->setFocus(); - if (!m_vlist->isLoaded()) { loadList(); @@ -210,6 +205,11 @@ void VersionSelectWidget::selectCurrent() } } +void VersionSelectWidget::selectSearch() +{ + search->setFocus(); +} + void VersionSelectWidget::selectRecommended() { auto idx = m_proxyModel->getRecommended(); diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index be4ba768d..a1b60d359 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -52,7 +52,6 @@ class VersionSelectWidget: public QWidget Q_OBJECT public: explicit VersionSelectWidget(QWidget *parent); - explicit VersionSelectWidget(bool focusSearch = false, QWidget *parent = 0); ~VersionSelectWidget(); //! loads the list if needed. @@ -65,6 +64,7 @@ public: BaseVersion::Ptr selectedVersion() const; void selectRecommended(); void selectCurrent(); + void selectSearch(); void setCurrentVersion(const QString & version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); @@ -74,6 +74,7 @@ public: void setEmptyErrorString(QString emptyErrorString); void setEmptyMode(VersionListView::EmptyMode mode); void setResizeOn(int column); + bool eventFilter(QObject* watched, QEvent* event) override; signals: @@ -98,7 +99,6 @@ private: int resizeOnColumn = 0; Task * loadTask; bool preselectedAlready = false; - bool focusSearch; QVBoxLayout *verticalLayout = nullptr; VersionListView *listView = nullptr; From 4cdf669154327b764ea2f7371e3d29f71d06daa7 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 1 Jul 2023 17:02:39 +0100 Subject: [PATCH 12/33] Modify "Change Version" to use "Install Loader" dialog Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 18 ++++++++++++++---- launcher/ui/dialogs/InstallLoaderDialog.h | 4 ++-- launcher/ui/pages/instance/VersionPage.cpp | 12 +++++++++++- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index f62fb8c47..74b3ea92b 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -74,7 +74,14 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { bool m_loaded = false; }; -InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, QWidget* parent) +InstallLoaderPage* pageCast(BasePage* page) +{ + auto result = dynamic_cast(page); + Q_ASSERT(result != nullptr); + return result; +} + +InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, const QString& uid, QWidget* parent) : QDialog(parent), m_profile(profile), m_container(new PageContainer(this)), m_buttons(new QDialogButtonBox(this)) { auto layout = new QVBoxLayout(this); @@ -86,7 +93,7 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q auto refreshButton = new QPushButton(tr("&Refresh"), this); connect(refreshButton, &QPushButton::pressed, this, [this] { - dynamic_cast(m_container->selectedPage())->loadList(); + pageCast(m_container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); @@ -105,7 +112,10 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q [this](BasePage* previous, BasePage* selected) { updateAcceptButton(selected); }); updateAcceptButton(m_container->selectedPage()); - dynamic_cast(m_container->selectedPage())->selectSearch(); + pageCast(m_container->selectedPage())->selectSearch(); + for (BasePage* page : m_container->getPages()) + if (page->id() == uid) + m_container->selectPage(page->id()); } QList InstallLoaderDialog::getPages() @@ -135,7 +145,7 @@ void InstallLoaderDialog::updateAcceptButton(const BasePage* page) void InstallLoaderDialog::done(int result) { if (result == Accepted) { - auto* page = dynamic_cast(m_container->selectedPage()); + auto* page = pageCast(m_container->selectedPage()); if (page->selectedVersion()) { m_profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); m_profile->resolve(Net::Mode::Online); diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index 6c8762dc0..24064eaa0 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -26,11 +26,11 @@ class PageContainer; class PackProfile; class QDialogButtonBox; -class InstallLoaderDialog : public QDialog, public BasePageProvider { +class InstallLoaderDialog final : public QDialog, public BasePageProvider { Q_OBJECT public: - explicit InstallLoaderDialog(std::shared_ptr instance, QWidget* parent = nullptr); + explicit InstallLoaderDialog(std::shared_ptr instance, const QString& uid = QString(), QWidget* parent = nullptr); QList getPages() override; QString dialogTitle() override; diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 53a710083..86ba5c276 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -432,6 +432,16 @@ void VersionPage::on_actionChange_version_triggered() return; } auto uid = list->uid(); + + // FIXME: this is still a horrible HACK. + if (uid == "net.minecraftforge" || uid == "com.mumfrey.liteloader" || uid == "net.fabricmc.fabric-loader" || + uid == "org.quiltmc.quilt-loader") { + InstallLoaderDialog dialog(m_inst->getPackProfile(), uid, this); + dialog.exec(); + m_container->refreshContainer(); + return; + } + VersionSelectDialog vselect(list.get(), tr("Change %1 version").arg(name), this); if (uid == "net.fabricmc.intermediary" || uid == "org.quiltmc.hashed") { @@ -485,7 +495,7 @@ void VersionPage::on_actionDownload_All_triggered() void VersionPage::on_actionInstall_Loader_triggered() { - InstallLoaderDialog dialog(m_inst->getPackProfile(), this); + InstallLoaderDialog dialog(m_inst->getPackProfile(), QString(), this); dialog.exec(); m_container->refreshContainer(); } From 284e374ae858d6784b6df48c83534dc6dc973747 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 1 Jul 2023 17:20:43 +0100 Subject: [PATCH 13/33] Nop Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 10 ---------- launcher/ui/dialogs/InstallLoaderDialog.h | 1 - 2 files changed, 11 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 74b3ea92b..31307ee15 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -108,10 +108,6 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c setWindowTitle(dialogTitle()); resize(650, 400); - connect(m_container, &PageContainer::selectedPageChanged, this, - [this](BasePage* previous, BasePage* selected) { updateAcceptButton(selected); }); - updateAcceptButton(m_container->selectedPage()); - pageCast(m_container->selectedPage())->selectSearch(); for (BasePage* page : m_container->getPages()) if (page->id() == uid) @@ -136,12 +132,6 @@ QString InstallLoaderDialog::dialogTitle() return tr("Install Loader"); } -void InstallLoaderDialog::updateAcceptButton(const BasePage* page) -{ - auto installed = !m_profile->getComponentVersion(page->id()).isNull(); - m_buttons->button(QDialogButtonBox::Ok)->setText(installed ? tr("&Update") : tr("&Install")); -} - void InstallLoaderDialog::done(int result) { if (result == Accepted) { diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index 24064eaa0..09d847778 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -35,7 +35,6 @@ class InstallLoaderDialog final : public QDialog, public BasePageProvider { QList getPages() override; QString dialogTitle() override; - void updateAcceptButton(const BasePage* page); void done(int result) override; private: From 9f9b5254a239d6359d199c33fa5d966e1f4d6e63 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 1 Jul 2023 19:32:04 +0100 Subject: [PATCH 14/33] Double-click to install/change version Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 33 +++++++++++---------- launcher/ui/dialogs/VersionSelectDialog.cpp | 5 ++-- launcher/ui/widgets/VersionSelectWidget.cpp | 5 ++++ launcher/ui/widgets/VersionSelectWidget.h | 1 + 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 31307ee15..acef60c69 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -33,13 +33,12 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { public: InstallLoaderPage(const QString& id, - const QString& icon, - const QString& name, - // "lightweight" loaders are independent to any game version - const bool lightweight, - const std::shared_ptr profile, - QWidget* parent = nullptr) - : VersionSelectWidget(parent), m_id(id), m_icon(icon), m_name(name) + const QString& icon, + const QString& name, + // "lightweight" loaders are independent to any game version + const bool lightweight, + const std::shared_ptr profile) + : VersionSelectWidget(nullptr), m_id(id), m_icon(icon), m_name(name) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); @@ -67,6 +66,12 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { m_loaded = true; } + void setParentContainer(BasePageContainer* container) override + { + auto dialog = dynamic_cast(dynamic_cast(container)->parent()); + connect(view(), &QAbstractItemView::doubleClicked, dialog, &QDialog::accept); + } + private: const QString m_id; const QString m_icon; @@ -82,7 +87,7 @@ InstallLoaderPage* pageCast(BasePage* page) } InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, const QString& uid, QWidget* parent) - : QDialog(parent), m_profile(profile), m_container(new PageContainer(this)), m_buttons(new QDialogButtonBox(this)) + : QDialog(parent), m_profile(profile), m_container(new PageContainer(this, QString(), this)), m_buttons(new QDialogButtonBox(this)) { auto layout = new QVBoxLayout(this); @@ -92,9 +97,7 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c auto buttonLayout = new QHBoxLayout(this); auto refreshButton = new QPushButton(tr("&Refresh"), this); - connect(refreshButton, &QPushButton::pressed, this, [this] { - pageCast(m_container->selectedPage())->loadList(); - }); + connect(refreshButton, &QPushButton::pressed, this, [this] { pageCast(m_container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); m_buttons->setOrientation(Qt::Horizontal); @@ -117,13 +120,13 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c QList InstallLoaderDialog::getPages() { return { // Forge - new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile, this), + new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile), // Fabric - new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile, this), + new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile), // Quilt - new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile, this), + new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile), // LiteLoader - new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) + new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile) }; } diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index dec85550f..e45787e4a 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -75,8 +75,9 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, retranslate(); - QObject::connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - QObject::connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(m_versionWidget->view(), &QAbstractItemView::doubleClicked, this, &QDialog::accept); + connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); QMetaObject::connectSlotsByName(this); setWindowModality(Qt::WindowModal); diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index efc9c4124..f20dad711 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -210,6 +210,11 @@ void VersionSelectWidget::selectSearch() search->setFocus(); } +VersionListView* VersionSelectWidget::view() +{ + return listView; +} + void VersionSelectWidget::selectRecommended() { auto idx = m_proxyModel->getRecommended(); diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index a1b60d359..624d9a232 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -65,6 +65,7 @@ public: void selectRecommended(); void selectCurrent(); void selectSearch(); + VersionListView* view(); void setCurrentVersion(const QString & version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); From 6cc3587da2a87c87d37f205fd39a31a5a136814a Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 1 Jul 2023 20:10:38 +0100 Subject: [PATCH 15/33] Disable as intended Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/VersionPage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 86ba5c276..31e0b9b37 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -274,8 +274,9 @@ void VersionPage::updateButtons(int row) ui->actionAdd_Empty->setEnabled(controlsEnabled); ui->actionImport_Components->setEnabled(controlsEnabled); ui->actionReload->setEnabled(controlsEnabled); - ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled); + ui->actionInstall_Loader->setEnabled(controlsEnabled); ui->actionAdd_to_Minecraft_jar->setEnabled(controlsEnabled); + ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled); ui->actionAdd_Agents->setEnabled(controlsEnabled); } From 0e5c37768084cf0772ca2598b4554bf262cb581b Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 3 Jul 2023 17:32:59 +0100 Subject: [PATCH 16/33] Various tweaks Signed-off-by: TheKodeToad --- .../multimc/128x128/instances/forge.png | Bin 0 -> 3229 bytes launcher/resources/multimc/multimc.qrc | 2 +- .../multimc/scalable/instances/forge.svg | 43 ---------- launcher/ui/dialogs/InstallLoaderDialog.cpp | 78 +++++++++++------- launcher/ui/dialogs/InstallLoaderDialog.h | 7 +- launcher/ui/widgets/PageContainer.cpp | 2 +- launcher/ui/widgets/PageContainer.h | 2 +- 7 files changed, 53 insertions(+), 81 deletions(-) create mode 100644 launcher/resources/multimc/128x128/instances/forge.png delete mode 100644 launcher/resources/multimc/scalable/instances/forge.svg diff --git a/launcher/resources/multimc/128x128/instances/forge.png b/launcher/resources/multimc/128x128/instances/forge.png new file mode 100644 index 0000000000000000000000000000000000000000..d8ff79a537bedb9b16ed0f2824580cd8037f5847 GIT binary patch literal 3229 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4mJh`hQoG=rx_R+I14-?iy0U=i$IuB`}}=3 z1_lPn64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq!<`@v^-rLLn`LHom&|b za+T?L{h1yfh2MM|_45*Eq#VTGPd*@!LrI4A1-irj+!wcXzCfpV$0PN_%Jf{CN7l;`4i-&nsTn z`TRnm?g9bs{?`m5c?+2Y_(U5DRxq?Uvnt4FF+2=lOjVxSCCpEjY^*eHIu*x%B^k4Gg%fCNQ-#glR+P-+gi4TGd4i_Fcyzz_Tw~o$U z_qpUzRhZthy*qau&tCU9Vg2nNKP$fN zv}q0E+!(<$(SxZogsn5A&21uw(nb-Xl_EwnWxn$E=Faa_4Kgw5QkZy3Ve-if8d-P4 zxn}P1oL%pmE5gNkL`ZXS>NZnGRsK^SKD}9bW9AOA#CrbJEkd~kTei2Z?G=6XN_zL* zWAVIw9<;ZAB%VH;WRD%nvoY~ zFlqJrE!OM;ovIN(u34>#-zoAr-8b3P!~e(c3Z>7_-oCT{{x!+ax4OkC*uvVlAWNr9*Qr%fG5fx0yCikGeJ!=(4AGbxF@J+> z>CG-6p^Xs;7%Dr1B6@GxF*7C^j-xZ6NZEI{bxig{GTHf8Swm*2K zcwl7c;fS5KacuW?1$Ss}zISBZlCKh9-xwUz3Z1@B=F#8Uy#c|q4?9VHTalk}U3Q(Rp#l*I%Z) zq%|g=-dJ^c|HhhJC6yq_%QJVWY?v7r@7CtEN2TG6m*_jkk6 zb4G7|eDT%@)lxGmJ;_i%KW_WWw;BuiL&B~q7+LWhKR4&O6&FJrTZ@JWm&#j@V_#N8 z+}ZozTG+Mh(EaP&HuF6DZ@>86nGjm4o2FaEZeILpN8cs3#mY^2DbJHW^+?pzy|4(; zN}KPVnWxs$KHIzh_K(Wf?=2ltLwS|Nk0|edA$L9S*1_$CAMc(>Y4kmNcE^lqeV^^) zoC_`}xaCjzP+@c9R*8LDkG@sS%9JEz(S zCvxb&T-U>c&I$S1heJh_3TIluJ^y&~($snj z%UjA9&T}7b<2!bxGqIq&^qEO`X|AkWo2%536wzj}1=%TGK)nSek5;jz0{Wy_Il0g{3DA`Wre-I!nRn9fq}24m@AcEJ7V?v zMW+h()if|LPSFzWo16Cjp7rhE-CK^nU}b2C&)Z=Bq$@q)yEc#Z+O{cw;?70I&XYO6 zC`eq1B|x*(JY=o%v}s~JeT^4PT{u3pRG(MwoRQ}9q9E+`Wi}<2imDe0VXtRP*iF0o zYsYt2SfuuB!(#Sby9;k!Z1{TsvKR{>MrimHhinosYl%t~u}`kG;Bj zSMtq6H!E^)bsJoq{4h;?-IC&6>+U9@=qHs$4AAcYh!IQhvkYUn*-qzp*Y5 zkrpb?itV$KxZ=5>vy*euz4(JCrq^4q=O|7JODcI$u(pcJy`85$Xr;@WRcE90KM2@X zTcx@9Tv^3aYN)|DO=m`D=Hx?LwH7a3%KDp6=IEE58$05S_WNHxSDjq;L}Z7B^`q8s zu}8P`_h*KN9okjV(o^B}+Nbtt0?Uu%D<(z={@xXq8WMUv>E9*O8xwX2zt@RA@ZwT= z_9JoS3+JVc#rO60cJ4Nj6IT%6`0%k^IzswpjsVk--xW#Wm#o%4W1II|k@unC#T_%I zHD*pew9(*ID4X!V!n^yG3w3Sg7r1_ERPLA|-My%q-$d*5#e;nFbN`ELuim)P%G5`A z&03wpjQ3$Xc3Na^*&m^F^p@`J2_G)Xok%JAQC0cib1dhJ>-|4HRnyX(c%-c)G}VIw z|E&74F|PX)28i)erj?vlc2cq z^v;OAN&*}kY#+wX;QXI;SX*m#q4xTKx0`<0$jR)Aw4B5FC5j(*hYgFku5K+|v2x|>EpO%qWN@)tM_X9mI(+sjXPw=|2Df literal 0 HcmV?d00001 diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index 907fbb5d3..4a407d95a 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -348,9 +348,9 @@ scalable/launch.svg scalable/server.svg - scalable/instances/forge.svg scalable/instances/quiltmc.svg 22x22/fabricmc-small.png + 128x128/instances/forge.png 128x128/instances/fabricmc.png 128x128/instances/liteloader.png diff --git a/launcher/resources/multimc/scalable/instances/forge.svg b/launcher/resources/multimc/scalable/instances/forge.svg deleted file mode 100644 index ea402c5b2..000000000 --- a/launcher/resources/multimc/scalable/instances/forge.svg +++ /dev/null @@ -1,43 +0,0 @@ - - diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index acef60c69..31d6f9ab5 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -38,7 +38,7 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { // "lightweight" loaders are independent to any game version const bool lightweight, const std::shared_ptr profile) - : VersionSelectWidget(nullptr), m_id(id), m_icon(icon), m_name(name) + : VersionSelectWidget(nullptr), uid(id), iconName(icon), name(name) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); @@ -49,21 +49,21 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { setCurrentVersion(currentVersion); } - QString id() const override { return m_id; } - QString displayName() const override { return m_name; } - QIcon icon() const override { return APPLICATION->getThemedIcon(m_icon); } + QString id() const override { return uid; } + QString displayName() const override { return name; } + QIcon icon() const override { return APPLICATION->getThemedIcon(iconName); } void openedImpl() override { - if (m_loaded) + if (loaded) return; - const auto versions = APPLICATION->metadataIndex()->get(m_id); + const auto versions = APPLICATION->metadataIndex()->get(uid); if (!versions) return; initialize(versions.get()); - m_loaded = true; + loaded = true; } void setParentContainer(BasePageContainer* container) override @@ -73,13 +73,13 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { } private: - const QString m_id; - const QString m_icon; - const QString m_name; - bool m_loaded = false; + const QString uid; + const QString iconName; + const QString name; + bool loaded = false; }; -InstallLoaderPage* pageCast(BasePage* page) +static InstallLoaderPage* pageCast(BasePage* page) { auto result = dynamic_cast(page); Q_ASSERT(result != nullptr); @@ -87,46 +87,55 @@ InstallLoaderPage* pageCast(BasePage* page) } InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, const QString& uid, QWidget* parent) - : QDialog(parent), m_profile(profile), m_container(new PageContainer(this, QString(), this)), m_buttons(new QDialogButtonBox(this)) + : QDialog(parent), profile(std::move(profile)), container(new PageContainer(this, QString(), this)), buttons(new QDialogButtonBox(this)) { auto layout = new QVBoxLayout(this); - m_container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); - layout->addWidget(m_container); + container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + layout->addWidget(container); auto buttonLayout = new QHBoxLayout(this); auto refreshButton = new QPushButton(tr("&Refresh"), this); - connect(refreshButton, &QPushButton::pressed, this, [this] { pageCast(m_container->selectedPage())->loadList(); }); + connect(refreshButton, &QPushButton::pressed, this, [this] { pageCast(container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); - m_buttons->setOrientation(Qt::Horizontal); - m_buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - connect(m_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); - buttonLayout->addWidget(m_buttons); + buttons->setOrientation(Qt::Horizontal); + buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + buttonLayout->addWidget(buttons); layout->addLayout(buttonLayout); setWindowTitle(dialogTitle()); - resize(650, 400); + setWindowModality(Qt::WindowModal); + resize(520, 347); - pageCast(m_container->selectedPage())->selectSearch(); - for (BasePage* page : m_container->getPages()) + for (BasePage* page : container->getPages()) { if (page->id() == uid) - m_container->selectPage(page->id()); + container->selectPage(page->id()); + + connect(pageCast(page), &VersionSelectWidget::selectedVersionChanged, this, [this, page] { + if (page->id() == container->selectedPage()->id()) + validate(container->selectedPage()); + }); + } + connect(container, &PageContainer::selectedPageChanged, this, [this](BasePage* previous, BasePage* current) { validate(current); }); + pageCast(container->selectedPage())->selectSearch(); + validate(container->selectedPage()); } QList InstallLoaderDialog::getPages() { return { // Forge - new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile), + new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, profile), // Fabric - new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile), + new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, profile), // Quilt - new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile), + new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, profile), // LiteLoader - new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile) + new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, profile) }; } @@ -135,13 +144,18 @@ QString InstallLoaderDialog::dialogTitle() return tr("Install Loader"); } +void InstallLoaderDialog::validate(BasePage* page) +{ + buttons->button(QDialogButtonBox::Ok)->setEnabled(pageCast(page)->selectedVersion() != nullptr); +} + void InstallLoaderDialog::done(int result) { if (result == Accepted) { - auto* page = pageCast(m_container->selectedPage()); + auto* page = pageCast(container->selectedPage()); if (page->selectedVersion()) { - m_profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); - m_profile->resolve(Net::Mode::Online); + profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); + profile->resolve(Net::Mode::Online); } } diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index 09d847778..cdcba2b96 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -35,10 +35,11 @@ class InstallLoaderDialog final : public QDialog, public BasePageProvider { QList getPages() override; QString dialogTitle() override; + void validate(BasePage* page); void done(int result) override; private: - std::shared_ptr m_profile; - PageContainer* m_container; - QDialogButtonBox* m_buttons; + std::shared_ptr profile; + PageContainer* container; + QDialogButtonBox* buttons; }; diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 0a8a0544c..dbbed36a7 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -147,7 +147,7 @@ BasePage* PageContainer::selectedPage() const return m_currentPage; } -const QList PageContainer::getPages() const +const QList& PageContainer::getPages() const { return m_model->pages(); } diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index bb365c826..eac597232 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -82,7 +82,7 @@ public: bool selectPage(QString pageId) override; BasePage* selectedPage() const override; BasePage* getPage(QString pageId) override; - const QList getPages() const; + const QList& getPages() const; void refreshContainer() override; virtual void setParentContainer(BasePageContainer * container) From 64c591b234cec2519d8a04b32d4b6e85dcf204da Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 3 Jul 2023 20:48:37 +0100 Subject: [PATCH 17/33] Better parent version filtering; handle old fabric :P Signed-off-by: TheKodeToad --- launcher/Filter.cpp | 6 ++++++ launcher/Filter.h | 10 ++++++++++ launcher/ui/dialogs/InstallLoaderDialog.cpp | 17 +++++++++-------- launcher/ui/dialogs/VersionSelectDialog.cpp | 4 ++++ launcher/ui/dialogs/VersionSelectDialog.h | 1 + launcher/ui/pages/instance/VersionPage.cpp | 12 ++---------- launcher/ui/widgets/VersionSelectWidget.cpp | 9 +++++++-- launcher/ui/widgets/VersionSelectWidget.h | 1 + 8 files changed, 40 insertions(+), 20 deletions(-) diff --git a/launcher/Filter.cpp b/launcher/Filter.cpp index c65ca0ceb..f95305977 100644 --- a/launcher/Filter.cpp +++ b/launcher/Filter.cpp @@ -16,6 +16,12 @@ bool ExactFilter::accepts(const QString& value) return value == pattern; } +ExactIfPresentFilter::ExactIfPresentFilter(const QString& pattern) : pattern(pattern) {} +bool ExactIfPresentFilter::accepts(const QString& value) +{ + return value.isEmpty() || value == pattern; +} + RegexpFilter::RegexpFilter(const QString& regexp, bool invert) :invert(invert) { diff --git a/launcher/Filter.h b/launcher/Filter.h index b55067acb..d3cee2d8d 100644 --- a/launcher/Filter.h +++ b/launcher/Filter.h @@ -30,6 +30,16 @@ private: QString pattern; }; +class ExactIfPresentFilter: public Filter +{ + public: + ExactIfPresentFilter(const QString& pattern); + ~ExactIfPresentFilter() override = default; + bool accepts(const QString& value) override; + private: + QString pattern; +}; + class RegexpFilter: public Filter { public: diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 31d6f9ab5..bab5b8350 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -35,15 +35,16 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { InstallLoaderPage(const QString& id, const QString& icon, const QString& name, - // "lightweight" loaders are independent to any game version - const bool lightweight, + const Version& oldestVersion, const std::shared_ptr profile) : VersionSelectWidget(nullptr), uid(id), iconName(icon), name(name) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); - if (!lightweight) - setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); + setExactIfPresentFilter(BaseVersionList::ParentVersionRole, minecraftVersion); + + if (oldestVersion != Version() && Version(minecraftVersion) < oldestVersion) + setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); if (const QString currentVersion = profile->getComponentVersion(id); !currentVersion.isNull()) setCurrentVersion(currentVersion); @@ -129,13 +130,13 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c QList InstallLoaderDialog::getPages() { return { // Forge - new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, profile), + new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), {}, profile), // Fabric - new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, profile), + new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), Version("1.14"), profile), // Quilt - new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, profile), + new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), Version("1.14"), profile), // LiteLoader - new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, profile) + new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), {}, profile) }; } diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index e45787e4a..9fa3c90f4 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -152,6 +152,10 @@ void VersionSelectDialog::setExactFilter(BaseVersionList::ModelRoles role, QStri m_versionWidget->setExactFilter(role, filter); } +void VersionSelectDialog::setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter) { + m_versionWidget->setExactIfPresentFilter(role, filter); +} + void VersionSelectDialog::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) { m_versionWidget->setFuzzyFilter(role, filter); diff --git a/launcher/ui/dialogs/VersionSelectDialog.h b/launcher/ui/dialogs/VersionSelectDialog.h index 18a50cdb0..c20a9ed58 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.h +++ b/launcher/ui/dialogs/VersionSelectDialog.h @@ -49,6 +49,7 @@ public: void setCurrentVersion(const QString & version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); void setExactFilter(BaseVersionList::ModelRoles role, QString filter); + void setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter); void setEmptyString(QString emptyString); void setEmptyErrorString(QString emptyErrorString); void setResizeOn(int column); diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 31e0b9b37..a8e6e9484 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -434,22 +434,14 @@ void VersionPage::on_actionChange_version_triggered() } auto uid = list->uid(); - // FIXME: this is still a horrible HACK. - if (uid == "net.minecraftforge" || uid == "com.mumfrey.liteloader" || uid == "net.fabricmc.fabric-loader" || - uid == "org.quiltmc.quilt-loader") { - InstallLoaderDialog dialog(m_inst->getPackProfile(), uid, this); - dialog.exec(); - m_container->refreshContainer(); - return; - } - VersionSelectDialog vselect(list.get(), tr("Change %1 version").arg(name), this); if (uid == "net.fabricmc.intermediary" || uid == "org.quiltmc.hashed") { vselect.setEmptyString(tr("No intermediary mappings versions are currently available.")); vselect.setEmptyErrorString(tr("Couldn't load or download the intermediary mappings version lists!")); - vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); } + vselect.setExactIfPresentFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); + auto currentVersion = patch->getVersion(); if(!currentVersion.isEmpty()) { diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index f20dad711..2b22a4a92 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -238,14 +238,19 @@ BaseVersion::Ptr VersionSelectWidget::selectedVersion() const return variant.value(); } +void VersionSelectWidget::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) +{ + m_proxyModel->setFilter(role, new ContainsFilter(filter)); +} + void VersionSelectWidget::setExactFilter(BaseVersionList::ModelRoles role, QString filter) { m_proxyModel->setFilter(role, new ExactFilter(filter)); } -void VersionSelectWidget::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) +void VersionSelectWidget::setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter) { - m_proxyModel->setFilter(role, new ContainsFilter(filter)); + m_proxyModel->setFilter(role, new ExactIfPresentFilter(filter)); } void VersionSelectWidget::setFilter(BaseVersionList::ModelRoles role, Filter *filter) diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index 624d9a232..598e10591 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -70,6 +70,7 @@ public: void setCurrentVersion(const QString & version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); void setExactFilter(BaseVersionList::ModelRoles role, QString filter); + void setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter); void setFilter(BaseVersionList::ModelRoles role, Filter *filter); void setEmptyString(QString emptyString); void setEmptyErrorString(QString emptyErrorString); From f9578066d6b9d2813e05ad6501935304a787ce52 Mon Sep 17 00:00:00 2001 From: leo78913 Date: Wed, 28 Jun 2023 17:30:11 -0300 Subject: [PATCH 18/33] make "browse" buttons and java pages more consistent Signed-off-by: leo78913 --- launcher/ui/pages/global/ExternalToolsPage.ui | 8 +- launcher/ui/pages/global/JavaPage.ui | 222 +++++++++--------- launcher/ui/pages/global/LauncherPage.ui | 8 +- .../ui/pages/instance/InstanceSettingsPage.ui | 62 ++--- 4 files changed, 150 insertions(+), 150 deletions(-) diff --git a/launcher/ui/pages/global/ExternalToolsPage.ui b/launcher/ui/pages/global/ExternalToolsPage.ui index 3643094df..47c77842a 100644 --- a/launcher/ui/pages/global/ExternalToolsPage.ui +++ b/launcher/ui/pages/global/ExternalToolsPage.ui @@ -47,7 +47,7 @@ - ... + Browse @@ -84,7 +84,7 @@ - ... + Browse @@ -121,7 +121,7 @@ - ... + Browse @@ -166,7 +166,7 @@ - ... + Browse diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index 6749cbe41..85afd5d65 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -160,117 +160,7 @@ Java Runtime - - - - - 0 - 0 - - - - &Auto-detect... - - - - - - - - 0 - 0 - - - - JVM arguments: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - &Java path: - - - javaPathTextBox - - - - - - - - 0 - 0 - - - - &Test - - - - - - - - - - - - - 0 - 0 - - - - - 28 - 16777215 - - - - ... - - - - - - - - - - 0 - 0 - - - - If enabled, the launcher will not check if an instance is compatible with the selected Java version. - - - &Skip Java compatibility checks - - - - - - - If enabled, the launcher will not prompt you to choose a Java version if one isn't found. - - - Skip Java &Wizard - - - - + true @@ -289,6 +179,114 @@ + + + + + 0 + 0 + + + + If enabled, the launcher will not check if an instance is compatible with the selected Java version. + + + &Skip Java compatibility checks + + + + + + + + + + 0 + 0 + + + + &Auto-detect... + + + + + + + + 0 + 0 + + + + &Test + + + + + + + + + + 0 + 0 + + + + JVM arguments: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + + + 0 + 0 + + + + &Java path: + + + javaPathTextBox + + + + + + + + + + + 0 + 0 + + + + Browse + + + + + + + + + If enabled, the launcher will not prompt you to choose a Java version if one isn't found. + + + Skip Java &Wizard + + + @@ -317,8 +315,6 @@ permGenSpinBox javaBrowseBtn javaPathTextBox - javaDetectBtn - javaTestBtn tabWidget diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index d9116bfcf..7c80c3af1 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -99,7 +99,7 @@ - ... + Browse @@ -109,7 +109,7 @@ - ... + Browse @@ -126,14 +126,14 @@ - ... + Browse - ... + Browse diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 8427965de..277deb2ae 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -61,31 +61,7 @@ false - - - - - - - Auto-detect... - - - - - - - Browse... - - - - - - - Test - - - - + If enabled, the launcher will not check if an instance is compatible with the selected Java version. @@ -95,6 +71,38 @@ + + + + + + + + + Browse + + + + + + + + + + + Auto-detect... + + + + + + + Test + + + + + @@ -674,10 +682,6 @@ openGlobalJavaSettingsButton settingsTabs javaSettingsGroupBox - javaPathTextBox - javaDetectBtn - javaBrowseBtn - javaTestBtn memoryGroupBox minMemSpinBox maxMemSpinBox From e8dc1564b67b9fa64ddae10ad3d0e076f9710787 Mon Sep 17 00:00:00 2001 From: leo78913 Date: Mon, 3 Jul 2023 12:37:27 -0300 Subject: [PATCH 19/33] add _kde_side_panel_view property to page container With this the sidebars look better with the breeze theme Signed-off-by: leo78913 --- launcher/ui/widgets/PageContainer_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/widgets/PageContainer_p.h b/launcher/ui/widgets/PageContainer_p.h index da1a66f46..d469019cf 100644 --- a/launcher/ui/widgets/PageContainer_p.h +++ b/launcher/ui/widgets/PageContainer_p.h @@ -103,6 +103,7 @@ public: setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); setItemDelegate(new PageViewDelegate(this)); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setProperty("_kde_side_panel_view", true); } virtual QSize sizeHint() const From 3154c2644ab51314d979dffef75a1b66e4113281 Mon Sep 17 00:00:00 2001 From: leo78913 Date: Fri, 7 Jul 2023 10:29:11 -0300 Subject: [PATCH 20/33] enable tear off on widebar context menu Signed-off-by: leo78913 --- launcher/ui/widgets/WideBar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index ac34e3aaa..ab73b7c97 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -195,8 +195,10 @@ static void copyAction(QAction* from, QAction* to) void WideBar::showVisibilityMenu(QPoint const& position) { - if (!m_bar_menu) + if (!m_bar_menu) { m_bar_menu = std::make_unique(this); + m_bar_menu->setTearOffEnabled(true); + } if (m_menu_state == MenuState::Dirty) { for (auto* old_action : m_bar_menu->actions()) From d1cceac7d129c83e41bc3db4700c720b412c88bc Mon Sep 17 00:00:00 2001 From: leo78913 Date: Fri, 7 Jul 2023 12:36:57 -0300 Subject: [PATCH 21/33] disable hiding enable and name columns on folder models Signed-off-by: leo78913 --- launcher/minecraft/mod/ModFolderModel.cpp | 1 + launcher/minecraft/mod/ResourceFolderModel.cpp | 2 ++ launcher/minecraft/mod/ResourceFolderModel.h | 1 + launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +- launcher/minecraft/mod/TexturePackFolderModel.cpp | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index af98d8348..2db454e38 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -61,6 +61,7 @@ ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER}; m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents}; + m_columnsHideable = { false, true, false, true, true, true }; } QVariant ModFolderModel::data(const QModelIndex &index, int role) const diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 7700fd36b..18b91d4d3 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -550,6 +550,8 @@ QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree) menu->addSeparator()->setText(tr("Show / Hide Columns")); for (int col = 0; col < columnCount(); ++col) { + // Skip creating actions for columns that should not be hidden + if (!m_columnsHideable.at(col)) continue; auto act = new QAction(menu); setupHeaderAction(act, col); diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index eb1d7c4f6..bf3febcba 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -202,6 +202,7 @@ class ResourceFolderModel : public QAbstractListModel { QStringList m_column_names = {"Enable", "Name", "Last Modified"}; QStringList m_column_names_translated = {tr("Enable"), tr("Name"), tr("Last Modified")}; QList m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents }; + QList m_columnsHideable = { false, false, true }; bool m_can_interact = true; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 41455599b..c8770d54f 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -54,7 +54,7 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstanc 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::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents }; - + m_columnsHideable = { false, true, false, true, true }; } QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index 531a70232..28fe0a46a 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -49,6 +49,7 @@ TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE }; m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents}; + m_columnsHideable = { false, true, false, true }; } From 1208300ddfc03b409dca7a3b1b0bf5ab8715ba1a Mon Sep 17 00:00:00 2001 From: leo78913 Date: Wed, 12 Jul 2023 10:57:30 -0300 Subject: [PATCH 22/33] i forgor to change skin upload browse button Signed-off-by: leo78913 --- launcher/ui/dialogs/SkinUploadDialog.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/SkinUploadDialog.ui b/launcher/ui/dialogs/SkinUploadDialog.ui index c7b166455..2c81a7fed 100644 --- a/launcher/ui/dialogs/SkinUploadDialog.ui +++ b/launcher/ui/dialogs/SkinUploadDialog.ui @@ -42,7 +42,7 @@ - ... + Browse From 8705e88e91959f7058902dd058d63bfd36f73cde Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 21 Jul 2023 11:19:55 +0100 Subject: [PATCH 23/33] Fix build on Windows Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 764cb0f2f..9841a72e0 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1079,7 +1079,6 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ScrollMessageBox.ui ui/dialogs/BlockedModsDialog.ui ui/dialogs/ChooseProviderDialog.ui - ui/dialogs/InstallLoaderDialog.ui ) qt_add_resources(LAUNCHER_RESOURCES From 40c614b3a579dd7435f917cf60289712190a379b Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Aug 2023 20:23:09 +0100 Subject: [PATCH 24/33] Pressed -> Clicked (doh) Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index bab5b8350..0b65882ef 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -98,7 +98,7 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c auto buttonLayout = new QHBoxLayout(this); auto refreshButton = new QPushButton(tr("&Refresh"), this); - connect(refreshButton, &QPushButton::pressed, this, [this] { pageCast(container->selectedPage())->loadList(); }); + connect(refreshButton, &QPushButton::clicked, this, [this] { pageCast(container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); buttons->setOrientation(Qt::Horizontal); From 8b3c465a50e6be2a09c3968f1fd1e91b0428cbb0 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Aug 2023 20:24:15 +0100 Subject: [PATCH 25/33] Use protected inheritance for BasePageProvider Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index cdcba2b96..86cb3bdd2 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -26,7 +26,7 @@ class PageContainer; class PackProfile; class QDialogButtonBox; -class InstallLoaderDialog final : public QDialog, public BasePageProvider { +class InstallLoaderDialog final : public QDialog, protected BasePageProvider { Q_OBJECT public: From 1bafa36c17604f6faa23f25b9ab61a46ed0de753 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Aug 2023 20:32:23 +0100 Subject: [PATCH 26/33] icon -> iconName Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 0b65882ef..6302cadbc 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -33,11 +33,11 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { public: InstallLoaderPage(const QString& id, - const QString& icon, + const QString& iconName, const QString& name, const Version& oldestVersion, const std::shared_ptr profile) - : VersionSelectWidget(nullptr), uid(id), iconName(icon), name(name) + : VersionSelectWidget(nullptr), uid(id), iconName(iconName), name(name) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); From 99fd1e622c4ab0218c206abed5876dbb273f5110 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 6 Aug 2023 17:43:30 +0200 Subject: [PATCH 27/33] chore: replace fabricmc icons with SVG Signed-off-by: Sefa Eyeoglu --- .../multimc/128x128/instances/fabricmc.png | Bin 4839 -> 0 bytes .../multimc/22x22/fabricmc-small.png | Bin 5672 -> 0 bytes launcher/resources/multimc/multimc.qrc | 3 +- .../multimc/scalable/instances/fabricmc.svg | 71 ++++++++++++++++++ launcher/ui/dialogs/InstallLoaderDialog.cpp | 2 +- 5 files changed, 73 insertions(+), 3 deletions(-) delete mode 100644 launcher/resources/multimc/128x128/instances/fabricmc.png delete mode 100644 launcher/resources/multimc/22x22/fabricmc-small.png create mode 100644 launcher/resources/multimc/scalable/instances/fabricmc.svg diff --git a/launcher/resources/multimc/128x128/instances/fabricmc.png b/launcher/resources/multimc/128x128/instances/fabricmc.png deleted file mode 100644 index c78543aeebf2b630810d2f5c8bd4d58ea6949ef7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4839 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 Mp00i_>zopr0Ll1@YXATM diff --git a/launcher/resources/multimc/22x22/fabricmc-small.png b/launcher/resources/multimc/22x22/fabricmc-small.png deleted file mode 100644 index e21ae9e88b7cfb9b26b3a81725bea57759d63846..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5672 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 SJD!t4BW9kielF{r5}E+3v=b-* diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index 4a407d95a..bdf3495be 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -349,9 +349,8 @@ scalable/server.svg scalable/instances/quiltmc.svg - 22x22/fabricmc-small.png + scalable/instances/fabricmc.svg 128x128/instances/forge.png - 128x128/instances/fabricmc.png 128x128/instances/liteloader.png diff --git a/launcher/resources/multimc/scalable/instances/fabricmc.svg b/launcher/resources/multimc/scalable/instances/fabricmc.svg new file mode 100644 index 000000000..7bfc75487 --- /dev/null +++ b/launcher/resources/multimc/scalable/instances/fabricmc.svg @@ -0,0 +1,71 @@ + + + + diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 6302cadbc..840a328f3 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -132,7 +132,7 @@ QList InstallLoaderDialog::getPages() return { // Forge new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), {}, profile), // Fabric - new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), Version("1.14"), profile), + new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc", tr("Fabric"), Version("1.14"), profile), // Quilt new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), Version("1.14"), profile), // LiteLoader From 9a9a4fcfd462f5d269e533713307abfb4b01bcf4 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 6 Aug 2023 13:16:30 -0700 Subject: [PATCH 28/33] Apply suggestions from code review Co-authored-by: Sefa Eyeoglu Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fa6f0f61b..9bffe2a1f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ on: description: Private key for AppImage signing required: false GPG_PRIVATE_KEY_ID: - description: ID for the GPG_PRIVATE_KEY, to select the signign key + description: ID for the GPG_PRIVATE_KEY, to select the signing key required: false jobs: From 8731f4ba275d6a0be44eb7cb1f0ad09a85cf4d16 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 10 Aug 2023 12:24:33 +0200 Subject: [PATCH 29/33] chore: add comment about _kde_side_panel_view Signed-off-by: Sefa Eyeoglu --- launcher/ui/widgets/PageContainer_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/widgets/PageContainer_p.h b/launcher/ui/widgets/PageContainer_p.h index d469019cf..8bf26618f 100644 --- a/launcher/ui/widgets/PageContainer_p.h +++ b/launcher/ui/widgets/PageContainer_p.h @@ -103,6 +103,7 @@ public: setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); setItemDelegate(new PageViewDelegate(this)); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + // Adjust margins when using Breeze theme setProperty("_kde_side_panel_view", true); } From d67277a668410e46a86870b3f9ab6bfdb90b4be4 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 10 Aug 2023 20:18:16 +0200 Subject: [PATCH 30/33] chore: replace LiteLoader logo with high quality version Signed-off-by: Sefa Eyeoglu --- .../multimc/128x128/instances/liteloader.png | Bin 20337 -> 7619 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/launcher/resources/multimc/128x128/instances/liteloader.png b/launcher/resources/multimc/128x128/instances/liteloader.png index 88295e6448fdea083a04969c0e2cc7eae0fbc259..646217de03371fcbddd6903ebbe10181a7a4e8e3 100644 GIT binary patch literal 7619 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 VFM4cZCJYP=44$rjF6*2UngBize}n)4 literal 20337 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 tWH3oAU^(dE^0 Date: Thu, 10 Aug 2023 20:18:28 +0200 Subject: [PATCH 31/33] chore: add licensing info to loader logos Signed-off-by: Sefa Eyeoglu --- launcher/resources/multimc/multimc.qrc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index bdf3495be..8f079bb37 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -348,9 +348,9 @@ scalable/launch.svg scalable/server.svg - scalable/instances/quiltmc.svg - scalable/instances/fabricmc.svg - 128x128/instances/forge.png - 128x128/instances/liteloader.png + scalable/instances/quiltmc.svg + scalable/instances/fabricmc.svg + 128x128/instances/forge.png + 128x128/instances/liteloader.png From 92dbe1684e3c7277a1b70711fe3450ba90c0e7d7 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 11 Aug 2023 19:42:02 +0300 Subject: [PATCH 32/33] revert asan on debug on by default Signed-off-by: Trial97 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 350189c87..60f03640e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0") # set CXXFLAGS for build targets set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}") -option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" on) +option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" off) # If this is a Debug build turn on address sanitiser if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) From bcf0635efd22d67b247d53562f91ae13a4095625 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sat, 12 Aug 2023 10:06:27 +0300 Subject: [PATCH 33/33] Update CMakeLists.txt Co-authored-by: Sefa Eyeoglu Signed-off-by: Alexandru Ionut Tripon --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60f03640e..17f7c3d8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0") # set CXXFLAGS for build targets set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}") -option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" off) +option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" OFF) # If this is a Debug build turn on address sanitiser if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER)