diff options
171 files changed, 2139 insertions, 704 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b6400791..3225cf1e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,26 +25,54 @@ jobs: - os: ubuntu-20.04 qt_ver: 6 qt_host: linux + qt_arch: '' qt_version: '6.2.4' qt_modules: 'qt5compat qtimageformats' + qt_tools: '' - os: windows-2022 name: "Windows-Legacy" - msystem: mingw32 + msystem: clang32 qt_ver: 5 - os: windows-2022 name: "Windows" - msystem: mingw32 + msystem: clang64 qt_ver: 6 + - os: windows-2022 + name: "Windows-Legacy-MSVC" + msystem: '' + architecture: 'win32' + vcvars_arch: 'amd64_x86' + qt_ver: 5 + qt_host: windows + qt_arch: 'win32_msvc2019' + qt_version: '5.15.2' + qt_modules: '' + qt_tools: 'tools_openssl_x86' + + - os: windows-2022 + name: "Windows-MSVC" + msystem: '' + architecture: 'x64' + vcvars_arch: 'amd64' + qt_ver: 6 + qt_host: windows + qt_arch: '' + qt_version: '6.4.0' + qt_modules: 'qt5compat qtimageformats' + qt_tools: '' + - os: macos-12 name: macOS macosx_deployment_target: 10.15 qt_ver: 6 qt_host: mac + qt_arch: '' qt_version: '6.3.0' qt_modules: 'qt5compat qtimageformats' + qt_tools: '' - os: macos-12 name: macOS-Legacy @@ -53,6 +81,7 @@ jobs: qt_host: mac qt_version: '5.15.2' qt_modules: '' + qt_tools: '' runs-on: ${{ matrix.os }} @@ -82,13 +111,14 @@ jobs: languages: cpp, java - name: 'Setup MSYS2' - if: runner.os == 'Windows' + if: runner.os == 'Windows' && matrix.msystem != '' uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.msystem }} update: true install: >- git + mingw-w64-x86_64-binutils pacboy: >- toolchain:p cmake:p @@ -99,17 +129,21 @@ jobs: qt${{ matrix.qt_ver }}-imageformats:p quazip-qt${{ matrix.qt_ver }}:p ccache:p - nsis:p ${{ matrix.qt_ver == 6 && 'qt6-5compat:p' || '' }} + - name: Force newer ccache + if: runner.os == 'Windows' && matrix.msystem == '' && inputs.build_type == 'Debug' + run: | + choco install ccache --version 4.7.1 + - name: Setup ccache - if: runner.os != 'Windows' && inputs.build_type == 'Debug' - uses: hendrikmuhs/ccache-action@v1.2.3 + if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug' + uses: hendrikmuhs/ccache-action@v1.2.5 with: key: ${{ matrix.os }}-qt${{ matrix.qt_ver }} - - name: Setup ccache (Windows) - if: runner.os == 'Windows' && inputs.build_type == 'Debug' + - name: Setup ccache (Windows MinGW-w64) + if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug' shell: msys2 {0} run: | ccache --set-config=cache_dir='${{ github.workspace }}\.ccache' @@ -124,8 +158,8 @@ jobs: run: | echo "CCACHE_VAR=ccache" >> $GITHUB_ENV - - name: Retrieve ccache cache (Windows) - if: runner.os == 'Windows' && inputs.build_type == 'Debug' + - name: Retrieve ccache cache (Windows MinGW-w64) + if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug' uses: actions/cache@v3.0.11 with: path: '${{ github.workspace }}\.ccache' @@ -156,14 +190,16 @@ jobs: run: | sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5 - - name: Install Qt (macOS and AppImage) - if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS' + - name: Install Qt (macOS, AppImage & Windows MSVC) + if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS' || (runner.os == 'Windows' && matrix.msystem == '') uses: jurplel/install-qt-action@v3 with: version: ${{ matrix.qt_version }} host: ${{ matrix.qt_host }} target: 'desktop' + arch: ${{ matrix.qt_arch }} modules: ${{ matrix.qt_modules }} + tools: ${{ matrix.qt_tools }} cache: true cache-key-prefix: ${{ matrix.qt_host }}-${{ matrix.qt_version }}-"${{ matrix.qt_modules }}"-qt_cache @@ -190,11 +226,26 @@ jobs: run: | cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja - - name: Configure CMake (Windows) - if: runner.os == 'Windows' + - name: Configure CMake (Windows MinGW-w64) + if: runner.os == 'Windows' && matrix.msystem != '' shell: msys2 {0} run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -G Ninja + + - name: Configure CMake (Windows MSVC) + if: runner.os == 'Windows' && matrix.msystem == '' + run: | + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} + # https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix) + if ("${{ env.CCACHE_VAR }}") + { + Copy-Item C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/ccache.exe -Destination C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/cl.exe + echo "CLToolExe=cl.exe" >> $env:GITHUB_ENV + echo "CLToolPath=C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/" >> $env:GITHUB_ENV + echo "TrackFileAccess=false" >> $env:GITHUB_ENV + } + # Needed for ccache, but also speeds up compile + echo "UseMultiToolTask=true" >> $env:GITHUB_ENV - name: Configure CMake (Linux) if: runner.os == 'Linux' @@ -210,12 +261,17 @@ jobs: run: | cmake --build ${{ env.BUILD_DIR }} - - name: Build (Windows) - if: runner.os == 'Windows' + - name: Build (Windows MinGW-w64) + if: runner.os == 'Windows' && matrix.msystem != '' shell: msys2 {0} run: | cmake --build ${{ env.BUILD_DIR }} + - name: Build (Windows MSVC) + if: runner.os == 'Windows' && matrix.msystem == '' + run: | + cmake --build ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }} + ## # TEST ## @@ -223,13 +279,18 @@ jobs: - name: Test if: runner.os != 'Windows' run: | - ctest --test-dir build --output-on-failure + ctest -E "^example64|example$" --test-dir build --output-on-failure - - name: Test (Windows) - if: runner.os == 'Windows' + - name: Test (Windows MinGW-w64) + if: runner.os == 'Windows' && matrix.msystem != '' shell: msys2 {0} run: | - ctest --test-dir build --output-on-failure + ctest -E "^example64|example$" --test-dir build --output-on-failure + + - name: Test (Windows MSVC) + if: runner.os == 'Windows' && matrix.msystem == '' + run: | + ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }} ## # CODE SCAN @@ -251,6 +312,7 @@ jobs: cd ${{ env.INSTALL_DIR }} chmod +x "PrismLauncher.app/Contents/MacOS/prismlauncher" sudo codesign --sign - --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PrismLauncher.app/Contents/MacOS/prismlauncher" + mv "PrismLauncher.app" "Prism Launcher.app" tar -czf ../PrismLauncher.tar.gz * - name: Make Sparkle signature (macOS) @@ -272,27 +334,50 @@ jobs: EOF fi - - name: Package (Windows) - if: runner.os == 'Windows' + - name: Add VC Enviroment Variables + if: runner.os == 'Windows' && matrix.msystem == '' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ matrix.vcvars_arch }} + + - name: Package (Windows MinGW-w64) + if: runner.os == 'Windows' && matrix.msystem != '' shell: msys2 {0} run: | cmake --install ${{ env.BUILD_DIR }} cd ${{ env.INSTALL_DIR }} if [ "${{ matrix.qt_ver }}" == "5" ]; then - cp /mingw32/bin/libcrypto-1_1.dll /mingw32/bin/libssl-1_1.dll ./ + cp /clang32/bin/libcrypto-1_1.dll /clang32/bin/libssl-1_1.dll ./ fi - - name: Package (Windows, portable) - if: runner.os == 'Windows' + - name: Package (Windows MSVC) + if: runner.os == 'Windows' && matrix.msystem == '' + run: | + cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }} + + 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 + } + + - name: Package (Windows MinGW-w64, portable) + if: runner.os == 'Windows' && matrix.msystem != '' shell: msys2 {0} 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 + - name: Package (Windows MSVC, portable) + if: runner.os == 'Windows' && matrix.msystem == '' + 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 + - name: Package (Windows, installer) if: runner.os == 'Windows' - shell: msys2 {0} run: | cd ${{ env.INSTALL_DIR }} makensis -NOCD "${{ github.workspace }}/${{ env.BUILD_DIR }}/program_info/win_install.nsi" @@ -411,5 +496,25 @@ 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 - - + snap: + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: 'true' + - name: Set short version + shell: bash + run: | + ver_short=`git rev-parse --short HEAD` + echo "VERSION=$ver_short" >> $GITHUB_ENV + - name: Package Snap (Linux) + id: snapcraft + if: runner.os == 'Linux' && matrix.qt_ver != 5 + uses: snapcore/action-build@v1 + - name: Upload Snap (Linux) + if: runner.os == 'Linux' && matrix.qt_ver != 5 + uses: actions/upload-artifact@v3 + with: + name: prismlauncher_${{ env.VERSION }}_amd64.snap + path: ${{ steps.snapcraft.outputs.snap }} diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index e74e870a..d415b2b1 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -47,10 +47,12 @@ jobs: for d in PrismLauncher-Windows-*; do cd "${d}" || continue + MSVC="$(echo -n ${d} | grep -o MSVC || true)" LEGACY="$(echo -n ${d} | grep -o Legacy || true)" INST="$(echo -n ${d} | grep -o Setup || true)" PORT="$(echo -n ${d} | grep -o Portable || true)" NAME="PrismLauncher-Windows" + test -z "${MSVC}" && NAME="${NAME}-MinGW" || NAME="${NAME}-MSVC" test -z "${LEGACY}" || NAME="${NAME}-Legacy" test -z "${PORT}" || NAME="${NAME}-Portable" test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe @@ -72,14 +74,20 @@ jobs: PrismLauncher-Linux-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage - PrismLauncher-Windows-Legacy-${{ env.VERSION }}.zip PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz - PrismLauncher-Windows-Legacy-Portable-${{ env.VERSION }}.zip - PrismLauncher-Windows-Legacy-Setup-${{ env.VERSION }}.exe - PrismLauncher-Windows-${{ env.VERSION }}.zip - PrismLauncher-Windows-Portable-${{ env.VERSION }}.zip - PrismLauncher-Windows-Setup-${{ env.VERSION }}.exe + PrismLauncher-Windows-MinGW-Legacy-${{ env.VERSION }}.zip + PrismLauncher-Windows-MinGW-Legacy-Portable-${{ env.VERSION }}.zip + PrismLauncher-Windows-MinGW-Legacy-Setup-${{ env.VERSION }}.exe + PrismLauncher-Windows-MinGW-${{ env.VERSION }}.zip + PrismLauncher-Windows-MinGW-Portable-${{ env.VERSION }}.zip + PrismLauncher-Windows-MinGW-Setup-${{ env.VERSION }}.exe + PrismLauncher-Windows-MSVC-Legacy-${{ env.VERSION }}.zip + PrismLauncher-Windows-MSVC-Legacy-Portable-${{ env.VERSION }}.zip + PrismLauncher-Windows-MSVC-Legacy-Setup-${{ env.VERSION }}.exe + PrismLauncher-Windows-MSVC-${{ env.VERSION }}.zip + PrismLauncher-Windows-MSVC-Portable-${{ env.VERSION }}.zip + PrismLauncher-Windows-MSVC-Setup-${{ env.VERSION }}.exe PrismLauncher-macOS-${{ env.VERSION }}.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}.tar.gz @@ -47,3 +47,6 @@ result/ # Flatpak .flatpak-builder flatbuild + +# Snap +*.snap diff --git a/.gitmodules b/.gitmodules index 8d034354..95274f15 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,9 @@ [submodule "libraries/libnbtplusplus"] path = libraries/libnbtplusplus url = https://github.com/PrismLauncher/libnbtplusplus.git +[submodule "libraries/zlib"] + path = libraries/zlib + url = https://github.com/madler/zlib.git +[submodule "libraries/extra-cmake-modules"] + path = libraries/extra-cmake-modules + url = https://github.com/KDE/extra-cmake-modules diff --git a/CMakeLists.txt b/CMakeLists.txt index 97bad31b..0db05f98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,5 @@ cmake_minimum_required(VERSION 3.15) # minimum version required by QuaZip -if(WIN32) - # In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows - cmake_policy(SET CMP0020 OLD) -endif() - project(Launcher) string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD) @@ -32,7 +27,43 @@ set(CMAKE_C_STANDARD_REQUIRED true) set(CMAKE_CXX_STANDARD 17) set(CMAKE_C_STANDARD 11) include(GenerateExportHeader) -set(CMAKE_CXX_FLAGS "-Wall -pedantic -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}") +if(MSVC) + # Use /W4 as /Wall includes unnesserey warnings such as added padding to structs + # /permissive- specify standards-conforming compiler behavior, also enabled by Qt6, default on with std:c++20 + # /GS Adds buffer security checks, default on but incuded anyway to mirror gcc's fstack-protector flag + set(CMAKE_CXX_FLAGS "/W4 /permissive- /GS ${CMAKE_CXX_FLAGS}") + + # LINK accepts /SUBSYSTEM whics sets if we are a WINDOWS (gui) or a CONSOLE programs + # This implicitly selects an entrypoint specific to the subsystem selected + # qtmain/QtEntryPointLib provides the correct entrypoint (wWinMain) for gui programs + # Additinaly LINK autodetects we use a GUI so we can omit /SUBSYSTEM + # This allows tests to still use have console without using seperate linker flags + # /MANIFEST:NO disables generating a manifest file, we instead provide our own + # /STACK sets the stack reserve size, ATL's pack list needs 3-4 MiB as of November 2022, provide 8 MiB + set(CMAKE_EXE_LINKER_FLAGS "/MANIFEST:NO /STACK:8388608 ${CMAKE_EXE_LINKER_FLAGS}") + + # See https://github.com/ccache/ccache/issues/1040 + # Note, CMake 3.25 replaces this with CMAKE_MSVC_DEBUG_INFORMATION_FORMAT + # See https://cmake.org/cmake/help/v3.25/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.html + foreach(config DEBUG RELWITHDEBINFO) + foreach(lang C CXX) + set(flags_var "CMAKE_${lang}_FLAGS_${config}") + string(REGEX REPLACE "/Z[Ii]" "/Z7" ${flags_var} "${${flags_var}}") + endforeach() + endforeach() + + if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDLL") + set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release "") + set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release "") + endif() +else() + set(CMAKE_CXX_FLAGS "-Wall -pedantic -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}") + + # ATL's pack list needs more than the default 1 Mib stack on windows + if(WIN32) + set(CMAKE_EXE_LINKER_FLAGS "-Wl,--stack,8388608 ${CMAKE_EXE_LINKER_FLAGS}") + endif() +endif() # Fix build with Qt 5.13 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y") @@ -48,11 +79,18 @@ if(ENABLE_LTO) include(CheckIPOSupported) check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error) - if(ipo_supported AND (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")) - message(STATUS "IPO / LTO enabled") - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) - elseif(ipo_supported) - message(STATUS "Not enabling IPO / LTO on debug builds") + if(ipo_supported) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE) + if(CMAKE_BUILD_TYPE) + if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") + message(STATUS "IPO / LTO enabled") + else() + message(STATUS "Not enabling IPO / LTO on debug builds") + endif() + else() + message(STATUS "IPO / LTO will only be enabled for release builds") + endif() else() message(STATUS "IPO / LTO not supported: <${ipo_error}>") endif() @@ -60,8 +98,20 @@ endif() option(BUILD_TESTING "Build the testing tree." ON) -find_package(ECM REQUIRED NO_MODULE) -set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}") +find_package(ECM QUIET NO_MODULE) +if(NOT ECM_FOUND) + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/CMakeLists.txt") + message(STATUS "Using bundled ECM") + set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/modules;${CMAKE_MODULE_PATH}") + else() + message(FATAL_ERROR + " Could not find ECM\n \n" + " Either install ECM using the system package manager or clone submodules\n" + " Submodules can be cloned with 'git submodule update --init --recursive'") + endif() +else() + set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}") +endif() include(CTest) include(ECMAddTests) if(BUILD_TESTING) @@ -76,7 +126,7 @@ set(Launcher_NEWS_OPEN_URL "https://prismlauncher.org/news" CACHE STRING "URL th set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help") ######## Set version numbers ######## -set(Launcher_VERSION_MAJOR 5) +set(Launcher_VERSION_MAJOR 6) set(Launcher_VERSION_MINOR 0) set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}") @@ -146,6 +196,10 @@ set(Launcher_BUILD_TIMESTAMP "${TODAY}") ################################ 3rd Party Libs ################################ +if(NOT Launcher_FORCE_BUNDLED_LIBS) + find_package(ZLIB QUIET) +endif() + # Find the required Qt parts include(QtVersionlessBackport) if(Launcher_QT_VERSION_MAJOR EQUAL 5) @@ -222,14 +276,14 @@ if(UNIX AND APPLE) set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app") # Mac bundle settings - set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_Name}") - set(MACOSX_BUNDLE_INFO_STRING "${Launcher_Name}: A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.") + set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_DisplayName}") + set(MACOSX_BUNDLE_INFO_STRING "${Launcher_DisplayName}: A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.") set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.prismlauncher.${Launcher_Name}") set(MACOSX_BUNDLE_BUNDLE_VERSION "${Launcher_VERSION_NAME}") set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_NAME}") set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_NAME}") set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns) - set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2021-2022 ${Launcher_Copyright}") + set(MACOSX_BUNDLE_COPYRIGHT "© 2022 ${Launcher_Copyright_Mac}") set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "v55ZWWD6QlPoXGV6VLzOTZxZUggWeE51X8cRQyQh6vA=") set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://prismlauncher.org/feed/appcast.xml") @@ -247,13 +301,11 @@ if(UNIX AND APPLE) install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns) elseif(UNIX) + include(KDEInstallDirs) + set(BINARY_DEST_DIR "bin") set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}") set(JARS_DEST_DIR "share/${Launcher_APP_BINARY_NAME}") - set(LAUNCHER_DESKTOP_DEST_DIR "share/applications" CACHE STRING "Path to the desktop file directory") - set(LAUNCHER_METAINFO_DEST_DIR "share/metainfo" CACHE STRING "Path to the metainfo directory") - set(LAUNCHER_ICON_DEST_DIR "share/icons/hicolor/scalable/apps" CACHE STRING "Path to the scalable icon directory") - set(LAUNCHER_MAN_DEST_DIR "share/man/man6" CACHE STRING "Path to the man page directory") # install as bundle with no dependencies included set(INSTALL_BUNDLE "nodeps") @@ -261,12 +313,13 @@ elseif(UNIX) # Set RPATH SET(Launcher_BINARY_RPATH "$ORIGIN/") - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${LAUNCHER_DESKTOP_DEST_DIR}) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${LAUNCHER_METAINFO_DEST_DIR}) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION ${LAUNCHER_ICON_DEST_DIR}) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${KDE_INSTALL_APPDIR}) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${KDE_INSTALL_METAINFODIR}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps") + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_mrpack_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR}) if(Launcher_ManPage) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION ${LAUNCHER_MAN_DEST_DIR}) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION "${KDE_INSTALL_MANDIR}/man6") endif() # Install basic runner script if component "portable" is selected @@ -306,6 +359,21 @@ add_subdirectory(libraries/systeminfo) # system information library add_subdirectory(libraries/hoedown) # markdown parser add_subdirectory(libraries/launcher) # java based launcher part for Minecraft add_subdirectory(libraries/javacheck) # java compatibility checker +if(NOT ZLIB_FOUND) + message(STATUS "Using bundled zlib") + set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) # Suppress cmake warnings and allow INTERPROCEDURAL_OPTIMIZATION for zlib + set(SKIP_INSTALL_ALL ON) + add_subdirectory(libraries/zlib EXCLUDE_FROM_ALL) + + set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib" "${CMAKE_CURRENT_BINARY_DIR}/libraries/zlib") + set_target_properties(zlibstatic PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIR}") + add_library(ZLIB::ZLIB ALIAS zlibstatic) + set(ZLIB_LIBRARY ZLIB::ZLIB) + set(ZLIB_FOUND true) + find_package(ZLIB REQUIRED) +else() + message(STATUS "Using system zlib") +endif() if (FORCE_BUNDLED_QUAZIP) message(STATUS "Using bundled QuaZip") set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts. @@ -1,14 +1,23 @@ -<p align="center"> -<img src="./program_info/org.prismlauncher.PrismLauncher.logo.svg#gh-light-mode-only" alt="Prism Launcher logo" width="50%"/> -<img src="./program_info/org.prismlauncher.PrismLauncher.logo-darkmode.svg#gh-dark-mode-only" alt="Prism Launcher logo" width="50%"/> +<p align="left"> +<picture> + <source media="(prefers-color-scheme: dark)" srcset="/program_info/org.prismlauncher.PrismLauncher.logo-darkmode.svg"> + <source media="(prefers-color-scheme: light)" srcset="/program_info/org.prismlauncher.PrismLauncher.logo.svg"> + <img alt="Prism Launcher" src="/program_info/org.prismlauncher.PrismLauncher.logo.svg" width="50%"> +</picture> </p> + Prism Launcher is a custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once. This is a **fork** of the MultiMC Launcher and not endorsed by MultiMC. + ## Installation +<a href="https://repology.org/project/prismlauncher/versions"> + <img src="https://repology.org/badge/vertical-allrepos/prismlauncher.svg" alt="Packaging status" align="right"> +</a> + - All downloads and instructions for Prism Launcher can be found [on our website](https://prismlauncher.org/download/). - Last build status can be found [here](https://github.com/PrismLauncher/PrismLauncher/actions). @@ -16,25 +25,24 @@ This is a **fork** of the MultiMC Launcher and not endorsed by MultiMC. There are development builds available [here](https://github.com/PrismLauncher/PrismLauncher/actions). These have debug information in the binaries, so their file sizes are relatively larger. -Portable builds are provided for on Linux, Windows, and macOS. +Portable builds are provided for Linux, Windows, and macOS. -For Debian and Arch, you can use these packages for the latest development versions: -[![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--git-blue)](https://aur.archlinux.org/packages/prismlauncher-git/) -[![prismlauncher-git](https://img.shields.io/badge/mpr-prismlauncher--git-orange)](https://mpr.makedeb.org/packages/prismlauncher-git) -## Help & Support +For Arch, Debian and Gentoo, respectively, you can use these packages to get compiled development versions: -Feel free to create an issue if you need help. However, you might find it easier to ask in the Discord server. +[![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--git-blue?style=flat-square)](https://aur.archlinux.org/packages/prismlauncher-qt5-git/) [![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--qt5--git-blue?style=flat-square)](https://aur.archlinux.org/packages/prismlauncher-git/) [![prismlauncher-git](https://img.shields.io/badge/mpr-prismlauncher--git-orange?style=flat-square)](https://mpr.makedeb.org/packages/prismlauncher-git) [![prismlauncher-9999](https://img.shields.io/badge/gentoo-prismlauncher--9999-purple?style=flat-square)](https://packages.gentoo.org/packages/games-action/prismlauncher) -[![Prism Launcher Discord server](https://discordapp.com/api/guilds/1031648380885147709/widget.png?style=banner3)](https://discord.gg/prismlauncher) +## Help & Support -We will also soon be opening up our Matrix channels. -You can already join our Matrix space: +Feel free to create an issue if you need help. -[![PrismLauncher Space](https://img.shields.io/matrix/prismlauncher:matrix.org?label=PrismLauncher%20space)](https://matrix.to/#/#prismlauncher:matrix.org) +#### Join our Discord server: +[![Prism Launcher Discord server](https://discordapp.com/api/guilds/1031648380885147709/widget.png?style=banner3)](https://discord.gg/prismlauncher) -We also have a subreddit you can post your issues and suggestions on: +#### Join our Matrix space: +[![PrismLauncher Space](https://img.shields.io/matrix/prismlauncher:matrix.org?style=for-the-badge)](https://matrix.to/#/#prismlauncher:matrix.org) -[r/PrismLauncher](https://www.reddit.com/r/PrismLauncher/) +#### Join our SubReddit: +[![r/PrismLauncher](https://img.shields.io/reddit/subreddit-subscribers/prismlauncher?style=for-the-badge)](https://www.reddit.com/r/PrismLauncher/) ## Building @@ -60,13 +68,11 @@ Be aware that if you build this software without removing the provided API keys If you do not agree with these terms and conditions, then remove the associated API keys from the [CMakeLists.txt](CMakeLists.txt) file by setting them to an empty string (`""`). -## License +## Sponsors & Partners -All launcher code is available under the GPL-3.0-only license. - -The logo and related assets are under the CC BY-SA 4.0 license. +We thank all the wonderful backers over at Open Collective! Support Prism Launcher by [becoming a backer](https://opencollective.com/prismlauncher). -## Sponsors +[![OpenCollective Backers](https://opencollective.com/prismlauncher/backers.svg?width=890&limit=1000)](https://opencollective.com/prismlauncher#backers) Thanks to JetBrains for providing us a few licenses for all their products, as part of their [Open Source program](https://www.jetbrains.com/opensource/). @@ -85,3 +91,12 @@ Thanks to Netlify for providing us their excellent web services, as part of thei Thanks to the awesome people over at [MacStadium](https://www.macstadium.com/), for providing M1-Macs for development purposes! <a href="https://www.macstadium.com"><img src="https://uploads-ssl.webflow.com/5ac3c046c82724970fc60918/5c019d917bba312af7553b49_MacStadium-developerlogo.png" alt="Powered by MacStadium" width="300"></a> + + +## License + +All launcher code is available under the GPL-3.0-only license. + +![https://github.com/PrismLauncher/PrismLauncher/blob/develop/LICENSE](https://img.shields.io/github/license/PrismLauncher/PrismLauncher?style=for-the-badge) + +The logo and related assets are under the CC BY-SA 4.0 license. diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index b8fa5133..1262ce8e 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -49,6 +49,7 @@ Config::Config() LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@"; LAUNCHER_GIT = "@Launcher_Git@"; LAUNCHER_DESKTOPFILENAME = "@Launcher_DesktopFileName@"; + LAUNCHER_SVGFILENAME = "@Launcher_SVGFileName@"; USER_AGENT = "@Launcher_UserAgent@"; USER_AGENT_UNCACHED = USER_AGENT + " (Uncached)"; diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 13ccdaa1..4a309073 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -51,6 +51,7 @@ class Config { QString LAUNCHER_CONFIGFILE; QString LAUNCHER_GIT; QString LAUNCHER_DESKTOPFILENAME; + QString LAUNCHER_SVGFILENAME; /// The major version number. int VERSION_MAJOR; diff --git a/cmake/MacOSXBundleInfo.plist.in b/cmake/MacOSXBundleInfo.plist.in index 1b22e21f..400e482f 100644 --- a/cmake/MacOSXBundleInfo.plist.in +++ b/cmake/MacOSXBundleInfo.plist.in @@ -44,5 +44,28 @@ <string>${MACOSX_SPARKLE_UPDATE_PUBLIC_KEY}</string> <key>SUFeedURL</key> <string>${MACOSX_SPARKLE_UPDATE_FEED_URL}</string> + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>zip</string> + <string>mrpack</string> + </array> + <key>CFBundleTypeName</key> + <string>Prism Launcher instance</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>TEXT</string> + <string>utxt</string> + <string>TUTX</string> + <string>****</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + </array> </dict> </plist> diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 97f757f7..9f731efa 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022 Lenny McLennington <lenny@sneed.church> + * Copyright (C) 2022 Tayou <tayou@gmx.net> * * 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 @@ -54,14 +55,9 @@ #include "ui/pages/global/APIPage.h" #include "ui/pages/global/CustomCommandsPage.h" -#include "ui/themes/ITheme.h" -#include "ui/themes/SystemTheme.h" -#include "ui/themes/DarkTheme.h" -#include "ui/themes/BrightTheme.h" -#include "ui/themes/CustomTheme.h" - #ifdef Q_OS_WIN #include "ui/WinDarkmode.h" +#include <versionhelpers.h> #endif #include "ui/setupwizard/SetupWizard.h" @@ -73,6 +69,8 @@ #include "ui/pagedialog/PageDialog.h" +#include "ui/themes/ThemeManager.h" + #include "ApplicationMessage.h" #include <iostream> @@ -245,7 +243,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) {{"s", "server"}, "Join the specified server on launch (only valid in combination with --launch)", "address"}, {{"a", "profile"}, "Use the account specified by its profile name (only valid in combination with --launch)", "profile"}, {"alive", "Write a small '" + liveCheckFile + "' file after the launcher starts"}, - {{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"} + {{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"}, + {"show", "Opens the window for the specified instance (by instance ID)", "show"} }); parser.addHelpOption(); parser.addVersionOption(); @@ -257,6 +256,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_profileToUse = parser.value("profile"); m_liveCheck = parser.isSet("alive"); m_zipToImport = parser.value("import"); + m_instanceIdToShowWindowOf = parser.value("show"); // error if --launch is missing with --server or --profile if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) @@ -498,6 +498,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // Theming m_settings->registerSetting("IconTheme", QString("pe_colored")); m_settings->registerSetting("ApplicationTheme", QString("system")); + m_settings->registerSetting("BackgroundCat", QString("kitteh")); // Remembered state m_settings->registerSetting("LastUsedGroupForNewInstance", QString()); @@ -610,6 +611,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // The cat m_settings->registerSetting("TheCat", false); + m_settings->registerSetting("ToolbarsLocked", false); + m_settings->registerSetting("InstSortMode", "Name"); m_settings->registerSetting("SelectedInstance", QString()); @@ -746,29 +749,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) qDebug() << "<> Instance icons intialized."; } - // Icon themes - { - // TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies! - // set icon theme search path! - auto searchPaths = QIcon::themeSearchPaths(); - searchPaths.append("iconthemes"); - QIcon::setThemeSearchPaths(searchPaths); - qDebug() << "<> Icon themes initialized."; - } - - // Initialize widget themes - { - auto insertTheme = [this](ITheme * theme) - { - m_themes.insert(std::make_pair(theme->id(), std::unique_ptr<ITheme>(theme))); - }; - auto darkTheme = new DarkTheme(); - insertTheme(new SystemTheme()); - insertTheme(darkTheme); - insertTheme(new BrightTheme()); - insertTheme(new CustomTheme(darkTheme, "custom")); - qDebug() << "<> Widget themes initialized."; - } + // Themes + m_themeManager = std::make_unique<ThemeManager>(m_mainWindow); // initialize and load all instances { @@ -945,6 +927,12 @@ bool Application::event(QEvent* event) { m_prevAppState = ev->applicationState(); } #endif + + if (event->type() == QEvent::FileOpen) { + auto ev = static_cast<QFileOpenEvent*>(event); + m_mainWindow->droppedURLs({ ev->url() }); + } + return QApplication::event(event); } @@ -986,6 +974,16 @@ void Application::performMainStartupAction() return; } } + if(!m_instanceIdToShowWindowOf.isEmpty()) + { + auto inst = instances()->getInstanceById(m_instanceIdToShowWindowOf); + if(inst) + { + qDebug() << "<> Showing window of instance " << m_instanceIdToShowWindowOf; + showInstanceWindow(inst); + return; + } + } if(!m_mainWindow) { // normal main window @@ -1112,60 +1110,25 @@ std::shared_ptr<JavaInstallList> Application::javalist() return m_javalist; } -std::vector<ITheme *> Application::getValidApplicationThemes() +QList<ITheme*> Application::getValidApplicationThemes() { - std::vector<ITheme *> ret; - auto iter = m_themes.cbegin(); - while (iter != m_themes.cend()) - { - ret.push_back((*iter).second.get()); - iter++; - } - return ret; -} - -bool Application::isFlatpak() -{ - #ifdef Q_OS_LINUX - return QFile::exists("/.flatpak-info"); - #else - return false; - #endif + return m_themeManager->getValidApplicationThemes(); } void Application::setApplicationTheme(const QString& name, bool initial) { - auto systemPalette = qApp->palette(); - auto themeIter = m_themes.find(name); - if(themeIter != m_themes.end()) - { - auto & theme = (*themeIter).second; - theme->apply(initial); -#ifdef Q_OS_WIN - if (m_mainWindow) { - if (QString::compare(theme->id(), "dark") == 0) { - WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), true); - } else { - WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), false); - } - } -#endif - } - else - { - qWarning() << "Tried to set invalid theme:" << name; - } + m_themeManager->setApplicationTheme(name, initial); } void Application::setIconTheme(const QString& name) { - QIcon::setThemeName(name); + m_themeManager->setIconTheme(name); } QIcon Application::getThemedIcon(const QString& name) { if(name == "logo") { - return QIcon(":/org.prismlauncher.PrismLauncher.svg"); // FIXME: Make this a BuildConfig variable + return QIcon(":/" + BuildConfig.LAUNCHER_SVGFILENAME); } return QIcon::fromTheme(name); } @@ -1383,10 +1346,13 @@ MainWindow* Application::showMainWindow(bool minimized) m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toByteArray())); m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toByteArray())); #ifdef Q_OS_WIN - if (QString::compare(settings()->get("ApplicationTheme").toString(), "dark") == 0) { - WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), true); - } else { - WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), false); + if (IsWindows10OrGreater()) + { + if (QString::compare(settings()->get("ApplicationTheme").toString(), "dark") == 0) { + WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), true); + } else { + WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), false); + } } #endif if(minimized) diff --git a/launcher/Application.h b/launcher/Application.h index 34ad8c15..78ab8fbd 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> + * Copyright (C) 2022 Tayou <tayou@gmx.net> * * 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 @@ -68,6 +69,7 @@ class BaseDetachedToolFactory; class TranslationsModel; class ITheme; class MCEditTool; +class ThemeManager; namespace Meta { class Index; @@ -116,11 +118,9 @@ public: QIcon getThemedIcon(const QString& name); - bool isFlatpak(); - void setIconTheme(const QString& name); - std::vector<ITheme *> getValidApplicationThemes(); + QList<ITheme*> getValidApplicationThemes(); void setApplicationTheme(const QString& name, bool initial); @@ -257,9 +257,9 @@ private: std::shared_ptr<JavaInstallList> m_javalist; std::shared_ptr<TranslationsModel> m_translations; std::shared_ptr<GenericPageProvider> m_globalSettingsProvider; - std::map<QString, std::unique_ptr<ITheme>> m_themes; std::unique_ptr<MCEditTool> m_mcedit; QSet<QString> m_features; + std::unique_ptr<ThemeManager> m_themeManager; QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers; @@ -301,6 +301,7 @@ public: QString m_profileToUse; bool m_liveCheck = false; QUrl m_zipToImport; + QString m_instanceIdToShowWindowOf; std::unique_ptr<QFile> logFile; }; diff --git a/launcher/BaseInstaller.h b/launcher/BaseInstaller.h index b2e6a14d..a1b80e93 100644 --- a/launcher/BaseInstaller.h +++ b/launcher/BaseInstaller.h @@ -17,13 +17,14 @@ #include <memory> +#include "BaseVersion.h" + class MinecraftInstance; class QDir; class QString; class QObject; class Task; class BaseVersion; -typedef std::shared_ptr<BaseVersion> BaseVersionPtr; class BaseInstaller { @@ -35,7 +36,7 @@ public: virtual bool add(MinecraftInstance *to); virtual bool remove(MinecraftInstance *from); - virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersionPtr version, QObject *parent) = 0; + virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersion::Ptr version, QObject *parent) = 0; protected: virtual QString id() const = 0; diff --git a/launcher/BaseVersion.h b/launcher/BaseVersion.h index b88105fb..ca0e4502 100644 --- a/launcher/BaseVersion.h +++ b/launcher/BaseVersion.h @@ -25,6 +25,7 @@ class BaseVersion { public: + using Ptr = std::shared_ptr<BaseVersion>; virtual ~BaseVersion() {} /*! * A string used to identify this version in config files. @@ -54,6 +55,4 @@ public: }; }; -typedef std::shared_ptr<BaseVersion> BaseVersionPtr; - -Q_DECLARE_METATYPE(BaseVersionPtr) +Q_DECLARE_METATYPE(BaseVersion::Ptr) diff --git a/launcher/BaseVersionList.cpp b/launcher/BaseVersionList.cpp index b4a7d6dd..4ed82612 100644 --- a/launcher/BaseVersionList.cpp +++ b/launcher/BaseVersionList.cpp @@ -40,20 +40,20 @@ BaseVersionList::BaseVersionList(QObject *parent) : QAbstractListModel(parent) { } -BaseVersionPtr BaseVersionList::findVersion(const QString &descriptor) +BaseVersion::Ptr BaseVersionList::findVersion(const QString &descriptor) { for (int i = 0; i < count(); i++) { if (at(i)->descriptor() == descriptor) return at(i); } - return BaseVersionPtr(); + return nullptr; } -BaseVersionPtr BaseVersionList::getRecommended() const +BaseVersion::Ptr BaseVersionList::getRecommended() const { if (count() <= 0) - return BaseVersionPtr(); + return nullptr; else return at(0); } @@ -66,7 +66,7 @@ QVariant BaseVersionList::data(const QModelIndex &index, int role) const if (index.row() > count()) return QVariant(); - BaseVersionPtr version = at(index.row()); + BaseVersion::Ptr version = at(index.row()); switch (role) { diff --git a/launcher/BaseVersionList.h b/launcher/BaseVersionList.h index 80a91e8f..31f29022 100644 --- a/launcher/BaseVersionList.h +++ b/launcher/BaseVersionList.h @@ -70,7 +70,7 @@ public: virtual bool isLoaded() = 0; //! Gets the version at the given index. - virtual const BaseVersionPtr at(int i) const = 0; + virtual const BaseVersion::Ptr at(int i) const = 0; //! Returns the number of versions in the list. virtual int count() const = 0; @@ -90,13 +90,13 @@ public: * \return A const pointer to the version with the given descriptor. NULL if * one doesn't exist. */ - virtual BaseVersionPtr findVersion(const QString &descriptor); + virtual BaseVersion::Ptr findVersion(const QString &descriptor); /*! * \brief Gets the recommended version from this list * If the list doesn't support recommended versions, this works exactly as getLatestStable */ - virtual BaseVersionPtr getRecommended() const; + virtual BaseVersion::Ptr getRecommended() const; /*! * Sorts the version list. @@ -117,5 +117,5 @@ slots: * then copies the versions and sets their parents correctly. * \param versions List of versions whose parents should be set. */ - virtual void updateListData(QList<BaseVersionPtr> versions) = 0; + virtual void updateListData(QList<BaseVersion::Ptr> versions) = 0; }; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 7dc060fb..f92375fb 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -541,9 +541,6 @@ set(ATLAUNCHER_SOURCES ################################ COMPILE ################################ -# we need zlib -find_package(ZLIB REQUIRED) - set(LOGIC_SOURCES ${CORE_SOURCES} ${PATHMATCHER_SOURCES} @@ -604,6 +601,7 @@ SET(LAUNCHER_SOURCES resources/OSX/OSX.qrc resources/iOS/iOS.qrc resources/flat/flat.qrc + resources/flat_white/flat_white.qrc resources/documents/documents.qrc ../${Launcher_Branding_LogoQRC} @@ -651,6 +649,8 @@ SET(LAUNCHER_SOURCES ui/themes/ITheme.h ui/themes/SystemTheme.cpp ui/themes/SystemTheme.h + ui/themes/ThemeManager.cpp + ui/themes/ThemeManager.h # Processes LaunchController.h @@ -1063,96 +1063,95 @@ if(INSTALL_BUNDLE STREQUAL "full") COMPONENT Runtime ) # Bundle plugins - if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - # Image formats - install( - DIRECTORY "${QT_PLUGINS_DIR}/imageformats" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "tga|tiff|mng" EXCLUDE - ) - # Icon engines - install( - DIRECTORY "${QT_PLUGINS_DIR}/iconengines" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "fontawesome" EXCLUDE - ) - # Platform plugins + # Image formats + install( + DIRECTORY "${QT_PLUGINS_DIR}/imageformats" + CONFIGURATIONS Debug RelWithDebInfo + DESTINATION ${PLUGIN_DEST_DIR} + COMPONENT Runtime + REGEX "tga|tiff|mng" EXCLUDE + ) + install( + DIRECTORY "${QT_PLUGINS_DIR}/imageformats" + CONFIGURATIONS Release MinSizeRel + DESTINATION ${PLUGIN_DEST_DIR} + COMPONENT Runtime + REGEX "tga|tiff|mng" EXCLUDE + REGEX "d\\." EXCLUDE + REGEX "_debug\\." EXCLUDE + REGEX "\\.dSYM" EXCLUDE + ) + # Icon engines + install( + DIRECTORY "${QT_PLUGINS_DIR}/iconengines" + CONFIGURATIONS Debug RelWithDebInfo + DESTINATION ${PLUGIN_DEST_DIR} + COMPONENT Runtime + REGEX "fontawesome" EXCLUDE + ) + install( + DIRECTORY "${QT_PLUGINS_DIR}/iconengines" + CONFIGURATIONS Release MinSizeRel + DESTINATION ${PLUGIN_DEST_DIR} + COMPONENT Runtime + REGEX "fontawesome" EXCLUDE + REGEX "d\\." EXCLUDE + REGEX "_debug\\." EXCLUDE + REGEX "\\.dSYM" EXCLUDE + ) + # Platform plugins + install( + DIRECTORY "${QT_PLUGINS_DIR}/platforms" + CONFIGURATIONS Debug RelWithDebInfo + DESTINATION ${PLUGIN_DEST_DIR} + COMPONENT Runtime + REGEX "minimal|linuxfb|offscreen" EXCLUDE + ) + install( + DIRECTORY "${QT_PLUGINS_DIR}/platforms" + CONFIGURATIONS Release MinSizeRel + DESTINATION ${PLUGIN_DEST_DIR} + COMPONENT Runtime + REGEX "minimal|linuxfb|offscreen" EXCLUDE + REGEX "[^2]d\\." EXCLUDE + REGEX "_debug\\." EXCLUDE + REGEX "\\.dSYM" EXCLUDE + ) + # Style plugins + if(EXISTS "${QT_PLUGINS_DIR}/styles") install( - DIRECTORY "${QT_PLUGINS_DIR}/platforms" + DIRECTORY "${QT_PLUGINS_DIR}/styles" + CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime - REGEX "minimal|linuxfb|offscreen" EXCLUDE ) - # Style plugins - if(EXISTS "${QT_PLUGINS_DIR}/styles") - install( - DIRECTORY "${QT_PLUGINS_DIR}/styles" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - ) - endif() - # TLS plugins (Qt 6 only) - if(EXISTS "${QT_PLUGINS_DIR}/tls") - install( - DIRECTORY "${QT_PLUGINS_DIR}/tls" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - ) - endif() - else() - # Image formats install( - DIRECTORY "${QT_PLUGINS_DIR}/imageformats" + DIRECTORY "${QT_PLUGINS_DIR}/styles" + CONFIGURATIONS Release MinSizeRel DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime - REGEX "tga|tiff|mng" EXCLUDE REGEX "d\\." EXCLUDE REGEX "_debug\\." EXCLUDE REGEX "\\.dSYM" EXCLUDE ) - # Icon engines + endif() + # TLS plugins (Qt 6 only) + if(EXISTS "${QT_PLUGINS_DIR}/tls") install( - DIRECTORY "${QT_PLUGINS_DIR}/iconengines" + DIRECTORY "${QT_PLUGINS_DIR}/tls" + CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime - REGEX "fontawesome" EXCLUDE - REGEX "d\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE ) - # Platform plugins install( - DIRECTORY "${QT_PLUGINS_DIR}/platforms" + DIRECTORY "${QT_PLUGINS_DIR}/tls" + CONFIGURATIONS Release MinSizeRel DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime - REGEX "minimal|linuxfb|offscreen" EXCLUDE - REGEX "d\\." EXCLUDE + REGEX "dd\\." EXCLUDE REGEX "_debug\\." EXCLUDE REGEX "\\.dSYM" EXCLUDE ) - # Style plugins - if(EXISTS "${QT_PLUGINS_DIR}/styles") - install( - DIRECTORY "${QT_PLUGINS_DIR}/styles" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "d\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - ) - endif() - # TLS plugins (Qt 6 only) - if(EXISTS "${QT_PLUGINS_DIR}/tls") - install( - DIRECTORY "${QT_PLUGINS_DIR}/tls" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - ) - endif() endif() configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in" diff --git a/launcher/DesktopServices.cpp b/launcher/DesktopServices.cpp index c29cbe7d..302eaf96 100644 --- a/launcher/DesktopServices.cpp +++ b/launcher/DesktopServices.cpp @@ -119,7 +119,7 @@ bool openDirectory(const QString &path, bool ensureExists) return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath())); }; #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) - if(!APPLICATION->isFlatpak()) + if(!isFlatpak()) { return IndirectOpen(f); } @@ -140,7 +140,7 @@ bool openFile(const QString &path) return QDesktopServices::openUrl(QUrl::fromLocalFile(path)); }; #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) - if(!APPLICATION->isFlatpak()) + if(!isFlatpak()) { return IndirectOpen(f); } @@ -158,7 +158,7 @@ bool openFile(const QString &application, const QString &path, const QString &wo qDebug() << "Opening file" << path << "using" << application; #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave - if(!APPLICATION->isFlatpak()) + if(!isFlatpak()) { return IndirectOpen([&]() { @@ -178,7 +178,7 @@ bool run(const QString &application, const QStringList &args, const QString &wor { qDebug() << "Running" << application << "with args" << args.join(' '); #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) - if(!APPLICATION->isFlatpak()) + if(!isFlatpak()) { // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave return IndirectOpen([&]() @@ -203,7 +203,7 @@ bool openUrl(const QUrl &url) return QDesktopServices::openUrl(url); }; #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) - if(!APPLICATION->isFlatpak()) + if(!isFlatpak()) { return IndirectOpen(f); } @@ -216,4 +216,13 @@ bool openUrl(const QUrl &url) #endif } +bool isFlatpak() +{ +#ifdef Q_OS_LINUX + return QFile::exists("/.flatpak-info"); +#else + return false; +#endif +} + } diff --git a/launcher/DesktopServices.h b/launcher/DesktopServices.h index 1c081da4..21c9cae0 100644 --- a/launcher/DesktopServices.h +++ b/launcher/DesktopServices.h @@ -33,4 +33,6 @@ namespace DesktopServices * Open the URL, most likely in a browser. Maybe. */ bool openUrl(const QUrl &url); + + bool isFlatpak(); } diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 39e68c20..4026d6c1 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -44,6 +44,7 @@ #include <QStandardPaths> #include <QTextStream> #include <QUrl> +#include "DesktopServices.h" #if defined Q_OS_WIN32 #include <objbase.h> @@ -182,6 +183,21 @@ bool copy::operator()(const QString& offset) if (!m_followSymlinks) opt |= copy_opts::copy_symlinks; + // Function that'll do the actual copying + auto copy_file = [&](QString src_path, QString relative_dst_path) { + if (m_blacklist && m_blacklist->matches(relative_dst_path)) + return; + + auto dst_path = PathCombine(dst, relative_dst_path); + ensureFilePathExists(dst_path); + + fs::copy(toStdString(src_path), toStdString(dst_path), opt, err); + if (err) { + qWarning() << "Failed to copy files:" << QString::fromStdString(err.message()); + qDebug() << "Source file:" << src_path; + qDebug() << "Destination file:" << dst_path; + } + }; // We can't use copy_opts::recursive because we need to take into account the // blacklisted paths, so we iterate over the source directory, and if there's no blacklist @@ -193,20 +209,13 @@ bool copy::operator()(const QString& offset) auto src_path = source_it.next(); auto relative_path = src_dir.relativeFilePath(src_path); - if (m_blacklist && m_blacklist->matches(relative_path)) - continue; - - auto dst_path = PathCombine(dst, relative_path); - ensureFilePathExists(dst_path); - - fs::copy(toStdString(src_path), toStdString(dst_path), opt, err); - if (err) { - qWarning() << "Failed to copy files:" << QString::fromStdString(err.message()); - qDebug() << "Source file:" << src_path; - qDebug() << "Destination file:" << dst_path; - } + copy_file(src_path, relative_path); } + // If the root src is not a directory, the previous iterator won't run. + if (!fs::is_directory(toStdString(src))) + copy_file(src, ""); + return err.value() == 0; } @@ -228,6 +237,9 @@ bool trash(QString path, QString *pathInTrash = nullptr) #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) return false; #else + // FIXME: Figure out trash in Flatpak. Qt seemingly doesn't use the Trash portal + if (DesktopServices::isFlatpak()) + return false; return QFile::moveToTrash(path, pathInTrash); #endif } @@ -401,6 +413,7 @@ bool overrideFolder(QString overwritten_path, QString override_path) std::error_code err; fs::copy_options opt = copy_opts::recursive | copy_opts::overwrite_existing; + // FIXME: hello traveller! Apparently std::copy does NOT overwrite existing files on GNU libstdc++ on Windows? fs::copy(toStdString(override_path), toStdString(overwritten_path), opt, err); if (err) { diff --git a/launcher/GZip.cpp b/launcher/GZip.cpp index 067104cf..e36dc8a4 100644 --- a/launcher/GZip.cpp +++ b/launcher/GZip.cpp @@ -72,7 +72,7 @@ bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedByte uncompLength *= 2; } - strm.next_out = (Bytef *)(uncompressedBytes.data() + strm.total_out); + strm.next_out = reinterpret_cast<Bytef *>((uncompressedBytes.data() + strm.total_out)); strm.avail_out = uncompLength - strm.total_out; // Inflate another chunk. @@ -129,7 +129,7 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes) { compressedBytes.resize(compressedBytes.size() * 2); } - zs.next_out = (Bytef *) (compressedBytes.data() + offset); + zs.next_out = reinterpret_cast<Bytef*>((compressedBytes.data() + offset)); temp = zs.avail_out = compressedBytes.size() - offset; ret = deflate(&zs, Z_FINISH); offset += temp - zs.avail_out; diff --git a/launcher/HoeDown.h b/launcher/HoeDown.h index b9e06ffb..cb62de6c 100644 --- a/launcher/HoeDown.h +++ b/launcher/HoeDown.h @@ -42,7 +42,7 @@ public: } void put(QByteArray input) { - hoedown_buffer_put(buf, (uint8_t *) input.data(), input.size()); + hoedown_buffer_put(buf, reinterpret_cast<uint8_t *>(input.data()), input.size()); } const uint8_t * data() const { diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index 0249bd22..155c956a 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -73,7 +73,7 @@ void JavaInstallList::load() } } -const BaseVersionPtr JavaInstallList::at(int i) const +const BaseVersion::Ptr JavaInstallList::at(int i) const { return m_vlist.at(i); } @@ -122,7 +122,7 @@ BaseVersionList::RoleList JavaInstallList::providesRoles() const } -void JavaInstallList::updateListData(QList<BaseVersionPtr> versions) +void JavaInstallList::updateListData(QList<BaseVersion::Ptr> versions) { beginResetModel(); m_vlist = versions; @@ -137,7 +137,7 @@ void JavaInstallList::updateListData(QList<BaseVersionPtr> versions) m_loadTask.reset(); } -bool sortJavas(BaseVersionPtr left, BaseVersionPtr right) +bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right) { auto rleft = std::dynamic_pointer_cast<JavaInstall>(right); auto rright = std::dynamic_pointer_cast<JavaInstall>(left); @@ -210,11 +210,11 @@ void JavaListLoadTask::javaCheckerFinished() } } - QList<BaseVersionPtr> javas_bvp; + QList<BaseVersion::Ptr> javas_bvp; for (auto java : candidates) { //qDebug() << java->id << java->arch << " at " << java->path; - BaseVersionPtr bp_java = std::dynamic_pointer_cast<BaseVersion>(java); + BaseVersion::Ptr bp_java = std::dynamic_pointer_cast<BaseVersion>(java); if (bp_java) { diff --git a/launcher/java/JavaInstallList.h b/launcher/java/JavaInstallList.h index 3c237edf..733dc7e1 100644 --- a/launcher/java/JavaInstallList.h +++ b/launcher/java/JavaInstallList.h @@ -42,7 +42,7 @@ public: Task::Ptr getLoadTask() override; bool isLoaded() override; - const BaseVersionPtr at(int i) const override; + const BaseVersion::Ptr at(int i) const override; int count() const override; void sortVersions() override; @@ -50,7 +50,7 @@ public: RoleList providesRoles() const override; public slots: - void updateListData(QList<BaseVersionPtr> versions) override; + void updateListData(QList<BaseVersion::Ptr> versions) override; protected: void load(); @@ -59,7 +59,7 @@ protected: protected: Status m_status = Status::NotDone; shared_qobject_ptr<JavaListLoadTask> m_loadTask; - QList<BaseVersionPtr> m_vlist; + QList<BaseVersion::Ptr> m_vlist; }; class JavaListLoadTask : public Task diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index 6c0c60cd..5efbc7a8 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -439,19 +439,28 @@ QList<QString> JavaUtils::FindJavaPaths() javas.append(FS::PathCombine(prefix, "bin/java")); } }; + // java installed in a snap is installed in the standard directory, but underneath $SNAP + auto snap = qEnvironmentVariable("SNAP"); + auto scanJavaDirs = [&](const QString & dirPath) + { + scanJavaDir(dirPath); + if (!snap.isNull()) { + scanJavaDir(snap + dirPath); + } + }; // oracle RPMs - scanJavaDir("/usr/java"); + scanJavaDirs("/usr/java"); // general locations used by distro packaging - scanJavaDir("/usr/lib/jvm"); - scanJavaDir("/usr/lib64/jvm"); - scanJavaDir("/usr/lib32/jvm"); + scanJavaDirs("/usr/lib/jvm"); + scanJavaDirs("/usr/lib64/jvm"); + scanJavaDirs("/usr/lib32/jvm"); // javas stored in Prism Launcher's folder - scanJavaDir("java"); + scanJavaDirs("java"); // manually installed JDKs in /opt - scanJavaDir("/opt/jdk"); - scanJavaDir("/opt/jdks"); + scanJavaDirs("/opt/jdk"); + scanJavaDirs("/opt/jdks"); // flatpak - scanJavaDir("/app/jdk"); + scanJavaDirs("/app/jdk"); javas = addJavasFromEnv(javas); javas.removeDuplicates(); return javas; diff --git a/launcher/main.cpp b/launcher/main.cpp index c6a7614c..e2116f38 100644 --- a/launcher/main.cpp +++ b/launcher/main.cpp @@ -84,6 +84,7 @@ int main(int argc, char *argv[]) Q_INIT_RESOURCE(OSX); Q_INIT_RESOURCE(iOS); Q_INIT_RESOURCE(flat); + Q_INIT_RESOURCE(flat_white); return app.exec(); } case Application::Failed: diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index 6802470d..eec1b329 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -24,7 +24,7 @@ Index::Index(QObject *parent) : QAbstractListModel(parent) { } -Index::Index(const QVector<VersionListPtr> &lists, QObject *parent) +Index::Index(const QVector<VersionList::Ptr> &lists, QObject *parent) : QAbstractListModel(parent), m_lists(lists) { for (int i = 0; i < m_lists.size(); ++i) @@ -41,7 +41,7 @@ QVariant Index::data(const QModelIndex &index, int role) const return QVariant(); } - VersionListPtr list = m_lists.at(index.row()); + VersionList::Ptr list = m_lists.at(index.row()); switch (role) { case Qt::DisplayRole: @@ -81,9 +81,9 @@ bool Index::hasUid(const QString &uid) const return m_uids.contains(uid); } -VersionListPtr Index::get(const QString &uid) +VersionList::Ptr Index::get(const QString &uid) { - VersionListPtr out = m_uids.value(uid, nullptr); + VersionList::Ptr out = m_uids.value(uid, nullptr); if(!out) { out = std::make_shared<VersionList>(uid); @@ -92,7 +92,7 @@ VersionListPtr Index::get(const QString &uid) return out; } -VersionPtr Index::get(const QString &uid, const QString &version) +Version::Ptr Index::get(const QString &uid, const QString &version) { auto list = get(uid); return list->getVersion(version); @@ -105,7 +105,7 @@ void Index::parse(const QJsonObject& obj) void Index::merge(const std::shared_ptr<Index> &other) { - const QVector<VersionListPtr> lists = std::dynamic_pointer_cast<Index>(other)->m_lists; + const QVector<VersionList::Ptr> lists = std::dynamic_pointer_cast<Index>(other)->m_lists; // initial load, no need to merge if (m_lists.isEmpty()) { @@ -120,7 +120,7 @@ void Index::merge(const std::shared_ptr<Index> &other) } else { - for (const VersionListPtr &list : lists) + for (const VersionList::Ptr &list : lists) { if (m_uids.contains(list->uid())) { @@ -138,7 +138,7 @@ void Index::merge(const std::shared_ptr<Index> &other) } } -void Index::connectVersionList(const int row, const VersionListPtr &list) +void Index::connectVersionList(const int row, const VersionList::Ptr &list) { connect(list.get(), &VersionList::nameChanged, this, [this, row]() { diff --git a/launcher/meta/Index.h b/launcher/meta/Index.h index d33ab0c8..06ea09dc 100644 --- a/launcher/meta/Index.h +++ b/launcher/meta/Index.h @@ -19,20 +19,19 @@ #include <memory> #include "BaseEntity.h" +#include "meta/VersionList.h" class Task; namespace Meta { -using VersionListPtr = std::shared_ptr<class VersionList>; -using VersionPtr = std::shared_ptr<class Version>; class Index : public QAbstractListModel, public BaseEntity { Q_OBJECT public: explicit Index(QObject *parent = nullptr); - explicit Index(const QVector<VersionListPtr> &lists, QObject *parent = nullptr); + explicit Index(const QVector<VersionList::Ptr> &lists, QObject *parent = nullptr); enum { @@ -49,21 +48,21 @@ public: QString localFilename() const override { return "index.json"; } // queries - VersionListPtr get(const QString &uid); - VersionPtr get(const QString &uid, const QString &version); + VersionList::Ptr get(const QString &uid); + Version::Ptr get(const QString &uid, const QString &version); bool hasUid(const QString &uid) const; - QVector<VersionListPtr> lists() const { return m_lists; } + QVector<VersionList::Ptr> lists() const { return m_lists; } public: // for usage by parsers only void merge(const std::shared_ptr<Index> &other); void parse(const QJsonObject &obj) override; private: - QVector<VersionListPtr> m_lists; - QHash<QString, VersionListPtr> m_uids; + QVector<VersionList::Ptr> m_lists; + QHash<QString, VersionList::Ptr> m_uids; - void connectVersionList(const int row, const VersionListPtr &list); + void connectVersionList(const int row, const VersionList::Ptr &list); }; } diff --git a/launcher/meta/JsonFormat.cpp b/launcher/meta/JsonFormat.cpp index 796da4bb..473f37d6 100644 --- a/launcher/meta/JsonFormat.cpp +++ b/launcher/meta/JsonFormat.cpp @@ -37,11 +37,11 @@ MetadataVersion currentFormatVersion() static std::shared_ptr<Index> parseIndexInternal(const QJsonObject &obj) { const QVector<QJsonObject> objects = requireIsArrayOf<QJsonObject>(obj, "packages"); - QVector<VersionListPtr> lists; + QVector<VersionList::Ptr> lists; lists.reserve(objects.size()); std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject &obj) { - VersionListPtr list = std::make_shared<VersionList>(requireString(obj, "uid")); + VersionList::Ptr list = std::make_shared<VersionList>(requireString(obj, "uid")); list->setName(ensureString(obj, "name", QString())); return list; }); @@ -49,9 +49,9 @@ static std::shared_ptr<Index> parseIndexInternal(const QJsonObject &obj) } // Version -static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj) +static Version::Ptr parseCommonVersion(const QString &uid, const QJsonObject &obj) { - VersionPtr version = std::make_shared<Version>(uid, requireString(obj, "version")); + Version::Ptr version = std::make_shared<Version>(uid, requireString(obj, "version")); version->setTime(QDateTime::fromString(requireString(obj, "releaseTime"), Qt::ISODate).toMSecsSinceEpoch() / 1000); version->setType(ensureString(obj, "type", QString())); version->setRecommended(ensureBoolean(obj, QString("recommended"), false)); @@ -63,9 +63,9 @@ static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj) return version; } -static std::shared_ptr<Version> parseVersionInternal(const QJsonObject &obj) +static Version::Ptr parseVersionInternal(const QJsonObject &obj) { - VersionPtr version = parseCommonVersion(requireString(obj, "uid"), obj); + Version::Ptr version = parseCommonVersion(requireString(obj, "uid"), obj); version->setData(OneSixVersionFormat::versionFileFromJson(QJsonDocument(obj), QString("%1/%2.json").arg(version->uid(), version->version()), @@ -74,12 +74,12 @@ static std::shared_ptr<Version> parseVersionInternal(const QJsonObject &obj) } // Version list / package -static std::shared_ptr<VersionList> parseVersionListInternal(const QJsonObject &obj) +static VersionList::Ptr parseVersionListInternal(const QJsonObject &obj) { const QString uid = requireString(obj, "uid"); const QVector<QJsonObject> versionsRaw = requireIsArrayOf<QJsonObject>(obj, "versions"); - QVector<VersionPtr> versions; + QVector<Version::Ptr> versions; versions.reserve(versionsRaw.size()); std::transform(versionsRaw.begin(), versionsRaw.end(), std::back_inserter(versions), [uid](const QJsonObject &vObj) { @@ -88,7 +88,7 @@ static std::shared_ptr<VersionList> parseVersionListInternal(const QJsonObject & return version; }); - VersionListPtr list = std::make_shared<VersionList>(uid); + VersionList::Ptr list = std::make_shared<VersionList>(uid); list->setName(ensureString(obj, "name", QString())); list->setVersions(versions); return list; diff --git a/launcher/meta/Version.cpp b/launcher/meta/Version.cpp index a8dc3169..68cfa55c 100644 --- a/launcher/meta/Version.cpp +++ b/launcher/meta/Version.cpp @@ -54,7 +54,7 @@ void Meta::Version::parse(const QJsonObject& obj) parseVersion(obj, this); } -void Meta::Version::mergeFromList(const Meta::VersionPtr& other) +void Meta::Version::mergeFromList(const Meta::Version::Ptr& other) { if(other->m_providesRecommendations) { @@ -85,7 +85,7 @@ void Meta::Version::mergeFromList(const Meta::VersionPtr& other) } } -void Meta::Version::merge(const VersionPtr &other) +void Meta::Version::merge(const Version::Ptr &other) { mergeFromList(other); if(other->m_data) diff --git a/launcher/meta/Version.h b/launcher/meta/Version.h index dea8dc8a..7228fa36 100644 --- a/launcher/meta/Version.h +++ b/launcher/meta/Version.h @@ -30,13 +30,14 @@ namespace Meta { -using VersionPtr = std::shared_ptr<class Version>; class Version : public QObject, public BaseVersion, public BaseEntity { Q_OBJECT -public: /* con/des */ +public: + using Ptr = std::shared_ptr<Version>; + explicit Version(const QString &uid, const QString &version); virtual ~Version(); @@ -78,8 +79,8 @@ public: /* con/des */ return m_data != nullptr; } - void merge(const VersionPtr &other); - void mergeFromList(const VersionPtr &other); + void merge(const Version::Ptr &other); + void mergeFromList(const Version::Ptr &other); void parse(const QJsonObject &obj) override; QString localFilename() const override; @@ -113,4 +114,4 @@ private: }; } -Q_DECLARE_METATYPE(Meta::VersionPtr) +Q_DECLARE_METATYPE(Meta::Version::Ptr) diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index f609e94c..7f001dfc 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -40,7 +40,7 @@ bool VersionList::isLoaded() return BaseEntity::isLoaded(); } -const BaseVersionPtr VersionList::at(int i) const +const BaseVersion::Ptr VersionList::at(int i) const { return m_versions.at(i); } @@ -52,7 +52,7 @@ int VersionList::count() const void VersionList::sortVersions() { beginResetModel(); - std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b) + std::sort(m_versions.begin(), m_versions.end(), [](const Version::Ptr &a, const Version::Ptr &b) { return *a.get() < *b.get(); }); @@ -66,7 +66,7 @@ QVariant VersionList::data(const QModelIndex &index, int role) const return QVariant(); } - VersionPtr version = m_versions.at(index.row()); + Version::Ptr version = m_versions.at(index.row()); switch (role) { @@ -129,9 +129,9 @@ QString VersionList::humanReadable() const return m_name.isEmpty() ? m_uid : m_name; } -VersionPtr VersionList::getVersion(const QString &version) +Version::Ptr VersionList::getVersion(const QString &version) { - VersionPtr out = m_lookup.value(version, nullptr); + Version::Ptr out = m_lookup.value(version, nullptr); if(!out) { out = std::make_shared<Version>(m_uid, version); @@ -143,7 +143,7 @@ VersionPtr VersionList::getVersion(const QString &version) bool VersionList::hasVersion(QString version) const { auto ver = std::find_if(m_versions.constBegin(), m_versions.constEnd(), - [&](Meta::VersionPtr const& a){ return a->version() == version; }); + [&](Meta::Version::Ptr const& a){ return a->version() == version; }); return (ver != m_versions.constEnd()); } @@ -153,11 +153,11 @@ void VersionList::setName(const QString &name) emit nameChanged(name); } -void VersionList::setVersions(const QVector<VersionPtr> &versions) +void VersionList::setVersions(const QVector<Version::Ptr> &versions) { beginResetModel(); m_versions = versions; - std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b) + std::sort(m_versions.begin(), m_versions.end(), [](const Version::Ptr &a, const Version::Ptr &b) { return a->rawTime() > b->rawTime(); }); @@ -168,7 +168,7 @@ void VersionList::setVersions(const QVector<VersionPtr> &versions) } // FIXME: this is dumb, we have 'recommended' as part of the metadata already... - auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const VersionPtr &ptr) { return ptr->type() == "release"; }); + auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const Version::Ptr &ptr) { return ptr->type() == "release"; }); m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt; endResetModel(); } @@ -179,7 +179,7 @@ void VersionList::parse(const QJsonObject& obj) } // FIXME: this is dumb, we have 'recommended' as part of the metadata already... -static const Meta::VersionPtr &getBetterVersion(const Meta::VersionPtr &a, const Meta::VersionPtr &b) +static const Meta::Version::Ptr &getBetterVersion(const Meta::Version::Ptr &a, const Meta::Version::Ptr &b) { if(!a) return b; @@ -194,7 +194,7 @@ static const Meta::VersionPtr &getBetterVersion(const Meta::VersionPtr &a, const return (a->type() == "release" ? a : b); } -void VersionList::mergeFromIndex(const VersionListPtr &other) +void VersionList::mergeFromIndex(const VersionList::Ptr &other) { if (m_name != other->m_name) { @@ -202,7 +202,7 @@ void VersionList::mergeFromIndex(const VersionListPtr &other) } } -void VersionList::merge(const VersionListPtr &other) +void VersionList::merge(const VersionList::Ptr &other) { if (m_name != other->m_name) { @@ -216,7 +216,7 @@ void VersionList::merge(const VersionListPtr &other) { qWarning() << "Empty list loaded ..."; } - for (const VersionPtr &version : other->m_versions) + for (const Version::Ptr &version : other->m_versions) { // we already have the version. merge the contents if (m_lookup.contains(version->version())) @@ -235,7 +235,7 @@ void VersionList::merge(const VersionListPtr &other) endResetModel(); } -void VersionList::setupAddedVersion(const int row, const VersionPtr &version) +void VersionList::setupAddedVersion(const int row, const Version::Ptr &version) { // FIXME: do not disconnect from everythin, disconnect only the lambdas here version->disconnect(); @@ -244,7 +244,7 @@ void VersionList::setupAddedVersion(const int row, const VersionPtr &version) connect(version.get(), &Version::typeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << TypeRole); }); } -BaseVersionPtr VersionList::getRecommended() const +BaseVersion::Ptr VersionList::getRecommended() const { return m_recommended; } diff --git a/launcher/meta/VersionList.h b/launcher/meta/VersionList.h index a6db2fd7..a4d5603d 100644 --- a/launcher/meta/VersionList.h +++ b/launcher/meta/VersionList.h @@ -20,10 +20,10 @@ #include <QJsonObject> #include <memory> +#include "meta/Version.h" + namespace Meta { -using VersionPtr = std::shared_ptr<class Version>; -using VersionListPtr = std::shared_ptr<class VersionList>; class VersionList : public BaseVersionList, public BaseEntity { @@ -33,6 +33,8 @@ class VersionList : public BaseVersionList, public BaseEntity public: explicit VersionList(const QString &uid, QObject *parent = nullptr); + using Ptr = std::shared_ptr<VersionList>; + enum Roles { UidRole = Qt::UserRole + 100, @@ -43,11 +45,11 @@ public: Task::Ptr getLoadTask() override; bool isLoaded() override; - const BaseVersionPtr at(int i) const override; + const BaseVersion::Ptr at(int i) const override; int count() const override; void sortVersions() override; - BaseVersionPtr getRecommended() const override; + BaseVersion::Ptr getRecommended() const override; QVariant data(const QModelIndex &index, int role) const override; RoleList providesRoles() const override; @@ -65,38 +67,38 @@ public: } QString humanReadable() const; - VersionPtr getVersion(const QString &version); + Version::Ptr getVersion(const QString &version); bool hasVersion(QString version) const; - QVector<VersionPtr> versions() const + QVector<Version::Ptr> versions() const { return m_versions; } public: // for usage only by parsers void setName(const QString &name); - void setVersions(const QVector<VersionPtr> &versions); - void merge(const VersionListPtr &other); - void mergeFromIndex(const VersionListPtr &other); + void setVersions(const QVector<Version::Ptr> &versions); + void merge(const VersionList::Ptr &other); + void mergeFromIndex(const VersionList::Ptr &other); void parse(const QJsonObject &obj) override; signals: void nameChanged(const QString &name); protected slots: - void updateListData(QList<BaseVersionPtr>) override + void updateListData(QList<BaseVersion::Ptr>) override { } private: - QVector<VersionPtr> m_versions; - QHash<QString, VersionPtr> m_lookup; + QVector<Version::Ptr> m_versions; + QHash<QString, Version::Ptr> m_lookup; QString m_uid; QString m_name; - VersionPtr m_recommended; + Version::Ptr m_recommended; - void setupAddedVersion(const int row, const VersionPtr &version); + void setupAddedVersion(const int row, const Version::Ptr &version); }; } -Q_DECLARE_METATYPE(Meta::VersionListPtr) +Q_DECLARE_METATYPE(Meta::VersionList::Ptr) diff --git a/launcher/minecraft/VanillaInstanceCreationTask.cpp b/launcher/minecraft/VanillaInstanceCreationTask.cpp index c45daa9a..0bb92e87 100644 --- a/launcher/minecraft/VanillaInstanceCreationTask.cpp +++ b/launcher/minecraft/VanillaInstanceCreationTask.cpp @@ -7,7 +7,7 @@ #include "minecraft/PackProfile.h" #include "settings/INISettingsObject.h" -VanillaCreationTask::VanillaCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loader_version) +VanillaCreationTask::VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loader_version) : InstanceCreationTask(), m_version(std::move(version)), m_using_loader(true), m_loader(std::move(loader)), m_loader_version(std::move(loader_version)) {} diff --git a/launcher/minecraft/VanillaInstanceCreationTask.h b/launcher/minecraft/VanillaInstanceCreationTask.h index 7a37bbd6..d1b81682 100644 --- a/launcher/minecraft/VanillaInstanceCreationTask.h +++ b/launcher/minecraft/VanillaInstanceCreationTask.h @@ -7,16 +7,16 @@ class VanillaCreationTask final : public InstanceCreationTask { Q_OBJECT public: - VanillaCreationTask(BaseVersionPtr version) : InstanceCreationTask(), m_version(std::move(version)) {} - VanillaCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loader_version); + VanillaCreationTask(BaseVersion::Ptr version) : InstanceCreationTask(), m_version(std::move(version)) {} + VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loader_version); bool createInstance() override; private: // Version to update to / create of the instance. - BaseVersionPtr m_version; + BaseVersion::Ptr m_version; bool m_using_loader = false; QString m_loader; - BaseVersionPtr m_loader_version; + BaseVersion::Ptr m_loader_version; }; diff --git a/launcher/minecraft/launch/VerifyJavaInstall.cpp b/launcher/minecraft/launch/VerifyJavaInstall.cpp index 99809f82..6ae666b4 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.cpp +++ b/launcher/minecraft/launch/VerifyJavaInstall.cpp @@ -71,5 +71,7 @@ void VerifyJavaInstall::executeTask() { { emit logLine(tr("Java version %1").arg(major), MessageLevel::Error); } + emit logLine(tr("Go to instance Java settings to change your Java version or disable the Java compatibility check if you know what you're doing."), MessageLevel::Error); + emitFailed(QString("Incompatible Java major version")); } diff --git a/launcher/modplatform/ModAPI.h b/launcher/modplatform/ModAPI.h index c7408835..703de143 100644 --- a/launcher/modplatform/ModAPI.h +++ b/launcher/modplatform/ModAPI.h @@ -39,7 +39,7 @@ #include <QList> #include <list> -#include "Version.h" +#include "../Version.h" #include "net/NetJob.h" namespace ModPlatform { diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 68d75943..291ad916 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -58,7 +58,7 @@ namespace ATLauncher { -static Meta::VersionPtr getComponentVersion(const QString& uid, const QString& version); +static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version); PackInstallTask::PackInstallTask(UserInteractionSupport *support, QString packName, QString version, InstallMode installMode) { @@ -1037,7 +1037,7 @@ void PackInstallTask::install() emitSucceeded(); } -static Meta::VersionPtr getComponentVersion(const QString& uid, const QString& version) +static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version) { auto vlist = APPLICATION->metadataIndex()->get(uid); if (!vlist) diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.h b/launcher/modplatform/atlauncher/ATLPackInstallTask.h index 78cd87fb..90e25ae2 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.h +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.h @@ -68,7 +68,7 @@ public: * Requests a user interaction to select a component version from a given version list * and constrained to a given Minecraft version. */ - virtual QString chooseVersion(Meta::VersionListPtr vlist, QString minecraftVersion) = 0; + virtual QString chooseVersion(Meta::VersionList::Ptr vlist, QString minecraftVersion) = 0; /** * Requests a user interaction to display a message. @@ -137,8 +137,8 @@ private: QString archivePath; QStringList jarmods; - Meta::VersionPtr minecraftVersion; - QMap<QString, Meta::VersionPtr> componentsToInstall; + Meta::Version::Ptr minecraftVersion; + QMap<QString, Meta::Version::Ptr> componentsToInstall; QFuture<std::optional<QStringList>> m_extractFuture; QFutureWatcher<std::optional<QStringList>> m_extractFutureWatcher; diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index c50abb8f..25b56fbd 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -3,6 +3,8 @@ #include "Json.h" #include "net/Upload.h" +#include "modplatform/modrinth/ModrinthPackIndex.h" + Flame::FileResolvingTask::FileResolvingTask(const shared_qobject_ptr<QNetworkAccessManager>& network, Flame::Manifest& toProcess) : m_network(network), m_toProcess(toProcess) {} @@ -84,18 +86,21 @@ void Flame::FileResolvingTask::modrinthCheckFinished() { delete bytes; continue; } + QJsonDocument doc = QJsonDocument::fromJson(*bytes); auto obj = doc.object(); - auto array = Json::requireArray(obj,"files"); - for (auto file: array) { - auto fileObj = Json::requireObject(file); - auto primary = Json::requireBoolean(fileObj,"primary"); - if (primary) { - out->url = Json::requireUrl(fileObj,"url"); - qDebug() << "Found alternative on modrinth " << out->fileName; - break; - } + auto file = Modrinth::loadIndexedPackVersion(obj); + + // If there's more than one mod loader for this version, we can't know for sure + // which file is relative to each loader, so it's best to not use any one and + // let the user download it manually. + if (file.loaders.size() <= 1) { + out->url = file.downloadUrl; + qDebug() << "Found alternative on modrinth " << out->fileName; + } else { + out->resolved = false; } + delete bytes; } //copy to an output list and filter out projects found on modrinth diff --git a/launcher/modplatform/helpers/NetworkModAPI.cpp b/launcher/modplatform/helpers/NetworkModAPI.cpp index 866e7540..7633030e 100644 --- a/launcher/modplatform/helpers/NetworkModAPI.cpp +++ b/launcher/modplatform/helpers/NetworkModAPI.cpp @@ -15,6 +15,7 @@ void NetworkModAPI::searchMods(CallerType* caller, SearchArgs&& args) const QObject::connect(netJob, &NetJob::started, caller, [caller, netJob] { caller->setActiveJob(netJob); }); QObject::connect(netJob, &NetJob::failed, caller, &CallerType::searchRequestFailed); + QObject::connect(netJob, &NetJob::aborted, caller, &CallerType::searchRequestAborted); QObject::connect(netJob, &NetJob::succeeded, caller, [caller, response] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 3e53becb..ae45e096 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln <flowlnlnln@gmail.com> -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln <flowlnlnln@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ #include "ModrinthPackIndex.h" #include "ModrinthAPI.h" @@ -35,7 +35,7 @@ void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) pack.provider = ModPlatform::Provider::MODRINTH; pack.name = Json::requireString(obj, "title"); - + pack.slug = Json::ensureString(obj, "slug", ""); if (!pack.slug.isEmpty()) pack.websiteUrl = "https://modrinth.com/mod/" + pack.slug; @@ -59,23 +59,23 @@ void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) void Modrinth::loadExtraPackData(ModPlatform::IndexedPack& pack, QJsonObject& obj) { pack.extraData.issuesUrl = Json::ensureString(obj, "issues_url"); - if(pack.extraData.issuesUrl.endsWith('/')) + if (pack.extraData.issuesUrl.endsWith('/')) pack.extraData.issuesUrl.chop(1); pack.extraData.sourceUrl = Json::ensureString(obj, "source_url"); - if(pack.extraData.sourceUrl.endsWith('/')) + if (pack.extraData.sourceUrl.endsWith('/')) pack.extraData.sourceUrl.chop(1); pack.extraData.wikiUrl = Json::ensureString(obj, "wiki_url"); - if(pack.extraData.wikiUrl.endsWith('/')) + if (pack.extraData.wikiUrl.endsWith('/')) pack.extraData.wikiUrl.chop(1); pack.extraData.discordUrl = Json::ensureString(obj, "discord_url"); - if(pack.extraData.discordUrl.endsWith('/')) + if (pack.extraData.discordUrl.endsWith('/')) pack.extraData.discordUrl.chop(1); auto donate_arr = Json::ensureArray(obj, "donation_urls"); - for(auto d : donate_arr){ + for (auto d : donate_arr) { auto d_obj = Json::requireObject(d); ModPlatform::DonationData donate; @@ -104,7 +104,7 @@ void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, auto obj = versionIter.toObject(); auto file = loadIndexedPackVersion(obj); - if(file.fileId.isValid()) // Heuristic to check if the returned value is valid + if (file.fileId.isValid()) // Heuristic to check if the returned value is valid unsortedVersions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { @@ -116,7 +116,8 @@ void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, pack.versionsLoaded = true; } -auto Modrinth::loadIndexedPackVersion(QJsonObject &obj, QString preferred_hash_type, QString preferred_file_name) -> ModPlatform::IndexedVersion +auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_type, QString preferred_file_name) + -> ModPlatform::IndexedVersion { ModPlatform::IndexedVersion file; @@ -141,6 +142,12 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject &obj, QString preferred_hash_t auto files = Json::requireArray(obj, "files"); int i = 0; + if (files.empty()) { + // This should not happen normally, but check just in case + qWarning() << "Modrinth returned an unexpected empty list of files:" << obj; + return {}; + } + // Find correct file (needed in cases where one version may have multiple files) // Will default to the last one if there's no primary (though I think Modrinth requires that // at least one file is primary, idk) @@ -167,7 +174,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject &obj, QString preferred_hash_t file.fileName = Json::requireString(parent, "filename"); file.is_preferred = Json::requireBoolean(parent, "primary") || (files.count() == 1); auto hash_list = Json::requireObject(parent, "hashes"); - + if (hash_list.contains(preferred_hash_type)) { file.hash = Json::requireString(hash_list, preferred_hash_type); file.hash_type = preferred_hash_type; diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp index a4620df9..96f54067 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp @@ -140,7 +140,7 @@ auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion for (auto file_iter : files) { File indexed_file; auto parent = Json::requireObject(file_iter); - auto is_primary = Json::ensureBoolean(parent, "primary", false); + auto is_primary = Json::ensureBoolean(parent, (const QString)QStringLiteral("primary"), false); if (!is_primary) { auto filename = Json::ensureString(parent, "filename"); // Checking suffix here is fine because it's the response from Modrinth, diff --git a/launcher/net/HttpMetaCache.cpp b/launcher/net/HttpMetaCache.cpp index 42198b71..e242dcf4 100644 --- a/launcher/net/HttpMetaCache.cpp +++ b/launcher/net/HttpMetaCache.cpp @@ -242,7 +242,7 @@ void HttpMetaCache::Load() foo->local_changed_timestamp = Json::ensureDouble(element_obj, "last_changed_timestamp"); foo->remote_changed_timestamp = Json::ensureString(element_obj, "remote_changed_timestamp"); - foo->makeEternal(Json::ensureBoolean(element_obj, "eternal", false)); + foo->makeEternal(Json::ensureBoolean(element_obj, (const QString)QStringLiteral("eternal"), false)); if (!foo->isEternal()) { foo->current_age = Json::ensureDouble(element_obj, "current_age"); foo->max_age = Json::ensureDouble(element_obj, "max_age"); diff --git a/launcher/resources/OSX/OSX.qrc b/launcher/resources/OSX/OSX.qrc index 55be28b5..19fe312b 100644 --- a/launcher/resources/OSX/OSX.qrc +++ b/launcher/resources/OSX/OSX.qrc @@ -38,5 +38,6 @@ <file>scalable/tag.svg</file> <file>scalable/export.svg</file> <file>scalable/rename.svg</file> + <file>scalable/launch.svg</file> </qresource> </RCC> diff --git a/launcher/resources/OSX/scalable/launch.svg b/launcher/resources/OSX/scalable/launch.svg new file mode 100644 index 00000000..fb189162 --- /dev/null +++ b/launcher/resources/OSX/scalable/launch.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + version="1.1" + id="Calque_1" + x="0px" + y="0px" + viewBox="0 0 32.099998 32" + enable-background="new 0 0 32 32" + xml:space="preserve" + width="32.099998" + height="32" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"><defs + id="defs45" /> + +<rect + fill-rule="evenodd" + clip-rule="evenodd" + fill="none" + width="32" + height="32" + id="rect1776" + x="0.1" + y="0" /><path + fill="#b6b5b6" + d="M 30,28.4 H 2 c -1.1,0 -2,-0.9 -2,-2 v -18 c 0,-1.1 0.9,-2 2,-2 h 28 c 1.1,0 2,0.9 2,2 v 18 c 0,1.1 -0.9,2 -2,2 z" + id="path1778" /><path + fill="#fbfbfb" + d="M 30,27.4 H 2 c -1.1,0 -2,-0.9 -2,-2 v -17 c 0,-1.1 0.9,-2 2,-2 h 28 c 1.1,0 2,0.9 2,2 v 17 c 0,1.1 -0.9,2 -2,2 z" + id="path1780" /><path + id="path11889" + style="color:#000000;fill:#585858;fill-opacity:1;stroke-width:0.999994;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill" + d="m 11.520289,8.4637512 c -0.06474,-0.00183 -0.129661,-0.00125 -0.194234,0.00117 C 9.7763279,8.5230552 8.3049,9.7900155 8.3049,11.461507 v 10.877094 c -6e-7,2.228655 2.616628,3.738089 4.545774,2.622156 l 9.398109,-5.436205 c 1.928423,-1.115516 1.928423,-4.133479 0,-5.248993 L 12.850674,8.839348 C 12.428673,8.595238 11.973493,8.4765655 11.520289,8.4637512 Z m -0.184873,1.2309276 c 0.307885,1.456e-4 0.612521,0.080796 0.882242,0.2363567 a 0.89871379,0.89871379 0 0 0 0.0012,0 l 9.398109,5.4362075 c 1.143234,0.659415 1.143234,2.406201 0,3.065618 l -9.398109,5.436206 a 0.89871379,0.89871379 0 0 0 -0.0012,0 C 11.076744,24.528497 9.5659235,23.656375 9.56625,22.338599 V 11.461504 c 3.043e-4,-0.851902 0.622381,-1.5925143 1.461434,-1.7399133 0.102209,-0.018038 0.205103,-0.026958 0.307732,-0.026912 z" /></svg> diff --git a/launcher/resources/OSX/scalable/launcher.svg b/launcher/resources/OSX/scalable/launcher.svg index 69dd84b1..aeee8433 100644 --- a/launcher/resources/OSX/scalable/launcher.svg +++ b/launcher/resources/OSX/scalable/launcher.svg @@ -37,17 +37,21 @@ </cc:Agent> </dc:contributor> <dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source> - <dc:rights> - <cc:Agent> - <dc:title>CC BY-SA 4.0</dc:title> - </cc:Agent> - </dc:rights> <dc:publisher> <cc:Agent> <dc:title>Prism Launcher</dc:title> </cc:Agent> </dc:publisher> + <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/> </cc:Work> + <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/> + </cc:License> </rdf:RDF> </metadata> </svg> diff --git a/launcher/resources/backgrounds/backgrounds.qrc b/launcher/resources/backgrounds/backgrounds.qrc index 52921512..652e7084 100644 --- a/launcher/resources/backgrounds/backgrounds.qrc +++ b/launcher/resources/backgrounds/backgrounds.qrc @@ -1,8 +1,15 @@ <!DOCTYPE RCC> <RCC version="1.0"> <qresource prefix="/backgrounds"> - <file alias="kitteh">catbgrnd2.png</file> - <file alias="catmas">catmas.png</file> - <file alias="cattiversary">cattiversary.png</file> + <file alias="kitteh">kitteh.png</file> + <file alias="kitteh-xmas">kitteh-xmas.png</file> + <file alias="kitteh-bday">kitteh-bday.png</file> + <file alias="kitteh-ween">kitteh-ween.png</file> + <file alias="rory">rory.png</file> + <file alias="rory-xmas">rory-xmas.png</file> + <file alias="rory-bday">rory-bday.png</file> + <file alias="rory-flat">rory-flat.png</file> + <file alias="rory-flat-xmas">rory-flat-xmas.png</file> + <file alias="rory-flat-bday">rory-flat-bday.png</file> </qresource> </RCC> diff --git a/launcher/resources/backgrounds/cattiversary.png b/launcher/resources/backgrounds/kitteh-bday.png Binary files differindex 09a36566..09a36566 100644 --- a/launcher/resources/backgrounds/cattiversary.png +++ b/launcher/resources/backgrounds/kitteh-bday.png diff --git a/launcher/resources/backgrounds/kitteh-ween.png b/launcher/resources/backgrounds/kitteh-ween.png Binary files differnew file mode 100644 index 00000000..deb0bebb --- /dev/null +++ b/launcher/resources/backgrounds/kitteh-ween.png diff --git a/launcher/resources/backgrounds/catmas.png b/launcher/resources/backgrounds/kitteh-xmas.png Binary files differindex 8bdb1d5c..8bdb1d5c 100644 --- a/launcher/resources/backgrounds/catmas.png +++ b/launcher/resources/backgrounds/kitteh-xmas.png diff --git a/launcher/resources/backgrounds/catbgrnd2.png b/launcher/resources/backgrounds/kitteh.png Binary files differindex e9de7f27..e9de7f27 100644 --- a/launcher/resources/backgrounds/catbgrnd2.png +++ b/launcher/resources/backgrounds/kitteh.png diff --git a/launcher/resources/backgrounds/rory-bday.png b/launcher/resources/backgrounds/rory-bday.png Binary files differnew file mode 100644 index 00000000..66b88094 --- /dev/null +++ b/launcher/resources/backgrounds/rory-bday.png diff --git a/launcher/resources/backgrounds/rory-flat-bday.png b/launcher/resources/backgrounds/rory-flat-bday.png Binary files differnew file mode 100644 index 00000000..8a6e366d --- /dev/null +++ b/launcher/resources/backgrounds/rory-flat-bday.png diff --git a/launcher/resources/backgrounds/rory-flat-xmas.png b/launcher/resources/backgrounds/rory-flat-xmas.png Binary files differnew file mode 100644 index 00000000..96c3ae38 --- /dev/null +++ b/launcher/resources/backgrounds/rory-flat-xmas.png diff --git a/launcher/resources/backgrounds/rory-flat.png b/launcher/resources/backgrounds/rory-flat.png Binary files differnew file mode 100644 index 00000000..ccec0662 --- /dev/null +++ b/launcher/resources/backgrounds/rory-flat.png diff --git a/launcher/resources/backgrounds/rory-xmas.png b/launcher/resources/backgrounds/rory-xmas.png Binary files differnew file mode 100644 index 00000000..107feb78 --- /dev/null +++ b/launcher/resources/backgrounds/rory-xmas.png diff --git a/launcher/resources/backgrounds/rory.png b/launcher/resources/backgrounds/rory.png Binary files differnew file mode 100644 index 00000000..577f4dce --- /dev/null +++ b/launcher/resources/backgrounds/rory.png diff --git a/launcher/resources/flat/flat.qrc b/launcher/resources/flat/flat.qrc index 7f59da7b..508e0a9f 100644 --- a/launcher/resources/flat/flat.qrc +++ b/launcher/resources/flat/flat.qrc @@ -46,5 +46,6 @@ <file>scalable/tag.svg</file> <file>scalable/export.svg</file> <file>scalable/rename.svg</file> + <file>scalable/launch.svg</file> </qresource> </RCC> diff --git a/launcher/resources/flat/scalable/launch.svg b/launcher/resources/flat/scalable/launch.svg new file mode 100644 index 00000000..b462f2e4 --- /dev/null +++ b/launcher/resources/flat/scalable/launch.svg @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + fill="#757575" + height="48" + width="48" + version="1.1" + id="svg24108" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs24112" /> + <path + d="M 11.674384,43.35533 V 4.3446706 L 42.325617,23.850001 Z" + id="path24106" + style="stroke-width:1" /> +</svg> diff --git a/launcher/resources/flat/scalable/launcher.svg b/launcher/resources/flat/scalable/launcher.svg index 69dd84b1..aeee8433 100644 --- a/launcher/resources/flat/scalable/launcher.svg +++ b/launcher/resources/flat/scalable/launcher.svg @@ -37,17 +37,21 @@ </cc:Agent> </dc:contributor> <dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source> - <dc:rights> - <cc:Agent> - <dc:title>CC BY-SA 4.0</dc:title> - </cc:Agent> - </dc:rights> <dc:publisher> <cc:Agent> <dc:title>Prism Launcher</dc:title> </cc:Agent> </dc:publisher> + <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/> </cc:Work> + <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/> + </cc:License> </rdf:RDF> </metadata> </svg> diff --git a/launcher/resources/flat_white/flat_white.qrc b/launcher/resources/flat_white/flat_white.qrc new file mode 100644 index 00000000..e11d6316 --- /dev/null +++ b/launcher/resources/flat_white/flat_white.qrc @@ -0,0 +1,51 @@ +<!DOCTYPE RCC> +<RCC version="1.0"> + <qresource prefix="/icons/flat_white"> + <file>index.theme</file> + <file>scalable/about.svg</file> + <file>scalable/accounts.svg</file> + <file>scalable/bug.svg</file> + <file>scalable/cat.svg</file> + <file>scalable/centralmods.svg</file> + <file>scalable/checkupdate.svg</file> + <file>scalable/copy.svg</file> + <file>scalable/coremods.svg</file> + <file>scalable/custom-commands.svg</file> + <file>scalable/discord.svg</file> + <file>scalable/externaltools.svg</file> + <file>scalable/help.svg</file> + <file>scalable/instance-settings.svg</file> + <file>scalable/jarmods.svg</file> + <file>scalable/java.svg</file> + <file>scalable/language.svg</file> + <file>scalable/launcher.svg</file> + <file>scalable/loadermods.svg</file> + <file>scalable/log.svg</file> + <file>scalable/minecraft.svg</file> + <file>scalable/new.svg</file> + <file>scalable/news.svg</file> + <file>scalable/notes.svg</file> + <file>scalable/packages.svg</file> + <file>scalable/proxy.svg</file> + <file>scalable/quickmods.svg</file> + <file>scalable/reddit-alien.svg</file> + <file>scalable/refresh.svg</file> + <file>scalable/resourcepacks.svg</file> + <file>scalable/shaderpacks.svg</file> + <file>scalable/screenshot-placeholder.svg</file> + <file>scalable/screenshots.svg</file> + <file>scalable/settings.svg</file> + <file>scalable/star.svg</file> + <file>scalable/status-bad.svg</file> + <file>scalable/status-good.svg</file> + <file>scalable/status-running.svg</file> + <file>scalable/status-yellow.svg</file> + <file>scalable/viewfolder.svg</file> + <file>scalable/worlds.svg</file> + <file>scalable/delete.svg</file> + <file>scalable/export.svg</file> + <file>scalable/rename.svg</file> + <file>scalable/tag.svg</file> + <file>scalable/launch.svg</file> + </qresource> +</RCC> diff --git a/launcher/resources/flat_white/index.theme b/launcher/resources/flat_white/index.theme new file mode 100644 index 00000000..54dd0e10 --- /dev/null +++ b/launcher/resources/flat_white/index.theme @@ -0,0 +1,11 @@ +[Icon Theme] +Name=Flat (White) +Comment=White version of the flat icons (dark mode) +Inherits=multimc +Directories=scalable + +[scalable] +Size=48 +Type=Scalable +MinSize=16 +MaxSize=256 diff --git a/launcher/resources/flat_white/scalable/about.svg b/launcher/resources/flat_white/scalable/about.svg new file mode 100644 index 00000000..e42ca948 --- /dev/null +++ b/launcher/resources/flat_white/scalable/about.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/accounts.svg b/launcher/resources/flat_white/scalable/accounts.svg new file mode 100644 index 00000000..e714bde1 --- /dev/null +++ b/launcher/resources/flat_white/scalable/accounts.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M16,13C15.71,13 15.38,13 15.03,13.05C16.19,13.89 17,15 17,16.5V19H23V16.5C23,14.17 18.33,13 16,13M8,13C5.67,13 1,14.17 1,16.5V19H15V16.5C15,14.17 10.33,13 8,13M8,11A3,3 0 0,0 11,8A3,3 0 0,0 8,5A3,3 0 0,0 5,8A3,3 0 0,0 8,11M16,11A3,3 0 0,0 19,8A3,3 0 0,0 16,5A3,3 0 0,0 13,8A3,3 0 0,0 16,11Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/bug.svg b/launcher/resources/flat_white/scalable/bug.svg new file mode 100644 index 00000000..3122702e --- /dev/null +++ b/launcher/resources/flat_white/scalable/bug.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/cat.svg b/launcher/resources/flat_white/scalable/cat.svg new file mode 100644 index 00000000..18da097a --- /dev/null +++ b/launcher/resources/flat_white/scalable/cat.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M12,8L10.67,8.09C9.81,7.07 7.4,4.5 5,4.5C5,4.5 3.03,7.46 4.96,11.41C4.41,12.24 4.07,12.67 4,13.66L2.07,13.95L2.28,14.93L4.04,14.67L4.18,15.38L2.61,16.32L3.08,17.21L4.53,16.32C5.68,18.76 8.59,20 12,20C15.41,20 18.32,18.76 19.47,16.32L20.92,17.21L21.39,16.32L19.82,15.38L19.96,14.67L21.72,14.93L21.93,13.95L20,13.66C19.93,12.67 19.59,12.24 19.04,11.41C20.97,7.46 19,4.5 19,4.5C16.6,4.5 14.19,7.07 13.33,8.09L12,8M9,11A1,1 0 0,1 10,12A1,1 0 0,1 9,13A1,1 0 0,1 8,12A1,1 0 0,1 9,11M15,11A1,1 0 0,1 16,12A1,1 0 0,1 15,13A1,1 0 0,1 14,12A1,1 0 0,1 15,11M11,14H13L12.3,15.39C12.5,16.03 13.06,16.5 13.75,16.5A1.5,1.5 0 0,0 15.25,15H15.75A2,2 0 0,1 13.75,17C13,17 12.35,16.59 12,16V16H12C11.65,16.59 11,17 10.25,17A2,2 0 0,1 8.25,15H8.75A1.5,1.5 0 0,0 10.25,16.5C10.94,16.5 11.5,16.03 11.7,15.39L11,14Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/centralmods.svg b/launcher/resources/flat_white/scalable/centralmods.svg new file mode 100644 index 00000000..d8d10f2f --- /dev/null +++ b/launcher/resources/flat_white/scalable/centralmods.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-2.06 11L15 15.28 12.06 17l.78-3.33-2.59-2.24 3.41-.29L15 8l1.34 3.14 3.41.29-2.59 2.24.78 3.33z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/checkupdate.svg b/launcher/resources/flat_white/scalable/checkupdate.svg new file mode 100644 index 00000000..0fa66fc2 --- /dev/null +++ b/launcher/resources/flat_white/scalable/checkupdate.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.73 2.71-2.73 7.08 0 9.79 2.73 2.71 7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-12.58 3.51-3.47 9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V8h1.5z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/copy.svg b/launcher/resources/flat_white/scalable/copy.svg new file mode 100644 index 00000000..1aaed97b --- /dev/null +++ b/launcher/resources/flat_white/scalable/copy.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/coremods.svg b/launcher/resources/flat_white/scalable/coremods.svg new file mode 100644 index 00000000..32c34383 --- /dev/null +++ b/launcher/resources/flat_white/scalable/coremods.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M22,12A10,10,0,1,1,12,2,10,10,0,0,1,22,12ZM12,4a8,8,0,1,0,8,8A8,8,0,0,0,12,4Zm4.23,14-1.12-4.82,3.73-3.23-4.92-.42L12,5,10.08,9.54,5.16,10l3.73,3.23L7.77,18,12,15.45,16.23,18"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/custom-commands.svg b/launcher/resources/flat_white/scalable/custom-commands.svg new file mode 100644 index 00000000..3d67d8f1 --- /dev/null +++ b/launcher/resources/flat_white/scalable/custom-commands.svg @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + fill="#D8DEE9" + height="24" + viewBox="0 0 24 24" + width="24" + version="1.1" + id="svg4" + sodipodi:docname="custom-commands.svg" + inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="3440" + inkscape:window-height="1382" + id="namedview6" + showgrid="true" + showguides="true" + inkscape:guide-bbox="true" + inkscape:zoom="39.333333" + inkscape:cx="11.38983" + inkscape:cy="13.283898" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:pagecheckerboard="0"> + <inkscape:grid + type="xygrid" + id="grid981" /> + <sodipodi:guide + position="-8,11.440678" + orientation="1,0" + id="guide1060" + inkscape:locked="false" /> + <sodipodi:guide + position="-28.34375,24" + orientation="0,1" + id="guide1062" + inkscape:locked="false" /> + </sodipodi:namedview> + <g + style="fill:#000000" + id="g821" + transform="matrix(0.0322459,0,0,0.0322459,-17.878956,30.647558)"> + <g + style="fill:#000000" + id="g819" /> + </g> + <g + id="g503"> + <path + d="M 0,0 H 24 V 24 H 0 Z" + fill="none" + id="path491" /> + <path + d="M 8.7,15.9 4.8,12 8.7,8.1 C 9.09,7.71 9.09,7.09 8.7,6.7 8.31,6.31 7.69,6.31 7.3,6.7 l -4.59,4.59 c -0.39,0.39 -0.39,1.02 0,1.41 l 4.59,4.6 c 0.39,0.39 1.01,0.39 1.4,0 0.39,-0.39 0.39,-1.01 0,-1.4 z m 6.6,0 3.9,-3.9 -3.9,-3.9 c -0.39,-0.39 -0.39,-1.01 0,-1.4 0.39,-0.39 1.01,-0.39 1.4,0 l 4.59,4.59 c 0.39,0.39 0.39,1.02 0,1.41 l -4.59,4.6 c -0.39,0.39 -1.01,0.39 -1.4,0 -0.39,-0.39 -0.39,-1.01 0,-1.4 z" + id="path493" /> + </g> +</svg> diff --git a/launcher/resources/flat_white/scalable/delete.svg b/launcher/resources/flat_white/scalable/delete.svg new file mode 100644 index 00000000..3365a96f --- /dev/null +++ b/launcher/resources/flat_white/scalable/delete.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" version="1.1" id="svg4" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> + <defs id="defs8"/> + <path id="path5145" style="fill:#D8DEE9;fill-opacity:1;stroke:none;stroke-width:1.4;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none" d="M 7.1074219 0.96484375 L 7.1074219 2.7304688 L 2.6132812 2.7304688 L 2.6132812 4.4960938 L 21.386719 4.4960938 L 21.386719 2.7304688 L 16.892578 2.7304688 L 16.892578 0.96484375 L 7.1074219 0.96484375 z M 5.0058594 6.0839844 L 5.0058594 22.859375 L 18.994141 22.859375 L 18.994141 6.0839844 L 5.0058594 6.0839844 z M 7.9160156 9.0605469 L 10.193359 9.0605469 L 10.193359 19.882812 L 7.9160156 19.882812 L 7.9160156 9.0605469 z M 13.804688 9.0605469 L 16.085938 9.0605469 L 16.085938 19.882812 L 13.804688 19.882812 L 13.804688 9.0605469 z "/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/discord.svg b/launcher/resources/flat_white/scalable/discord.svg new file mode 100644 index 00000000..ee07ed25 --- /dev/null +++ b/launcher/resources/flat_white/scalable/discord.svg @@ -0,0 +1,4 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M10.14,11.63a1.15,1.15,0,1,0,1,1.14A1.1,1.1,0,0,0,10.14,11.63Zm3.75,0a1.15,1.15,0,1,0,1,1.14A1.1,1.1,0,0,0,13.89,11.63Z"/> + <path d="M18.89,3H5.11A2.11,2.11,0,0,0,3,5.12V19a2.11,2.11,0,0,0,2.11,2.12H16.77l-.55-1.9,1.32,1.22,1.24,1.15,2.21,2V5.12A2.11,2.11,0,0,0,18.89,3Zm-4,13.43s-.37-.44-.68-.83a3.25,3.25,0,0,0,1.86-1.22,5.89,5.89,0,0,1-1.18.61,6.77,6.77,0,0,1-1.49.44,7.21,7.21,0,0,1-2.66,0A8.63,8.63,0,0,1,9.25,15a6,6,0,0,1-.75-.35l-.09-.05,0,0-.29-.17a3.2,3.2,0,0,0,1.8,1.21l-.69.85a3.73,3.73,0,0,1-3.14-1.56,13.77,13.77,0,0,1,1.48-6,5.09,5.09,0,0,1,2.89-1.08l.1.12A6.94,6.94,0,0,0,7.82,9.26s.23-.12.61-.3a7.72,7.72,0,0,1,2.33-.65l.17,0a8.7,8.7,0,0,1,2.08,0,8.38,8.38,0,0,1,3.1,1A6.85,6.85,0,0,0,13.55,8l.14-.16a5.09,5.09,0,0,1,2.89,1.08,13.77,13.77,0,0,1,1.48,6A3.76,3.76,0,0,1,14.92,16.43Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/export.svg b/launcher/resources/flat_white/scalable/export.svg new file mode 100644 index 00000000..a28bb254 --- /dev/null +++ b/launcher/resources/flat_white/scalable/export.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" version="1.1" id="svg4" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> + <defs id="defs8"/> + <path id="path2" d="M 4 4 C 2.9000011 4 2.0097656 4.9000011 2.0097656 6 L 2 18 C 2 19.099999 2.9000011 20 4 20 L 20 20 C 21.099999 20 22 19.099999 22 18 L 22 8 C 22 6.9000011 21.099999 6 20 6 L 12 6 L 10 4 L 4 4 z M 12.537109 9.9082031 L 13.185547 10.298828 L 17.554688 12.929688 L 13.185547 15.5625 L 12.537109 15.953125 L 11.755859 14.65625 L 12.404297 14.265625 L 13.349609 13.695312 L 6.4453125 13.695312 L 6.4453125 12.166016 L 13.351562 12.166016 L 12.404297 11.595703 L 11.755859 11.205078 L 12.537109 9.9082031 z "/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/externaltools.svg b/launcher/resources/flat_white/scalable/externaltools.svg new file mode 100644 index 00000000..e7c0930c --- /dev/null +++ b/launcher/resources/flat_white/scalable/externaltools.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M22.7,19L13.6,9.9C14.5,7.6 14,4.9 12.1,3C10.1,1 7.1,0.6 4.7,1.7L9,6L6,9L1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1C4.8,14 7.5,14.5 9.8,13.6L18.9,22.7C19.3,23.1 19.9,23.1 20.3,22.7L22.6,20.4C23.1,20 23.1,19.3 22.7,19Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/help.svg b/launcher/resources/flat_white/scalable/help.svg new file mode 100644 index 00000000..82b413fe --- /dev/null +++ b/launcher/resources/flat_white/scalable/help.svg @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + id="svg4" + version="1.1" + width="24" + viewBox="0 0 24 24" + height="24" + fill="#D8DEE9"> + <path + d="m 15.07,11.25 -0.9,0.92 C 13.45,12.89 13,13.5 13,15 h -2 v -0.5 c 0,-1.11 0.45,-2.11 1.17,-2.83 l 1.24,-1.26 C 13.78,10.049999 14,9.549999 14,9 14,7.89 13.100001,7 12,7 A 2,2 0 0 0 10,9 H 7.9999995 A 4,4 0 0 1 12,5 4,4 0 0 1 16,9 c 0,0.879999 -0.36,1.67 -0.93,2.25 M 13,19 h -2 v -2 h 2 M 12,2 A 10,10 0 0 0 1.9999995,12 10,10 0 0 0 12,22 10,10 0 0 0 22,12 C 22,6.47 17.5,2 12,2 Z" + id="path817" /> +</svg> diff --git a/launcher/resources/flat_white/scalable/instance-settings.svg b/launcher/resources/flat_white/scalable/instance-settings.svg new file mode 100644 index 00000000..7dac7b14 --- /dev/null +++ b/launcher/resources/flat_white/scalable/instance-settings.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/jarmods.svg b/launcher/resources/flat_white/scalable/jarmods.svg new file mode 100644 index 00000000..f0f298f3 --- /dev/null +++ b/launcher/resources/flat_white/scalable/jarmods.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M2,21H20V19H2M20,8H18V5h2m0-2H4V13a4,4,0,0,0,4,4h6a4,4,0,0,0,4-4V10h2a2,2,0,0,0,2-2V5A2,2,0,0,0,20,3ZM11,4.43l1.62,3.29,3.63.53-2.63,2.56.62,3.62L11,12.72,7.75,14.43l.62-3.62L5.74,8.25l3.63-.53Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/java.svg b/launcher/resources/flat_white/scalable/java.svg new file mode 100644 index 00000000..56bb481f --- /dev/null +++ b/launcher/resources/flat_white/scalable/java.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M2,21H20V19H2M20,8H18V5H20M20,3H4V13A4,4 0 0,0 8,17H14A4,4 0 0,0 18,13V10H20A2,2 0 0,0 22,8V5C22,3.89 21.1,3 20,3Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/language.svg b/launcher/resources/flat_white/scalable/language.svg new file mode 100644 index 00000000..18c22efb --- /dev/null +++ b/launcher/resources/flat_white/scalable/language.svg @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + fill="#D8DEE9" + height="24" + viewBox="0 0 24 24" + width="24" + version="1.1" + id="svg4" + sodipodi:docname="language.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8"> + + + + + + + + + + + + + + + + + + + + + + + </defs> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="3840" + inkscape:window-height="2123" + id="namedview6" + showgrid="true" + showguides="true" + inkscape:guide-bbox="true" + inkscape:zoom="6.9532167" + inkscape:cx="-18.49351" + inkscape:cy="-12.477971" + inkscape:window-x="1200" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4"> + <inkscape:grid + type="xygrid" + id="grid981" /> + <sodipodi:guide + position="-8,11.440678" + orientation="1,0" + id="guide1060" + inkscape:locked="false" /> + <sodipodi:guide + position="-28.34375,24" + orientation="0,1" + id="guide1062" + inkscape:locked="false" /> + </sodipodi:namedview> + <path + d="M 5,3 C 3.89,3 3,3.89 3,5 v 14 c 0,1.104569 0.895431,2 2,2 h 14 c 1.104569,0 2,-0.895431 2,-2 V 5 C 21,3.89 20.1,3 19,3 Z m 10.359375,4.505859 c 0.400344,0 0.726563,0.326845 0.726563,0.728516 v 0.724609 h 2.21875 c 0.400344,0 0.726562,0.326845 0.726562,0.728516 0,0.401669 -0.326217,0.726562 -0.726562,0.726562 h -0.191407 c -0.412128,1.326612 -1.066893,2.363281 -1.746093,3.181641 0.53207,0.488052 1.100334,0.887517 1.666015,1.335938 0.311924,0.250518 0.365651,0.709744 0.115235,1.023437 -0.249259,0.313205 -0.708226,0.362473 -1.019532,0.111328 -0.614642,-0.486742 -1.192601,-0.892661 -1.769531,-1.423828 -0.576929,0.531167 -1.104107,0.937086 -1.71875,1.423828 -0.311303,0.251148 -0.768322,0.201879 -1.017578,-0.111328 -0.250416,-0.313693 -0.200604,-0.772919 0.111328,-1.023437 0.565677,-0.448421 1.087072,-0.847886 1.619141,-1.335938 -0.679199,-0.818312 -1.283234,-1.854981 -1.695313,-3.181641 h -0.197265 c -0.400344,0 -0.720704,-0.324893 -0.720704,-0.726562 0,-0.401671 0.320361,-0.728516 0.720704,-0.728516 h 2.173828 V 8.234375 c 0,-0.401671 0.324264,-0.728516 0.724609,-0.728516 z M 7.142578,7.800781 h 1.496094 c 0.345155,0 0.643047,0.243927 0.710937,0.582031 l 1.447266,7.244141 c 0.07851,0.39257 -0.174512,0.773053 -0.566406,0.851563 -0.384074,0.07905 -0.774336,-0.168718 -0.853516,-0.566407 L 8.914062,13.595703 H 6.867188 L 6.402344,15.912109 C 6.324551,16.303955 5.947553,16.559826 5.550781,16.478516 5.158934,16.400005 4.905865,16.019523 4.984375,15.626953 L 6.431641,8.382812 C 6.499536,8.044708 6.797425,7.800781 7.142578,7.800781 Z m 0.4375,1.632813 -0.578125,2.898437 H 8.46875 L 7.890625,9.433594 Z m 6.589844,0.980468 c 0.312752,0.842923 0.729088,1.524886 1.189453,2.105469 0.460366,-0.580583 0.925527,-1.262594 1.238281,-2.105469 z" + id="path1072" + inkscape:connector-curvature="0" /> + <g + style="fill:#000000" + id="g821" + transform="matrix(0.0322459,0,0,0.0322459,-17.878956,30.647558)"> + <g + style="fill:#000000" + id="g819" /> + </g> +</svg> diff --git a/launcher/resources/flat_white/scalable/launch.svg b/launcher/resources/flat_white/scalable/launch.svg new file mode 100644 index 00000000..9e759431 --- /dev/null +++ b/launcher/resources/flat_white/scalable/launch.svg @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + fill="#D8DEE9" + height="48" + width="48" + version="1.1" + id="svg24108" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs24112" /> + <path + d="M 11.674384,43.35533 V 4.3446706 L 42.325617,23.850001 Z" + id="path24106" + style="stroke-width:1" /> +</svg> diff --git a/launcher/resources/flat_white/scalable/launcher.svg b/launcher/resources/flat_white/scalable/launcher.svg new file mode 100644 index 00000000..d7ad0dd3 --- /dev/null +++ b/launcher/resources/flat_white/scalable/launcher.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="24" height="24" fill="#D8DEE9" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m20 4h-16v16h16zm0 18h-16c-1.1046 0-2-0.89543-2-2v-16c0-1.1046 0.89543-2 2-2h16c1.1046 0 2 0.89543 2 2v16c0 1.1046-0.89543 2-2 2z"/><path d="m7.2 18c-0.225 0-0.45-0.075-0.6-0.15-0.375-0.225-0.6-0.6-0.6-1.05v-9.6c0-0.45 0.225-0.825 0.6-1.05 0.225-0.15 0.375-0.15 0.6-0.15 0.15 0 0.375 0.075 0.525 0.15l9.6 4.8c0.375 0.225 0.675 0.6 0.675 1.05 0 0.45-0.225 0.9-0.675 1.05l-9.6 4.8c-0.15 0.075-0.375 0.15-0.525 0.15z" clip-rule="evenodd" fill="#D8DEE9" fill-rule="evenodd" stroke-width=".99999"/></svg> diff --git a/launcher/resources/flat_white/scalable/loadermods.svg b/launcher/resources/flat_white/scalable/loadermods.svg new file mode 100644 index 00000000..100f7a93 --- /dev/null +++ b/launcher/resources/flat_white/scalable/loadermods.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M16.23,18l-1.12-4.82,3.73-3.23-4.92-.42L12,5,10.08,9.54,5.16,10l3.73,3.23L7.77,18,12,15.45,16.23,18M20,4H4V20H20Zm0,18H4a2,2,0,0,1-2-2V4A2,2,0,0,1,4,2H20a2,2,0,0,1,2,2V20A2,2,0,0,1,20,22Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/log.svg b/launcher/resources/flat_white/scalable/log.svg new file mode 100644 index 00000000..69b7c1dc --- /dev/null +++ b/launcher/resources/flat_white/scalable/log.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/minecraft.svg b/launcher/resources/flat_white/scalable/minecraft.svg new file mode 100644 index 00000000..a0348e79 --- /dev/null +++ b/launcher/resources/flat_white/scalable/minecraft.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L6.04,7.5L12,10.85L17.96,7.5L12,4.15M5,15.91L11,19.29V12.58L5,9.21V15.91M19,15.91V9.21L13,12.58V19.29L19,15.91Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/multimc.svg b/launcher/resources/flat_white/scalable/multimc.svg new file mode 100644 index 00000000..3dce2699 --- /dev/null +++ b/launcher/resources/flat_white/scalable/multimc.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M0,2A2,2,0,0,1,2,0H22a2,2,0,0,1,2,2V8L22,8V6H20V8H18v2H16V8H14V6H12V8H10V6H8v4H6V8H4V6H2V8H0ZM0,22a2,2,0,0,0,2,2H22a2,2,0,0,0,2-2V10H22V22H2V10H0Zm18.71-3.29a3.83,3.83,0,0,0-5.41-5.41L12,14.59l-1.29-1.29a3.83,3.83,0,1,0,0,5.41L12,17.41l1.29,1.29a3.83,3.83,0,0,0,5.41,0Zm-4-4a1.83,1.83,0,1,1,0,2.59L13.41,16Zm-5.41,0L10.59,16,9.29,17.29a1.83,1.83,0,1,1,0-2.59Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/new.svg b/launcher/resources/flat_white/scalable/new.svg new file mode 100644 index 00000000..46dc3361 --- /dev/null +++ b/launcher/resources/flat_white/scalable/new.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/news.svg b/launcher/resources/flat_white/scalable/news.svg new file mode 100644 index 00000000..414e5454 --- /dev/null +++ b/launcher/resources/flat_white/scalable/news.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M20,11H4V8H20M20,15H13V13H20M20,19H13V17H20M11,19H4V13H11M20.33,4.67L18.67,3L17,4.67L15.33,3L13.67,4.67L12,3L10.33,4.67L8.67,3L7,4.67L5.33,3L3.67,4.67L2,3V19A2,2 0 0,0 4,21H20A2,2 0 0,0 22,19V3L20.33,4.67Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/notes.svg b/launcher/resources/flat_white/scalable/notes.svg new file mode 100644 index 00000000..4ce5f6f1 --- /dev/null +++ b/launcher/resources/flat_white/scalable/notes.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M14,17H7V15H14M17,13H7V11H17M17,9H7V7H17M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/packages.svg b/launcher/resources/flat_white/scalable/packages.svg new file mode 100644 index 00000000..909ad0b2 --- /dev/null +++ b/launcher/resources/flat_white/scalable/packages.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M5.12,5l.81-1h12l.94,1m1.67.23L19.15,3.55A1.45,1.45,0,0,0,18,3H6a1.49,1.49,0,0,0-1.16.55L3.46,5.23A1.92,1.92,0,0,0,3,6.5V19a2,2,0,0,0,2,2H19a2,2,0,0,0,2-2V6.5A1.92,1.92,0,0,0,20.54,5.23Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/patreon.svg b/launcher/resources/flat_white/scalable/patreon.svg new file mode 100644 index 00000000..b745765b --- /dev/null +++ b/launcher/resources/flat_white/scalable/patreon.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M12,3h0a9,9,0,0,0-9,9v9H5.09V12a6.91,6.91,0,1,1,7.23,6.9,5.9,5.9,0,0,1-2.59-.47v-3A4.13,4.13,0,1,0,7.85,12v9H12A9,9,0,1,0,12,3Zm0,15.91h0Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/proxy.svg b/launcher/resources/flat_white/scalable/proxy.svg new file mode 100644 index 00000000..a86703f4 --- /dev/null +++ b/launcher/resources/flat_white/scalable/proxy.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M22 4v-.5C22 2.12 20.88 1 19.5 1S17 2.12 17 3.5V4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zm-.8 0h-3.4v-.5c0-.94.76-1.7 1.7-1.7s1.7.76 1.7 1.7V4zm-2.28 8c.04.33.08.66.08 1 0 2.08-.8 3.97-2.1 5.39-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H7v-2h2c.55 0 1-.45 1-1V8h2c1.1 0 2-.9 2-2V3.46c-.95-.3-1.95-.46-3-.46C5.48 3 1 7.48 1 13s4.48 10 10 10 10-4.48 10-10c0-.34-.02-.67-.05-1h-2.03zM10 20.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L8 16v1c0 1.1.9 2 2 2v1.93z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/quickmods.svg b/launcher/resources/flat_white/scalable/quickmods.svg new file mode 100644 index 00000000..9e0045b2 --- /dev/null +++ b/launcher/resources/flat_white/scalable/quickmods.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M8.75,5.5v7.15H10.7V18.5l4.55-7.8h-2.6l2.6-5.2ZM20,4H4V20H20Zm0,18H4a2,2,0,0,1-2-2V4A2,2,0,0,1,4,2H20a2,2,0,0,1,2,2V20A2,2,0,0,1,20,22Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/reddit-alien.svg b/launcher/resources/flat_white/scalable/reddit-alien.svg new file mode 100644 index 00000000..be22148c --- /dev/null +++ b/launcher/resources/flat_white/scalable/reddit-alien.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M20,11.86a1.76,1.76,0,0,0-1.75-1.75,1.73,1.73,0,0,0-1.22.51,9,9,0,0,0-4.67-1.38l1-3.16L16,6.71s0,0,0,0a1.46,1.46,0,1,0,.1-.53l-2.89-.68a.25.25,0,0,0-.29.17L11.83,9.23a9.16,9.16,0,0,0-4.88,1.36,1.75,1.75,0,1,0-2.07,2.79,3,3,0,0,0-.06.58C4.82,16.58,8,18.7,12,18.7s7.14-2.13,7.14-4.74a2.94,2.94,0,0,0-.05-.55A1.74,1.74,0,0,0,20,11.86ZM8.51,13.08a1.06,1.06,0,1,1,1.06,1.06A1.06,1.06,0,0,1,8.51,13.08Zm6.06,3.14A3.48,3.48,0,0,1,12,17h0a3.48,3.48,0,0,1-2.56-.79.25.25,0,0,1,.35-.35,3,3,0,0,0,2.2.65h0a3,3,0,0,0,2.2-.65.25.25,0,1,1,.35.35Zm-.13-2.08a1.06,1.06,0,1,1,1.06-1.06A1.06,1.06,0,0,1,14.44,14.14Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/refresh.svg b/launcher/resources/flat_white/scalable/refresh.svg new file mode 100644 index 00000000..08c63bdf --- /dev/null +++ b/launcher/resources/flat_white/scalable/refresh.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/rename.svg b/launcher/resources/flat_white/scalable/rename.svg new file mode 100644 index 00000000..f2067c16 --- /dev/null +++ b/launcher/resources/flat_white/scalable/rename.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" version="1.1" id="svg4" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"><defs id="defs6"/> + +<path id="rect345" style="stroke-width:1.40001;stroke-linecap:square" d="m 16.944458,1.2305698 -2.249239,2.2492384 5.824973,5.8249729 2.249239,-2.2492385 a 0.74206194,0.74206194 90.000002 0 0 0,-1.0494341 L 17.993892,1.2305699 a 0.74206211,0.74206211 2.5523302e-6 0 0 -1.049434,-1e-7 z M 13.645389,4.5296385 3.5726925,14.602335 9.3976653,20.427306 19.470362,10.35461 Z M 2.5228612,15.652165 1.0244287,22.411695 a 0.47276304,0.47276304 44.999993 0 0 0.5638754,0.563875 l 6.75953,-1.498434 z"/></svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/resourcepacks.svg b/launcher/resources/flat_white/scalable/resourcepacks.svg new file mode 100644 index 00000000..9dd73c3a --- /dev/null +++ b/launcher/resources/flat_white/scalable/resourcepacks.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M19.51 3.08L3.08 19.51c.09.34.27.65.51.9.25.24.56.42.9.51L20.93 4.49c-.19-.69-.73-1.23-1.42-1.41zM11.88 3L3 11.88v2.83L14.71 3h-2.83zM5 3c-1.1 0-2 .9-2 2v2l4-4H5zm14 18c.55 0 1.05-.22 1.41-.59.37-.36.59-.86.59-1.41v-2l-4 4h2zm-9.71 0h2.83L21 12.12V9.29L9.29 21z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/screenshot-placeholder.svg b/launcher/resources/flat_white/scalable/screenshot-placeholder.svg new file mode 100644 index 00000000..41eb6fcf --- /dev/null +++ b/launcher/resources/flat_white/scalable/screenshot-placeholder.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M21 15h2v2h-2v-2zm0-4h2v2h-2v-2zm2 8h-2v2c1 0 2-1 2-2zM13 3h2v2h-2V3zm8 4h2v2h-2V7zm0-4v2h2c0-1-1-2-2-2zM1 7h2v2H1V7zm16-4h2v2h-2V3zm0 16h2v2h-2v-2zM3 3C2 3 1 4 1 5h2V3zm6 0h2v2H9V3zM5 3h2v2H5V3zm-4 8v8c0 1.1.9 2 2 2h12V11H1zm2 8l2.5-3.21 1.79 2.15 2.5-3.22L13 19H3z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/screenshots.svg b/launcher/resources/flat_white/scalable/screenshots.svg new file mode 100644 index 00000000..68cf8969 --- /dev/null +++ b/launcher/resources/flat_white/scalable/screenshots.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M21 3H3C2 3 1 4 1 5v14c0 1.1.9 2 2 2h18c1 0 2-1 2-2V5c0-1-1-2-2-2zM5 17l3.5-4.5 2.5 3.01L14.5 11l4.5 6H5z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/settings.svg b/launcher/resources/flat_white/scalable/settings.svg new file mode 100644 index 00000000..7dac7b14 --- /dev/null +++ b/launcher/resources/flat_white/scalable/settings.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/shaderpacks.svg b/launcher/resources/flat_white/scalable/shaderpacks.svg new file mode 100644 index 00000000..ccae221c --- /dev/null +++ b/launcher/resources/flat_white/scalable/shaderpacks.svg @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + fill="#D8DEE9" + height="24" + viewBox="0 0 24 24" + width="24" + version="1.1" + id="svg4" + sodipodi:docname="shaderpacks.svg" + inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="9.7227182" + inkscape:cx="16.302025" + inkscape:cy="3.1884088" + inkscape:window-width="3840" + inkscape:window-height="2129" + inkscape:window-x="1200" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4"> + <inkscape:grid + type="xygrid" + id="grid974" /> + </sodipodi:namedview> + <path + id="path2" + d="M 5 3 C 3.9 3 3 3.9 3 5 L 3 7 L 5 5 L 7 3 L 5 3 z M 11.880859 3 L 9.8808594 5 L 12.710938 5 L 14.710938 3 L 11.880859 3 z M 19.509766 3.0800781 L 17.589844 5 L 19 5 L 19 6.4179688 L 20.929688 4.4902344 C 20.739687 3.8002344 20.199766 3.2600781 19.509766 3.0800781 z M 21 9.2890625 L 19 11.289062 L 19 14.119141 L 21 12.119141 L 21 9.2890625 z M 5 9.8808594 L 3 11.880859 L 3 14.710938 L 5 12.710938 L 5 9.8808594 z M 21 17 L 19 19 L 17 21 L 19 21 C 19.55 21 20.050156 20.780156 20.410156 20.410156 C 20.780156 20.050156 21 19.55 21 19 L 21 17 z M 5 17.589844 L 3.0800781 19.509766 C 3.1700781 19.849766 3.3498438 20.160156 3.5898438 20.410156 C 3.8398438 20.650156 4.1502344 20.829922 4.4902344 20.919922 L 6.4121094 19 L 5 19 L 5 17.589844 z M 11.289062 19 L 9.2890625 21 L 12.119141 21 L 14.119141 19 L 11.289062 19 z " /> + <path + style="fill:none;fill-rule:evenodd;stroke:#D8DEE9;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" + d="m 7,9 v 8 h 8 V 9 Z" + id="path6727" + sodipodi:nodetypes="ccccc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#D8DEE9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" + d="M 7,9 9,7 h 8 l -2,2 z" + id="path7008" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#D8DEE9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" + d="m 17,7 v 8 l -2,2 V 9 Z" + id="path7010" + sodipodi:nodetypes="ccccc" /> +</svg> diff --git a/launcher/resources/flat_white/scalable/star.svg b/launcher/resources/flat_white/scalable/star.svg new file mode 100644 index 00000000..116f952e --- /dev/null +++ b/launcher/resources/flat_white/scalable/star.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M12,17.27L18.18,21L16.54,13.97L22,9.24L14.81,8.62L12,2L9.19,8.62L2,9.24L7.45,13.97L5.82,21L12,17.27Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/status-bad.svg b/launcher/resources/flat_white/scalable/status-bad.svg new file mode 100644 index 00000000..5a121c09 --- /dev/null +++ b/launcher/resources/flat_white/scalable/status-bad.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M12,2A10,10,0,1,0,22,12,10,10,0,0,0,12,2Zm4.24,7.17L13.41,12l2.83,2.83-1.41,1.41L12,13.41,9.17,16.24,7.76,14.83,10.59,12,7.76,9.17,9.17,7.76,12,10.59l2.83-2.83Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/status-good.svg b/launcher/resources/flat_white/scalable/status-good.svg new file mode 100644 index 00000000..ccb732ab --- /dev/null +++ b/launcher/resources/flat_white/scalable/status-good.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/status-running.svg b/launcher/resources/flat_white/scalable/status-running.svg new file mode 100644 index 00000000..aa2d5fbf --- /dev/null +++ b/launcher/resources/flat_white/scalable/status-running.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/status-yellow.svg b/launcher/resources/flat_white/scalable/status-yellow.svg new file mode 100644 index 00000000..772699d3 --- /dev/null +++ b/launcher/resources/flat_white/scalable/status-yellow.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/tag.svg b/launcher/resources/flat_white/scalable/tag.svg new file mode 100644 index 00000000..f91fb0b4 --- /dev/null +++ b/launcher/resources/flat_white/scalable/tag.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" version="1.1" id="svg4" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> + <path style="fill:#D8DEE9;fill-opacity:1;stroke:none;stroke-width:0.999999" d="M 12,2.4960934 2.5451968,2.5451969 2.4960933,12 12.791992,21.503907 21.503907,12.791992 Z M 8.0400388,5.6640622 c 1.3115393,0 2.3759772,1.0644375 2.3759772,2.3759766 0,1.3115391 -1.0644379,2.3759772 -2.3759772,2.3759772 -1.3115392,0 -2.3759767,-1.0644381 -2.3759767,-2.3759772 0,-1.3115391 1.0644375,-2.3759766 2.3759767,-2.3759766" class="ColorScheme-Text" id="path4838"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/viewfolder.svg b/launcher/resources/flat_white/scalable/viewfolder.svg new file mode 100644 index 00000000..145f8624 --- /dev/null +++ b/launcher/resources/flat_white/scalable/viewfolder.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/flat_white/scalable/worlds.svg b/launcher/resources/flat_white/scalable/worlds.svg new file mode 100644 index 00000000..cea30cf8 --- /dev/null +++ b/launcher/resources/flat_white/scalable/worlds.svg @@ -0,0 +1,3 @@ +<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M18.2,13a3.18,3.18,0,0,1-.84,2.16.8.8,0,0,0-.76-.56h-.4V13.4a.4.4,0,0,0-.4-.4H13.4v-.8h.8a.4.4,0,0,0,.4-.4V11h.8a.8.8,0,0,0,.8-.8V10A3.19,3.19,0,0,1,18.2,13Zm-4.4,1.6v-.4l-1.92-1.92a3.18,3.18,0,0,0,2.72,3.89V15.4A.8.8,0,0,1,13.8,14.6ZM22,8V18a2,2,0,0,1-2,2H4a2,2,0,0,1-2-2V6A2,2,0,0,1,4,4h6l2,2h8A2,2,0,0,1,22,8Zm-3,5a4,4,0,1,0-4,4A4,4,0,0,0,19,13Z"/> +</svg>
\ No newline at end of file diff --git a/launcher/resources/iOS/iOS.qrc b/launcher/resources/iOS/iOS.qrc index 1d752042..aa08d811 100644 --- a/launcher/resources/iOS/iOS.qrc +++ b/launcher/resources/iOS/iOS.qrc @@ -38,5 +38,6 @@ <file>scalable/tag.svg</file> <file>scalable/export.svg</file> <file>scalable/rename.svg</file> + <file>scalable/launch.svg</file> </qresource> </RCC> diff --git a/launcher/resources/iOS/scalable/launch.svg b/launcher/resources/iOS/scalable/launch.svg new file mode 100644 index 00000000..c16d5c37 --- /dev/null +++ b/launcher/resources/iOS/scalable/launch.svg @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + version="1.1" + id="Calque_1" + x="0px" + y="0px" + viewBox="0 0 32 32" + enable-background="new 0 0 32 32" + xml:space="preserve" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"><defs + id="defs45" /> + +<path + id="path11889" + style="color:#000000;fill:#3366cc;fill-opacity:1;stroke-width:0.999996;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill" + d="M 9.3515625 1.5410156 C 9.2434917 1.5379599 9.1351284 1.5389257 9.0273438 1.5429688 C 6.4405102 1.6400023 3.9843749 3.7548369 3.984375 6.5449219 L 3.984375 24.701172 C 3.9843742 28.421285 8.3520988 30.94086 11.572266 29.078125 L 27.259766 20.003906 C 30.478726 18.141866 30.478727 13.104225 27.259766 11.242188 L 11.572266 2.1679688 C 10.867854 1.7604958 10.108058 1.5624055 9.3515625 1.5410156 z M 9.0429688 3.5957031 C 9.5568946 3.5959458 10.065401 3.7305695 10.515625 3.9902344 A 1.50015 1.50015 0 0 0 10.517578 3.9902344 L 26.205078 13.064453 C 28.113387 14.165162 28.113387 17.080931 26.205078 18.181641 L 10.517578 27.255859 A 1.50015 1.50015 0 0 0 10.515625 27.255859 C 8.6111878 28.356592 6.0892988 26.90083 6.0898438 24.701172 L 6.0898438 6.5449219 C 6.090352 5.1229119 7.128734 3.8866658 8.5292969 3.640625 C 8.6999053 3.6105103 8.87166 3.5956222 9.0429688 3.5957031 z " /></svg> diff --git a/launcher/resources/iOS/scalable/launcher.svg b/launcher/resources/iOS/scalable/launcher.svg index 69dd84b1..aeee8433 100644 --- a/launcher/resources/iOS/scalable/launcher.svg +++ b/launcher/resources/iOS/scalable/launcher.svg @@ -37,17 +37,21 @@ </cc:Agent> </dc:contributor> <dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source> - <dc:rights> - <cc:Agent> - <dc:title>CC BY-SA 4.0</dc:title> - </cc:Agent> - </dc:rights> <dc:publisher> <cc:Agent> <dc:title>Prism Launcher</dc:title> </cc:Agent> </dc:publisher> + <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/> </cc:Work> + <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/> + </cc:License> </rdf:RDF> </metadata> </svg> diff --git a/launcher/resources/multimc/scalable/launcher.svg b/launcher/resources/multimc/scalable/launcher.svg index 69dd84b1..aeee8433 100644 --- a/launcher/resources/multimc/scalable/launcher.svg +++ b/launcher/resources/multimc/scalable/launcher.svg @@ -37,17 +37,21 @@ </cc:Agent> </dc:contributor> <dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source> - <dc:rights> - <cc:Agent> - <dc:title>CC BY-SA 4.0</dc:title> - </cc:Agent> - </dc:rights> <dc:publisher> <cc:Agent> <dc:title>Prism Launcher</dc:title> </cc:Agent> </dc:publisher> + <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/> </cc:Work> + <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/> + </cc:License> </rdf:RDF> </metadata> </svg> diff --git a/launcher/resources/pe_blue/pe_blue.qrc b/launcher/resources/pe_blue/pe_blue.qrc index 3d385713..3121ffe6 100644 --- a/launcher/resources/pe_blue/pe_blue.qrc +++ b/launcher/resources/pe_blue/pe_blue.qrc @@ -38,5 +38,6 @@ <file>scalable/tag.svg</file> <file>scalable/export.svg</file> <file>scalable/rename.svg</file> + <file>scalable/launch.svg</file> </qresource> </RCC> diff --git a/launcher/resources/pe_blue/scalable/launch.svg b/launcher/resources/pe_blue/scalable/launch.svg new file mode 100644 index 00000000..b3bd124f --- /dev/null +++ b/launcher/resources/pe_blue/scalable/launch.svg @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + version="1.1" + id="Calque_1" + x="0px" + y="0px" + viewBox="0 0 32 32" + enable-background="new 0 0 32 32" + xml:space="preserve" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"><defs + id="defs45" /> + +<path + style="color:#000000;fill:#3366cc;fill-opacity:1;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill;stroke:#3366cc;stroke-opacity:1" + d="M 25.454197,16.881861 9.7664963,25.956555 A 1.4501236,1.4501236 0 0 1 7.5902672,24.701314 V 6.544692 A 1.4501239,1.4501239 0 0 1 9.7664965,5.2894509 L 25.454196,14.364142 a 1.4543042,1.4543042 0 0 1 1e-6,2.517719 z" + id="path11891" /><path + style="color:#000000;fill:#daeeff;fill-opacity:1;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill" + d="M 25.454197,16.881861 9.7664962,25.956555 A 1.4501236,1.4501236 0 0 1 7.5902671,24.701314 V 6.544692 A 1.4501239,1.4501239 0 0 1 9.7664964,5.289451 l 15.6876996,9.074691 a 1.4543042,1.4543042 0 0 1 1e-6,2.517719 z" + id="path11897" /></svg> diff --git a/launcher/resources/pe_blue/scalable/launcher.svg b/launcher/resources/pe_blue/scalable/launcher.svg index 69dd84b1..aeee8433 100644 --- a/launcher/resources/pe_blue/scalable/launcher.svg +++ b/launcher/resources/pe_blue/scalable/launcher.svg @@ -37,17 +37,21 @@ </cc:Agent> </dc:contributor> <dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source> - <dc:rights> - <cc:Agent> - <dc:title>CC BY-SA 4.0</dc:title> - </cc:Agent> - </dc:rights> <dc:publisher> <cc:Agent> <dc:title>Prism Launcher</dc:title> </cc:Agent> </dc:publisher> + <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/> </cc:Work> + <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/> + </cc:License> </rdf:RDF> </metadata> </svg> diff --git a/launcher/resources/pe_colored/pe_colored.qrc b/launcher/resources/pe_colored/pe_colored.qrc index fa6cd9cd..ce5ad8e2 100644 --- a/launcher/resources/pe_colored/pe_colored.qrc +++ b/launcher/resources/pe_colored/pe_colored.qrc @@ -38,5 +38,6 @@ <file>scalable/tag.svg</file> <file>scalable/export.svg</file> <file>scalable/rename.svg</file> + <file>scalable/launch.svg</file> </qresource> </RCC> diff --git a/launcher/resources/pe_colored/scalable/launch.svg b/launcher/resources/pe_colored/scalable/launch.svg new file mode 100644 index 00000000..76713387 --- /dev/null +++ b/launcher/resources/pe_colored/scalable/launch.svg @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + version="1.1" + id="Calque_1" + x="0px" + y="0px" + viewBox="0 0 32 32" + enable-background="new 0 0 32 32" + xml:space="preserve" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"><defs + id="defs45" /> + +<path + style="color:#000000;fill:#8c6239;fill-opacity:1;stroke-width:0.999996;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill" + d="M 9.0277705,1.5430089 C 6.4409319,1.6400426 3.9852419,3.7549517 3.985242,6.5450423 V 24.700962 c -8e-7,3.720121 4.3665092,6.239738 7.586682,4.376999 l 15.687475,-9.074438 c 3.218968,-1.862044 3.218969,-6.899 0,-8.761041 L 11.571924,2.1680429 C 10.766881,1.7023586 9.8900501,1.5106643 9.0277705,1.5430089 Z m 2.1691325,8.7399131 9.231137,5.34008 -9.231137,5.34008 z" + id="path11889" /><path + id="path11895" + style="color:#000000;fill:#39b54a;fill-opacity:1;stroke-width:0.999996;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill" + d="M 9.3517318,1.541286 C 9.2436609,1.5382303 9.1355552,1.5390036 9.0277705,1.5430466 6.4409344,1.6400802 3.9852418,3.7549923 3.9852419,6.54508 V 9.6526439 H 24.511009 L 11.571923,2.1680807 C 10.867511,1.7606073 10.108228,1.5626759 9.3517318,1.541286 Z" /><path + style="color:#000000;fill:#f2f2f2;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none;paint-order:markers stroke fill" + d="M 25.454197,16.881861 9.7664962,25.956555 A 1.4501236,1.4501236 0 0 1 7.5902671,24.701314 V 6.544692 A 1.4501239,1.4501239 0 0 1 9.7664964,5.289451 l 15.6876996,9.074691 a 1.4543042,1.4543042 0 0 1 1e-6,2.517719 z" + id="path11897" /></svg> diff --git a/launcher/resources/pe_colored/scalable/launcher.svg b/launcher/resources/pe_colored/scalable/launcher.svg index 69dd84b1..aeee8433 100644 --- a/launcher/resources/pe_colored/scalable/launcher.svg +++ b/launcher/resources/pe_colored/scalable/launcher.svg @@ -37,17 +37,21 @@ </cc:Agent> </dc:contributor> <dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source> - <dc:rights> - <cc:Agent> - <dc:title>CC BY-SA 4.0</dc:title> - </cc:Agent> - </dc:rights> <dc:publisher> <cc:Agent> <dc:title>Prism Launcher</dc:title> </cc:Agent> </dc:publisher> + <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/> </cc:Work> + <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/> + </cc:License> </rdf:RDF> </metadata> </svg> diff --git a/launcher/resources/pe_dark/pe_dark.qrc b/launcher/resources/pe_dark/pe_dark.qrc index 6b9c7cb6..156d8f8b 100644 --- a/launcher/resources/pe_dark/pe_dark.qrc +++ b/launcher/resources/pe_dark/pe_dark.qrc @@ -38,5 +38,6 @@ <file>scalable/tag.svg</file> <file>scalable/export.svg</file> <file>scalable/rename.svg</file> + <file>scalable/launch.svg</file> </qresource> </RCC> diff --git a/launcher/resources/pe_dark/scalable/launch.svg b/launcher/resources/pe_dark/scalable/launch.svg new file mode 100644 index 00000000..3746e2dd --- /dev/null +++ b/launcher/resources/pe_dark/scalable/launch.svg @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + version="1.1" + id="Calque_1" + x="0px" + y="0px" + viewBox="0 0 32 32" + enable-background="new 0 0 32 32" + xml:space="preserve" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"><defs + id="defs45" /> + +<path + id="path11889" + style="color:#000000;fill:#000000;fill-opacity:1;stroke-width:0.999996;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill" + d="M 9.3515625,1.5410156 C 9.2434916,1.5379599 9.1351286,1.5389257 9.0273438,1.5429688 6.4405077,1.6400024 3.9843749,3.7548341 3.984375,6.5449219 V 24.701172 c -8e-7,3.720117 4.367721,6.23969 7.587891,4.376953 l 15.6875,-9.074219 c 3.218964,-1.862042 3.218965,-6.899679 0,-8.761718 L 11.572266,2.1679688 C 10.867854,1.7604954 10.108059,1.5624055 9.3515625,1.5410156 Z m -0.5625,3.5761719 a 1.4501239,1.4501239 0 0 1 0.9765625,0.171875 l 15.689453,9.0742185 a 1.4543042,1.4543042 0 0 1 0,2.519531 L 9.765625,25.957031 A 1.4501236,1.4501236 0 0 1 7.5898438,24.701172 V 6.5449219 A 1.4501239,1.4501239 0 0 1 8.7890625,5.1171875 Z" /></svg> diff --git a/launcher/resources/pe_dark/scalable/launcher.svg b/launcher/resources/pe_dark/scalable/launcher.svg index 69dd84b1..aeee8433 100644 --- a/launcher/resources/pe_dark/scalable/launcher.svg +++ b/launcher/resources/pe_dark/scalable/launcher.svg @@ -37,17 +37,21 @@ </cc:Agent> </dc:contributor> <dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source> - <dc:rights> - <cc:Agent> - <dc:title>CC BY-SA 4.0</dc:title> - </cc:Agent> - </dc:rights> <dc:publisher> <cc:Agent> <dc:title>Prism Launcher</dc:title> </cc:Agent> </dc:publisher> + <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/> </cc:Work> + <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/> + </cc:License> </rdf:RDF> </metadata> </svg> diff --git a/launcher/resources/pe_light/pe_light.qrc b/launcher/resources/pe_light/pe_light.qrc index 963bfcde..d8e4a1bd 100644 --- a/launcher/resources/pe_light/pe_light.qrc +++ b/launcher/resources/pe_light/pe_light.qrc @@ -38,5 +38,6 @@ <file>scalable/tag.svg</file> <file>scalable/export.svg</file> <file>scalable/rename.svg</file> + <file>scalable/launch.svg</file> </qresource> </RCC> diff --git a/launcher/resources/pe_light/scalable/launch.svg b/launcher/resources/pe_light/scalable/launch.svg new file mode 100644 index 00000000..6c27b7e0 --- /dev/null +++ b/launcher/resources/pe_light/scalable/launch.svg @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + version="1.1" + id="Calque_1" + x="0px" + y="0px" + viewBox="0 0 32 32" + enable-background="new 0 0 32 32" + xml:space="preserve" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"><defs + id="defs45" /> + +<path + id="path11889" + style="color:#000000;fill:#f2f2f2;fill-opacity:1;stroke-width:0.999996;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill" + d="M 9.3515625,1.5410156 C 9.2434916,1.5379599 9.1351286,1.5389257 9.0273438,1.5429688 6.4405077,1.6400024 3.9843749,3.7548341 3.984375,6.5449219 V 24.701172 c -8e-7,3.720117 4.367721,6.23969 7.587891,4.376953 l 15.6875,-9.074219 c 3.218964,-1.862042 3.218965,-6.899679 0,-8.761718 L 11.572266,2.1679688 C 10.867854,1.7604954 10.108059,1.5624055 9.3515625,1.5410156 Z m -0.5625,3.5761719 a 1.4501239,1.4501239 0 0 1 0.9765625,0.171875 l 15.689453,9.0742185 a 1.4543042,1.4543042 0 0 1 0,2.519531 L 9.765625,25.957031 A 1.4501236,1.4501236 0 0 1 7.5898438,24.701172 V 6.5449219 A 1.4501239,1.4501239 0 0 1 8.7890625,5.1171875 Z" /></svg> diff --git a/launcher/resources/pe_light/scalable/launcher.svg b/launcher/resources/pe_light/scalable/launcher.svg index 69dd84b1..aeee8433 100644 --- a/launcher/resources/pe_light/scalable/launcher.svg +++ b/launcher/resources/pe_light/scalable/launcher.svg @@ -37,17 +37,21 @@ </cc:Agent> </dc:contributor> <dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source> - <dc:rights> - <cc:Agent> - <dc:title>CC BY-SA 4.0</dc:title> - </cc:Agent> - </dc:rights> <dc:publisher> <cc:Agent> <dc:title>Prism Launcher</dc:title> </cc:Agent> </dc:publisher> + <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/> </cc:Work> + <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/> + <cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/> + </cc:License> </rdf:RDF> </metadata> </svg> diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp index b4babdd4..9ea1bb26 100644 --- a/launcher/tasks/Task.cpp +++ b/launcher/tasks/Task.cpp @@ -153,7 +153,7 @@ QString Task::describe() auto name = objectName(); if(name.isEmpty()) { - out << QString("0x%1").arg((quintptr)this, 0, 16); + out << QString("0x%1").arg(reinterpret_cast<quintptr>(this), 0, 16); } else { diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 2f57de3a..20aa6d04 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -83,6 +83,12 @@ struct Language else if(key == "es_UY") { result = u8"español de Latinoamérica"; } + else if(key == "en@pirate") { + result = u8"Tongue of the High Seas"; + } + else if(key == "en@uwu") { + result = u8"Cute Engwish"; + } else { result = locale.nativeLanguageName(); } diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 08005b86..f697897a 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -262,6 +262,8 @@ public: TranslatedAction actionNoAccountsAdded; TranslatedAction actionNoDefaultAccount; + TranslatedAction actionLockToolbars; + QVector<TranslatedToolButton *> all_toolbuttons; QWidget *centralWidget = nullptr; @@ -335,11 +337,10 @@ public: all_actions.append(&actionSettings); actionUndoTrashInstance = TranslatedAction(MainWindow); - connect(actionUndoTrashInstance, SIGNAL(triggered(bool)), MainWindow, SLOT(undoTrashInstance())); actionUndoTrashInstance->setObjectName(QStringLiteral("actionUndoTrashInstance")); actionUndoTrashInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "&Undo Last Instance Deletion")); actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething()); - actionUndoTrashInstance->setShortcut(QKeySequence("Ctrl+Z")); + actionUndoTrashInstance->setShortcut(QKeySequence::Undo); all_actions.append(&actionUndoTrashInstance); actionClearMetadata = TranslatedAction(MainWindow); @@ -421,6 +422,12 @@ public: actionManageAccounts->setCheckable(false); actionManageAccounts->setIcon(APPLICATION->getThemedIcon("accounts")); all_actions.append(&actionManageAccounts); + + actionLockToolbars = TranslatedAction(MainWindow); + actionLockToolbars->setObjectName(QStringLiteral("actionLockToolbars")); + actionLockToolbars.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Lock Toolbars")); + actionLockToolbars->setCheckable(true); + all_actions.append(&actionLockToolbars); } void createMainToolbar(QMainWindow *MainWindow) @@ -428,7 +435,6 @@ public: mainToolBar = TranslatedToolbar(MainWindow); mainToolBar->setVisible(menuBar->isNativeMenuBar() || !APPLICATION->settings()->get("MenuBarInsteadOfToolBar").toBool()); mainToolBar->setObjectName(QStringLiteral("mainToolBar")); - mainToolBar->setMovable(true); mainToolBar->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); mainToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); mainToolBar->setFloatable(false); @@ -525,9 +531,11 @@ public: viewMenu->addAction(actionCAT); viewMenu->addSeparator(); + viewMenu->addAction(actionLockToolbars); + menuBar->addMenu(foldersMenu); - profileMenu = menuBar->addMenu(tr("&Profiles")); + profileMenu = menuBar->addMenu(tr("&Accounts")); profileMenu->setSeparatorsCollapsible(false); profileMenu->addAction(actionManageAccounts); @@ -602,7 +610,6 @@ public: { newsToolBar = TranslatedToolbar(MainWindow); newsToolBar->setObjectName(QStringLiteral("newsToolBar")); - newsToolBar->setMovable(true); newsToolBar->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); newsToolBar->setIconSize(QSize(16, 16)); newsToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -656,6 +663,7 @@ public: actionLaunchInstance->setObjectName(QStringLiteral("actionLaunchInstance")); actionLaunchInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "&Launch")); actionLaunchInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Launch the selected instance.")); + actionLaunchInstance->setIcon(APPLICATION->getThemedIcon("launch")); all_actions.append(&actionLaunchInstance); actionLaunchInstanceOffline = TranslatedAction(MainWindow); @@ -736,12 +744,13 @@ public: instanceToolBar->setObjectName(QStringLiteral("instanceToolBar")); // disabled until we have an instance selected instanceToolBar->setEnabled(false); - instanceToolBar->setMovable(true); // Qt doesn't like vertical moving toolbars, so we have to force them... // See https://github.com/PolyMC/PolyMC/issues/493 connect(instanceToolBar, &QToolBar::orientationChanged, [=](Qt::Orientation){ instanceToolBar->setOrientation(Qt::Vertical); }); instanceToolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea); - instanceToolBar->setToolButtonStyle(Qt::ToolButtonTextOnly); + instanceToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + instanceToolBar->setIconSize(QSize(16, 16)); + instanceToolBar->setFloatable(false); instanceToolBar->setWindowTitle(QT_TRANSLATE_NOOP("MainWindow", "Instance Toolbar")); @@ -761,8 +770,18 @@ public: instanceToolBar->addAction(actionViewSelectedInstFolder); instanceToolBar->addAction(actionExportInstance); - instanceToolBar->addAction(actionDeleteInstance); instanceToolBar->addAction(actionCopyInstance); + instanceToolBar->addAction(actionDeleteInstance); + + QLayout * lay = instanceToolBar->layout(); + for(int i = 0; i < lay->count(); i++) + { + QLayoutItem * item = lay->itemAt(i); + if (item->widget()->metaObject()->className() == QString("QToolButton")) + { + item->setAlignment(Qt::AlignLeft); + } + } all_toolbars.append(&instanceToolBar); MainWindow->addToolBar(Qt::RightToolBarArea, instanceToolBar); @@ -906,6 +925,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow connect(ui->actionCAT.operator->(), SIGNAL(toggled(bool)), SLOT(onCatToggled(bool))); setCatBackground(cat_enable); } + + // Lock toolbars + { + bool toolbarsLocked = APPLICATION->settings()->get("ToolbarsLocked").toBool(); + ui->actionLockToolbars->setChecked(toolbarsLocked); + connect(ui->actionLockToolbars, &QAction::toggled, this, &MainWindow::lockToolbars); + lockToolbars(toolbarsLocked); + } // start instance when double-clicked connect(view, &InstanceView::activated, this, &MainWindow::instanceActivated); @@ -1010,6 +1037,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow } } + connect(ui->actionUndoTrashInstance.operator->(), &QAction::triggered, this, &MainWindow::undoTrashInstance); + setSelectedInstanceById(APPLICATION->settings()->get("SelectedInstance").toString()); // removing this looks stupid @@ -1039,7 +1068,7 @@ void MainWindow::retranslateUi() accountMenuButton->setText(profileLabel); } else { - accountMenuButton->setText(tr("Profiles")); + accountMenuButton->setText(tr("Accounts")); } if (m_selectedInstance) { @@ -1059,8 +1088,19 @@ QMenu * MainWindow::createPopupMenu() { QMenu* filteredMenu = QMainWindow::createPopupMenu(); filteredMenu->removeAction( ui->mainToolBar->toggleViewAction() ); + + filteredMenu->addAction(ui->actionLockToolbars); + return filteredMenu; } +void MainWindow::lockToolbars(bool state) +{ + ui->mainToolBar->setMovable(!state); + ui->instanceToolBar->setMovable(!state); + ui->newsToolBar->setMovable(!state); + APPLICATION->settings()->set("ToolbarsLocked", state); +} + void MainWindow::konamiTriggered() { @@ -1121,11 +1161,6 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos) connect(actionDeleteGroup, SIGNAL(triggered(bool)), SLOT(deleteGroup())); actions.append(actionDeleteGroup); } - - QAction *actionUndoTrashInstance = new QAction("Undo last trash instance", this); - connect(actionUndoTrashInstance, SIGNAL(triggered(bool)), SLOT(undoTrashInstance())); - actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething()); - actions.append(actionUndoTrashInstance); } QMenu myMenu; myMenu.addActions(actions); @@ -1382,7 +1417,7 @@ void MainWindow::defaultAccountChanged() // Set the icon to the "no account" icon. accountMenuButton->setIcon(APPLICATION->getThemedIcon("noaccount")); - accountMenuButton->setText(tr("Profiles")); + accountMenuButton->setText(tr("Accounts")); } bool MainWindow::eventFilter(QObject *obj, QEvent *ev) @@ -1551,15 +1586,14 @@ void MainWindow::setCatBackground(bool enabled) QDateTime now = QDateTime::currentDateTime(); QDateTime birthday(QDate(now.date().year(), 11, 30), QTime(0, 0)); QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0)); - QString cat; - if(non_stupid_abs(now.daysTo(xmas)) <= 4) { - cat = "catmas"; - } - else if (non_stupid_abs(now.daysTo(birthday)) <= 12) { - cat = "cattiversary"; - } - else { - cat = "kitteh"; + QDateTime halloween(QDate(now.date().year(), 10, 31), QTime(0, 0)); + QString cat = APPLICATION->settings()->get("BackgroundCat").toString(); + if (non_stupid_abs(now.daysTo(xmas)) <= 4) { + cat += "-xmas"; + } else if (cat == "kitteh" && non_stupid_abs(now.daysTo(halloween)) <= 4) { + cat += "-ween"; + } else if (non_stupid_abs(now.daysTo(birthday)) <= 12) { + cat += "-bday"; } view->setStyleSheet(QString(R"( InstanceView @@ -1567,10 +1601,11 @@ InstanceView background-image: url(:/backgrounds/%1); background-attachment: fixed; background-clip: padding; - background-position: top right; + background-position: bottom left; background-repeat: none; background-color:palette(base); -})").arg(cat)); +})") + .arg(cat)); } else { @@ -1821,6 +1856,7 @@ void MainWindow::deleteGroup() void MainWindow::undoTrashInstance() { APPLICATION->instances()->undoTrashInstance(); + ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething()); } void MainWindow::on_actionViewInstanceFolder_triggered() @@ -1927,6 +1963,7 @@ void MainWindow::on_actionDeleteInstance_triggered() auto id = m_selectedInstance->id(); if (APPLICATION->instances()->trashInstance(id)) { + ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething()); return; } diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index cb8cb4aa..f9d1f1c7 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -203,6 +203,8 @@ private slots: void globalSettingsClosed(); + void lockToolbars(bool); + #ifndef Q_OS_MAC void keyReleaseEvent(QKeyEvent *event) override; #endif diff --git a/launcher/ui/dialogs/AboutDialog.cpp b/launcher/ui/dialogs/AboutDialog.cpp index cecda1df..a36e4a3d 100644 --- a/launcher/ui/dialogs/AboutDialog.cpp +++ b/launcher/ui/dialogs/AboutDialog.cpp @@ -73,17 +73,12 @@ QString getCreditsHtml() stream << "<h3>" << QObject::tr("%1 Developers", "About Credits").arg(BuildConfig.LAUNCHER_DISPLAYNAME) << "</h3>\n"; stream << QString("<p>Sefa Eyeoglu (Scrumplex) %1</p>\n") .arg(getWebsite("https://scrumplex.net")); stream << QString("<p>dada513 %1</p>\n") .arg(getGitHub("dada513")); - stream << QString("<p>txtsd %1</p>\n") .arg(getGitHub("txtsd")); + stream << QString("<p>txtsd %1</p>\n") .arg(getWebsite("https://ihavea.quest")); stream << QString("<p>timoreo %1</p>\n") .arg(getGitHub("timoreo22")); stream << QString("<p>Ezekiel Smith (ZekeSmith) %1</p>\n") .arg(getGitHub("ZekeSmith")); stream << QString("<p>cozyGalvinism %1</p>\n") .arg(getGitHub("cozyGalvinism")); - stream << "<br />\n"; - - //: %1 is the name of the launcher, determined at build time, e.g. "Prism Launcher Contributors" - stream << "<h3>" << QObject::tr("%1 Contributors", "About Credits").arg(BuildConfig.LAUNCHER_DISPLAYNAME) << "</h3>\n"; stream << QString("<p>DioEgizio %1</p>\n") .arg(getGitHub("DioEgizio")); stream << QString("<p>flowln %1</p>\n") .arg(getGitHub("flowln")); - stream << QString("<p>swirl %1</p>\n") .arg(getWebsite("https://swurl.xyz/")); stream << "<br />\n"; // TODO: possibly retrieve from git history at build time? @@ -97,7 +92,7 @@ QString getCreditsHtml() stream << "<br />\n"; stream << "<h3>" << QObject::tr("With thanks to", "About Credits") << "</h3>\n"; - stream << QString("<p>Boba %1</p>\n") .arg(getWebsite("https://cmdplusv.neocities.org/")); + stream << QString("<p>Boba %1</p>\n") .arg(getWebsite("https://bobaonline.neocities.org/")); stream << QString("<p>Davi Rafael %1</p>\n") .arg(getWebsite("https://auti.one/")); stream << QString("<p>Fulmine %1</p>\n") .arg(getWebsite("https://www.fulmine.xyz/")); stream << QString("<p>ely %1</p>\n") .arg(getGitHub("elyrodso")); diff --git a/launcher/ui/dialogs/AboutDialog.ui b/launcher/ui/dialogs/AboutDialog.ui index e0429321..4a9eef08 100644 --- a/launcher/ui/dialogs/AboutDialog.ui +++ b/launcher/ui/dialogs/AboutDialog.ui @@ -87,14 +87,11 @@ </property> </widget> </item> - <item> + <item alignment="Qt::AlignHCenter"> <widget class="QLabel" name="versionLabel"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> <property name="textInteractionFlags"> <set>Qt::TextSelectableByMouse</set> </property> @@ -167,7 +164,7 @@ </property> </widget> </item> - <item> + <item alignment="Qt::AlignHCenter"> <widget class="QLabel" name="platformLabel"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -183,7 +180,7 @@ </property> </widget> </item> - <item> + <item alignment="Qt::AlignHCenter"> <widget class="QLabel" name="buildDateLabel"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -199,7 +196,7 @@ </property> </widget> </item> - <item> + <item alignment="Qt::AlignHCenter"> <widget class="QLabel" name="commitLabel"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -215,7 +212,7 @@ </property> </widget> </item> - <item> + <item alignment="Qt::AlignHCenter"> <widget class="QLabel" name="channelLabel"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 4171586e..cedd4a96 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -366,33 +366,28 @@ void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info) auto changelog = new QTreeWidgetItem(changelog_item); auto changelog_area = new QTextBrowser(); + QString text = info.changelog; switch (info.provider) { case ModPlatform::Provider::MODRINTH: { HoeDown h; // HoeDown bug?: \n aren't converted to <br> - auto text = h.process(info.changelog.toUtf8()); + text = h.process(info.changelog.toUtf8()); // Don't convert if there's an HTML tag right after (Qt rendering weirdness) text.remove(QRegularExpression("(\n+)(?=<)")); text.replace('\n', "<br>"); - changelog_area->setHtml(text); break; } - case ModPlatform::Provider::FLAME: { - changelog_area->setHtml(info.changelog); + default: break; - } } + changelog_area->setHtml(text); changelog_area->setOpenExternalLinks(true); - changelog_area->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap); + changelog_area->setLineWrapMode(QTextBrowser::LineWrapMode::WidgetWidth); changelog_area->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - // HACK: Is there a better way of achieving this? - auto font_height = QFontMetrics(changelog_area->font()).height(); - changelog_area->setMaximumHeight((changelog_area->toPlainText().count(QRegularExpression("\n|<br>")) + 2) * font_height); - ui->modTreeWidget->setItemWidget(changelog, 0, changelog_area); ui->modTreeWidget->addTopLevelItem(item_top); diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index 70ef72d6..d7880334 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -120,7 +120,7 @@ void VersionSelectDialog::selectRecommended() m_versionWidget->selectRecommended(); } -BaseVersionPtr VersionSelectDialog::selectedVersion() const +BaseVersion::Ptr VersionSelectDialog::selectedVersion() const { return m_versionWidget->selectedVersion(); } diff --git a/launcher/ui/dialogs/VersionSelectDialog.h b/launcher/ui/dialogs/VersionSelectDialog.h index ed30d3f3..18a50cdb 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.h +++ b/launcher/ui/dialogs/VersionSelectDialog.h @@ -44,7 +44,7 @@ public: int exec() override; - BaseVersionPtr selectedVersion() const; + BaseVersion::Ptr selectedVersion() const; void setCurrentVersion(const QString & version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); diff --git a/launcher/ui/pages/global/APIPage.ui b/launcher/ui/pages/global/APIPage.ui index 1ae788c7..d56a9ef6 100644 --- a/launcher/ui/pages/global/APIPage.ui +++ b/launcher/ui/pages/global/APIPage.ui @@ -179,7 +179,7 @@ <item> <widget class="QLabel" name="label_4"> <property name="text"> - <string>Enter a custom client ID for Microsoft Authentication here. </string> + <string>Enter a custom client ID for Microsoft Authentication here.</string> </property> <property name="textFormat"> <enum>Qt::RichText</enum> diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index b8431e8c..6661bf0f 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org> * Copyright (c) 2022 dada513 <dada513@protonmail.com> + * Copyright (C) 2022 Tayou <tayou@gmx.net> * * 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 @@ -49,6 +50,7 @@ #include <FileSystem.h> #include "Application.h" #include "BuildConfig.h" +#include "DesktopServices.h" #include "ui/themes/ITheme.h" #include <QApplication> @@ -143,7 +145,7 @@ void LauncherPage::on_instDirBrowseBtn_clicked() ui->instDirTextBox->setText(cooked_dir); } } - else if(APPLICATION->isFlatpak() && raw_dir.startsWith("/run/user")) + else if(DesktopServices::isFlatpak() && raw_dir.startsWith("/run/user")) { QMessageBox warning; warning.setText(tr("You're trying to specify an instance folder " @@ -310,9 +312,12 @@ void LauncherPage::applySettings() s->set("IconTheme", "flat"); break; case 7: - s->set("IconTheme", "multimc"); + s->set("IconTheme", "flat_white"); break; case 8: + s->set("IconTheme", "multimc"); + break; + case 9: s->set("IconTheme", "custom"); break; } @@ -330,6 +335,18 @@ void LauncherPage::applySettings() APPLICATION->setApplicationTheme(newAppTheme, false); } + switch (ui->themeBackgroundCat->currentIndex()) { + case 0: // original cat + s->set("BackgroundCat", "kitteh"); + break; + case 1: // rory the cat + s->set("BackgroundCat", "rory"); + break; + case 2: // rory the cat flat edition + s->set("BackgroundCat", "rory-flat"); + break; + } + s->set("MenuBarInsteadOfToolBar", ui->preferMenuBarCheckBox->isChecked()); // Console settings @@ -380,41 +397,16 @@ void LauncherPage::loadSettings() m_currentUpdateChannel = s->get("UpdateChannel").toString(); //FIXME: make generic auto theme = s->get("IconTheme").toString(); - if (theme == "pe_colored") - { - ui->themeComboBox->setCurrentIndex(0); - } - else if (theme == "pe_light") - { - ui->themeComboBox->setCurrentIndex(1); - } - else if (theme == "pe_dark") - { - ui->themeComboBox->setCurrentIndex(2); - } - else if (theme == "pe_blue") - { - ui->themeComboBox->setCurrentIndex(3); - } - else if (theme == "OSX") - { - ui->themeComboBox->setCurrentIndex(4); - } - else if (theme == "iOS") - { - ui->themeComboBox->setCurrentIndex(5); - } - else if (theme == "flat") - { - ui->themeComboBox->setCurrentIndex(6); - } - else if (theme == "multimc") - { - ui->themeComboBox->setCurrentIndex(7); - } - else if (theme == "custom") - { - ui->themeComboBox->setCurrentIndex(8); + QStringList iconThemeOptions{"pe_colored", "pe_light", "pe_dark", "pe_blue", "OSX", "iOS", "flat", "flat_white", "multimc", "custom"}; + ui->themeComboBox->setCurrentIndex(iconThemeOptions.indexOf(theme)); + + auto cat = s->get("BackgroundCat").toString(); + if (cat == "kitteh") { + ui->themeBackgroundCat->setCurrentIndex(0); + } else if (cat == "rory") { + ui->themeBackgroundCat->setCurrentIndex(1); + } else if (cat == "rory-flat") { + ui->themeBackgroundCat->setCurrentIndex(2); } { diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 0d14f147..6de644ee 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -302,6 +302,11 @@ </item> <item> <property name="text"> + <string>Flat (White)</string> + </property> + </item> + <item> + <property name="text"> <string>Legacy</string> </property> </item> @@ -335,6 +340,44 @@ </property> </widget> </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>C&at</string> + </property> + <property name="buddy"> + <cstring>themeBackgroundCat</cstring> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="themeBackgroundCat"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <item> + <property name="text"> + <string>Background Cat (from MultiMC)</string> + </property> + </item> + <item> + <property name="text"> + <string>Rory ID 11 (drawn by Ashtaka)</string> + </property> + </item> + <item> + <property name="text"> + <string>Rory ID 11 (flat edition, drawn by Ashtaka)</string> + </property> + </item> + </widget> + </item> </layout> </widget> </item> diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 49766fa6..ed58eb32 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -267,18 +267,25 @@ void ListModel::searchRequestFailed(QString reason) .arg(m_parent->displayName()) .arg(tr("API version too old!\nPlease update %1!").arg(BuildConfig.LAUNCHER_DISPLAYNAME))); } + jobPtr.reset(); + searchState = Finished; +} - if (searchState == ResetRequested) { - beginResetModel(); - modpacks.clear(); - endResetModel(); +void ListModel::searchRequestAborted() +{ + if (searchState != ResetRequested) + qCritical() << "Search task in ModModel aborted by an unknown reason!"; - nextSearchOffset = 0; - performPaginatedSearch(); - } else { - searchState = Finished; - } + // Retry fetching + jobPtr.reset(); + + beginResetModel(); + modpacks.clear(); + endResetModel(); + + nextSearchOffset = 0; + performPaginatedSearch(); } void ListModel::infoRequestFinished(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index) diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index a58c7c55..d2636d87 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -51,6 +51,7 @@ class ListModel : public QAbstractListModel { public slots: void searchRequestFinished(QJsonDocument& doc); void searchRequestFailed(QString reason); + void searchRequestAborted(); void infoRequestFinished(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index); diff --git a/launcher/ui/pages/modplatform/VanillaPage.cpp b/launcher/ui/pages/modplatform/VanillaPage.cpp index 99190f31..29fecb85 100644 --- a/launcher/ui/pages/modplatform/VanillaPage.cpp +++ b/launcher/ui/pages/modplatform/VanillaPage.cpp @@ -187,12 +187,12 @@ void VanillaPage::retranslate() ui->retranslateUi(this); } -BaseVersionPtr VanillaPage::selectedVersion() const +BaseVersion::Ptr VanillaPage::selectedVersion() const { return m_selectedVersion; } -BaseVersionPtr VanillaPage::selectedLoaderVersion() const +BaseVersion::Ptr VanillaPage::selectedLoaderVersion() const { return m_selectedLoaderVersion; } @@ -227,14 +227,14 @@ void VanillaPage::suggestCurrent() dialog->setSuggestedIcon("default"); } -void VanillaPage::setSelectedVersion(BaseVersionPtr version) +void VanillaPage::setSelectedVersion(BaseVersion::Ptr version) { m_selectedVersion = version; suggestCurrent(); loaderFilterChanged(); } -void VanillaPage::setSelectedLoaderVersion(BaseVersionPtr version) +void VanillaPage::setSelectedLoaderVersion(BaseVersion::Ptr version) { m_selectedLoaderVersion = version; suggestCurrent(); diff --git a/launcher/ui/pages/modplatform/VanillaPage.h b/launcher/ui/pages/modplatform/VanillaPage.h index 7193597d..39aba760 100644 --- a/launcher/ui/pages/modplatform/VanillaPage.h +++ b/launcher/ui/pages/modplatform/VanillaPage.h @@ -76,13 +76,13 @@ public: void openedImpl() override; - BaseVersionPtr selectedVersion() const; - BaseVersionPtr selectedLoaderVersion() const; + BaseVersion::Ptr selectedVersion() const; + BaseVersion::Ptr selectedLoaderVersion() const; QString selectedLoader() const; public slots: - void setSelectedVersion(BaseVersionPtr version); - void setSelectedLoaderVersion(BaseVersionPtr version); + void setSelectedVersion(BaseVersion::Ptr version); + void setSelectedLoaderVersion(BaseVersion::Ptr version); private slots: void filterChanged(); @@ -98,7 +98,7 @@ private: NewInstanceDialog *dialog = nullptr; Ui::VanillaPage *ui = nullptr; bool m_versionSetByUser = false; - BaseVersionPtr m_selectedVersion; - BaseVersionPtr m_selectedLoaderVersion; + BaseVersion::Ptr m_selectedVersion; + BaseVersion::Ptr m_selectedLoaderVersion; QString m_selectedLoader; }; diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp index c68e40ba..f5f50cae 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp @@ -53,7 +53,7 @@ std::optional<QVector<QString>> AtlUserInteractionSupportImpl::chooseOptionalMod return optionalModDialog.getResult(); } -QString AtlUserInteractionSupportImpl::chooseVersion(Meta::VersionListPtr vlist, QString minecraftVersion) +QString AtlUserInteractionSupportImpl::chooseVersion(Meta::VersionList::Ptr vlist, QString minecraftVersion) { VersionSelectDialog vselect(vlist.get(), "Choose Version", m_parent, false); if (minecraftVersion != nullptr) { diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h index 3b37c9be..37010b3f 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h @@ -46,7 +46,7 @@ public: AtlUserInteractionSupportImpl(QWidget* parent); private: - QString chooseVersion(Meta::VersionListPtr vlist, QString minecraftVersion) override; + QString chooseVersion(Meta::VersionList::Ptr vlist, QString minecraftVersion) override; std::optional<QVector<QString>> chooseOptionalMods(ATLauncher::PackVersion version, QVector<ATLauncher::VersionMod> mods) override; void displayMessage(QString message) override; diff --git a/launcher/ui/themes/CustomTheme.cpp b/launcher/ui/themes/CustomTheme.cpp index 3e3e27de..3ad61668 100644 --- a/launcher/ui/themes/CustomTheme.cpp +++ b/launcher/ui/themes/CustomTheme.cpp @@ -1,48 +1,81 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Tayou <tayou@gmx.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include "CustomTheme.h" -#include <QDir> -#include <Json.h> #include <FileSystem.h> +#include <Json.h> +#include "ThemeManager.h" -const char * themeFile = "theme.json"; -const char * styleFile = "themeStyle.css"; +const char* themeFile = "theme.json"; -static bool readThemeJson(const QString &path, QPalette &palette, double &fadeAmount, QColor &fadeColor, QString &name, QString &widgets) +static bool readThemeJson(const QString& path, + QPalette& palette, + double& fadeAmount, + QColor& fadeColor, + QString& name, + QString& widgets, + QString& qssFilePath, + bool& dataIncomplete) { QFileInfo pathInfo(path); - if(pathInfo.exists() && pathInfo.isFile()) - { - try - { + if (pathInfo.exists() && pathInfo.isFile()) { + try { auto doc = Json::requireDocument(path, "Theme JSON file"); const QJsonObject root = doc.object(); + dataIncomplete = !root.contains("qssFilePath"); name = Json::requireString(root, "name", "Theme name"); widgets = Json::requireString(root, "widgets", "Qt widget theme"); + qssFilePath = Json::ensureString(root, "qssFilePath", "themeStyle.css"); auto colorsRoot = Json::requireObject(root, "colors", "colors object"); - auto readColor = [&](QString colorName) -> QColor - { + auto readColor = [&](QString colorName) -> QColor { auto colorValue = Json::ensureString(colorsRoot, colorName, QString()); - if(!colorValue.isEmpty()) - { + if (!colorValue.isEmpty()) { QColor color(colorValue); - if(!color.isValid()) - { - qWarning() << "Color value" << colorValue << "for" << colorName << "was not recognized."; + if (!color.isValid()) { + themeWarningLog() << "Color value" << colorValue << "for" << colorName << "was not recognized."; return QColor(); } return color; } return QColor(); }; - auto readAndSetColor = [&](QPalette::ColorRole role, QString colorName) - { + auto readAndSetColor = [&](QPalette::ColorRole role, QString colorName) { auto color = readColor(colorName); - if(color.isValid()) - { + if (color.isValid()) { palette.setColor(role, color); - } - else - { - qDebug() << "Color value for" << colorName << "was not present."; + } else { + themeDebugLog() << "Color value for" << colorName << "was not present."; } }; @@ -61,36 +94,36 @@ static bool readThemeJson(const QString &path, QPalette &palette, double &fadeAm readAndSetColor(QPalette::Highlight, "Highlight"); readAndSetColor(QPalette::HighlightedText, "HighlightedText"); - //fade + // fade fadeColor = readColor("fadeColor"); fadeAmount = Json::ensureDouble(colorsRoot, "fadeAmount", 0.5, "fade amount"); - } - catch (const Exception &e) - { - qWarning() << "Couldn't load theme json: " << e.cause(); + } catch (const Exception& e) { + themeWarningLog() << "Couldn't load theme json: " << e.cause(); return false; } - } - else - { - qDebug() << "No theme json present."; + } else { + themeDebugLog() << "No theme json present."; return false; } return true; } -static bool writeThemeJson(const QString &path, const QPalette &palette, double fadeAmount, QColor fadeColor, QString name, QString widgets) +static bool writeThemeJson(const QString& path, + const QPalette& palette, + double fadeAmount, + QColor fadeColor, + QString name, + QString widgets, + QString qssFilePath) { QJsonObject rootObj; rootObj.insert("name", name); rootObj.insert("widgets", widgets); + rootObj.insert("qssFilePath", qssFilePath); QJsonObject colorsObj; - auto insertColor = [&](QPalette::ColorRole role, QString colorName) - { - colorsObj.insert(colorName, palette.color(role).name()); - }; + auto insertColor = [&](QPalette::ColorRole role, QString colorName) { colorsObj.insert(colorName, palette.color(role).name()); }; // palette insertColor(QPalette::Window, "Window"); @@ -112,82 +145,95 @@ static bool writeThemeJson(const QString &path, const QPalette &palette, double colorsObj.insert("fadeAmount", fadeAmount); rootObj.insert("colors", colorsObj); - try - { + try { Json::write(rootObj, path); return true; - } - catch (const Exception &e) - { - qWarning() << "Failed to write theme json to" << path; + } catch (const Exception& e) { + themeWarningLog() << "Failed to write theme json to" << path; return false; } } -CustomTheme::CustomTheme(ITheme* baseTheme, QString folder) +/// @param baseTheme Base Theme +/// @param fileInfo FileInfo object for file to load +/// @param isManifest whether to load a theme manifest or a qss file +CustomTheme::CustomTheme(ITheme* baseTheme, QFileInfo& fileInfo, bool isManifest) { - m_id = folder; - QString path = FS::PathCombine("themes", m_id); - QString pathResources = FS::PathCombine("themes", m_id, "resources"); + if (isManifest) { + m_id = fileInfo.dir().dirName(); - qDebug() << "Loading theme" << m_id; + QString path = FS::PathCombine("themes", m_id); + QString pathResources = FS::PathCombine("themes", m_id, "resources"); - if(!FS::ensureFolderPathExists(path) || !FS::ensureFolderPathExists(pathResources)) - { - qWarning() << "couldn't create folder for theme!"; - m_palette = baseTheme->colorScheme(); - m_styleSheet = baseTheme->appStyleSheet(); - return; - } + if (!FS::ensureFolderPathExists(path) || !FS::ensureFolderPathExists(pathResources)) { + themeWarningLog() << "couldn't create folder for theme!"; + m_palette = baseTheme->colorScheme(); + m_styleSheet = baseTheme->appStyleSheet(); + return; + } + + auto themeFilePath = FS::PathCombine(path, themeFile); - auto themeFilePath = FS::PathCombine(path, themeFile); + bool jsonDataIncomplete = false; - m_palette = baseTheme->colorScheme(); - if (!readThemeJson(themeFilePath, m_palette, m_fadeAmount, m_fadeColor, m_name, m_widgets)) - { - m_name = "Custom"; m_palette = baseTheme->colorScheme(); - m_fadeColor = baseTheme->fadeColor(); - m_fadeAmount = baseTheme->fadeAmount(); - m_widgets = baseTheme->qtTheme(); - - QFileInfo info(themeFilePath); - if(!info.exists()) - { - writeThemeJson(themeFilePath, m_palette, m_fadeAmount, m_fadeColor, "Custom", m_widgets); + if (!readThemeJson(themeFilePath, m_palette, m_fadeAmount, m_fadeColor, m_name, m_widgets, m_qssFilePath, jsonDataIncomplete)) { + themeDebugLog() << "Did not read theme json file correctly, writing new one to: " << themeFilePath; + m_name = "Custom"; + m_palette = baseTheme->colorScheme(); + m_fadeColor = baseTheme->fadeColor(); + m_fadeAmount = baseTheme->fadeAmount(); + m_widgets = baseTheme->qtTheme(); + m_qssFilePath = "themeStyle.css"; + } else { + m_palette = fadeInactive(m_palette, m_fadeAmount, m_fadeColor); } - } - else - { - m_palette = fadeInactive(m_palette, m_fadeAmount, m_fadeColor); - } - auto cssFilePath = FS::PathCombine(path, styleFile); - QFileInfo info (cssFilePath); - if(info.isFile()) - { - try - { - // TODO: validate css? - m_styleSheet = QString::fromUtf8(FS::read(cssFilePath)); + if (jsonDataIncomplete) { + writeThemeJson(fileInfo.absoluteFilePath(), m_palette, m_fadeAmount, m_fadeColor, m_name, m_widgets, m_qssFilePath); } - catch (const Exception &e) - { - qWarning() << "Couldn't load css:" << e.cause() << "from" << cssFilePath; + + auto qssFilePath = FS::PathCombine(path, m_qssFilePath); + QFileInfo info(qssFilePath); + if (info.isFile()) { + try { + // TODO: validate css? + m_styleSheet = QString::fromUtf8(FS::read(qssFilePath)); + } catch (const Exception& e) { + themeWarningLog() << "Couldn't load css:" << e.cause() << "from" << qssFilePath; + m_styleSheet = baseTheme->appStyleSheet(); + } + } else { + themeDebugLog() << "No theme css present."; m_styleSheet = baseTheme->appStyleSheet(); + try { + FS::write(qssFilePath, m_styleSheet.toUtf8()); + } catch (const Exception& e) { + themeWarningLog() << "Couldn't write css:" << e.cause() << "to" << qssFilePath; + } } - } - else - { - qDebug() << "No theme css present."; - m_styleSheet = baseTheme->appStyleSheet(); - try - { - FS::write(cssFilePath, m_styleSheet.toUtf8()); + } else { + m_id = fileInfo.fileName(); + m_name = fileInfo.baseName(); + QString path = fileInfo.filePath(); + // themeDebugLog << "Theme ID: " << m_id; + // themeDebugLog << "Theme Name: " << m_name; + // themeDebugLog << "Theme Path: " << path; + + if (!FS::ensureFilePathExists(path)) { + themeWarningLog() << m_name << " Theme file path doesn't exist!"; + m_palette = baseTheme->colorScheme(); + m_styleSheet = baseTheme->appStyleSheet(); + return; } - catch (const Exception &e) - { - qWarning() << "Couldn't write css:" << e.cause() << "to" << cssFilePath; + + m_palette = baseTheme->colorScheme(); + try { + // TODO: validate qss? + m_styleSheet = QString::fromUtf8(FS::read(path)); + } catch (const Exception& e) { + themeWarningLog() << "Couldn't load qss:" << e.cause() << "from" << path; + m_styleSheet = baseTheme->appStyleSheet(); } } } @@ -197,7 +243,6 @@ QStringList CustomTheme::searchPaths() return { FS::PathCombine("themes", m_id, "resources") }; } - QString CustomTheme::id() { return m_id; diff --git a/launcher/ui/themes/CustomTheme.h b/launcher/ui/themes/CustomTheme.h index d216895d..f2b1b06e 100644 --- a/launcher/ui/themes/CustomTheme.h +++ b/launcher/ui/themes/CustomTheme.h @@ -1,11 +1,45 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Tayou <tayou@gmx.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #pragma once +#include <QFileInfo> #include "ITheme.h" -class CustomTheme: public ITheme -{ -public: - CustomTheme(ITheme * baseTheme, QString folder); +class CustomTheme : public ITheme { + public: + CustomTheme(ITheme* baseTheme, QFileInfo& file, bool isManifest); virtual ~CustomTheme() {} QString id() override; @@ -19,7 +53,7 @@ public: QString qtTheme() override; QStringList searchPaths() override; -private: /* data */ + private: /* data */ QPalette m_palette; QColor m_fadeColor; double m_fadeAmount; @@ -27,5 +61,5 @@ private: /* data */ QString m_name; QString m_id; QString m_widgets; + QString m_qssFilePath; }; - diff --git a/launcher/ui/themes/DarkTheme.cpp b/launcher/ui/themes/DarkTheme.cpp index 07a2efd2..48231b53 100644 --- a/launcher/ui/themes/DarkTheme.cpp +++ b/launcher/ui/themes/DarkTheme.cpp @@ -31,7 +31,7 @@ QPalette DarkTheme::colorScheme() darkPalette.setColor(QPalette::ButtonText, Qt::white); darkPalette.setColor(QPalette::BrightText, Qt::red); darkPalette.setColor(QPalette::Link, QColor(47,163,198)); - darkPalette.setColor(QPalette::Highlight, QColor(145,205,92)); + darkPalette.setColor(QPalette::Highlight, QColor(150,219,89)); darkPalette.setColor(QPalette::HighlightedText, Qt::black); darkPalette.setColor(QPalette::PlaceholderText, Qt::darkGray); return fadeInactive(darkPalette, fadeAmount(), fadeColor()); diff --git a/launcher/ui/themes/SystemTheme.cpp b/launcher/ui/themes/SystemTheme.cpp index 49b1afaa..a63d1741 100644 --- a/launcher/ui/themes/SystemTheme.cpp +++ b/launcher/ui/themes/SystemTheme.cpp @@ -1,30 +1,65 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Tayou <tayou@gmx.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include "SystemTheme.h" #include <QApplication> #include <QStyle> #include <QStyleFactory> #include <QDebug> +#include "ThemeManager.h" SystemTheme::SystemTheme() { - qDebug() << "Determining System Theme..."; + themeDebugLog() << "Determining System Theme..."; const auto & style = QApplication::style(); systemPalette = style->standardPalette(); QString lowerThemeName = style->objectName(); - qDebug() << "System theme seems to be:" << lowerThemeName; + themeDebugLog() << "System theme seems to be:" << lowerThemeName; QStringList styles = QStyleFactory::keys(); for(auto &st: styles) { - qDebug() << "Considering theme from theme factory:" << st.toLower(); + themeDebugLog() << "Considering theme from theme factory:" << st.toLower(); if(st.toLower() == lowerThemeName) { systemTheme = st; - qDebug() << "System theme has been determined to be:" << systemTheme; + themeDebugLog() << "System theme has been determined to be:" << systemTheme; return; } } // fall back to fusion if we can't find the current theme. systemTheme = "Fusion"; - qDebug() << "System theme not found, defaulted to Fusion"; + themeDebugLog() << "System theme not found, defaulted to Fusion"; } void SystemTheme::apply(bool initial) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp new file mode 100644 index 00000000..01a38a86 --- /dev/null +++ b/launcher/ui/themes/ThemeManager.cpp @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Tayou <tayou@gmx.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+#include "ThemeManager.h"
+
+#include <QApplication>
+#include <QDir>
+#include <QDirIterator>
+#include <QIcon>
+#include "ui/themes/BrightTheme.h"
+#include "ui/themes/CustomTheme.h"
+#include "ui/themes/DarkTheme.h"
+#include "ui/themes/SystemTheme.h"
+
+#include "Application.h"
+
+#ifdef Q_OS_WIN
+#include <windows.h>
+// this is needed for versionhelpers.h, it is also included in WinDarkmode, but we can't rely on that.
+// Ultimately this should be included in versionhelpers, but that is outside of the project.
+#include "ui/WinDarkmode.h"
+#include <versionhelpers.h>
+#endif
+
+ThemeManager::ThemeManager(MainWindow* mainWindow)
+{
+ m_mainWindow = mainWindow;
+ InitializeThemes();
+}
+
+/// @brief Adds the Theme to the list of themes
+/// @param theme The Theme to add
+/// @return Theme ID
+QString ThemeManager::AddTheme(std::unique_ptr<ITheme> theme)
+{
+ QString id = theme->id();
+ m_themes.emplace(id, std::move(theme));
+ return id;
+}
+
+/// @brief Gets the Theme from the List via ID
+/// @param themeId Theme ID of theme to fetch
+/// @return Theme at themeId
+ITheme* ThemeManager::GetTheme(QString themeId)
+{
+ return m_themes[themeId].get();
+}
+
+void ThemeManager::InitializeThemes()
+{
+ // Icon themes
+ {
+ // TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies!
+ // set icon theme search path!
+ auto searchPaths = QIcon::themeSearchPaths();
+ searchPaths.append("iconthemes");
+ QIcon::setThemeSearchPaths(searchPaths);
+ themeDebugLog() << "<> Icon themes initialized.";
+ }
+
+ // Initialize widget themes
+ {
+ themeDebugLog() << "<> Initializing Widget Themes";
+ themeDebugLog() << "Loading Built-in Theme:" << AddTheme(std::make_unique<SystemTheme>());
+ auto darkThemeId = AddTheme(std::make_unique<DarkTheme>());
+ themeDebugLog() << "Loading Built-in Theme:" << darkThemeId;
+ themeDebugLog() << "Loading Built-in Theme:" << AddTheme(std::make_unique<BrightTheme>());
+
+ // TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in
+ // dropdown?)
+ QString themeFolder = QDir("./themes/").absoluteFilePath("");
+ themeDebugLog() << "Theme Folder Path: " << themeFolder;
+
+ QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
+ while (directoryIterator.hasNext()) {
+ QDir dir(directoryIterator.next());
+ QFileInfo themeJson(dir.absoluteFilePath("theme.json"));
+ if (themeJson.exists()) {
+ // Load "theme.json" based themes
+ themeDebugLog() << "Loading JSON Theme from:" << themeJson.absoluteFilePath();
+ AddTheme(std::make_unique<CustomTheme>(GetTheme(darkThemeId), themeJson, true));
+ } else {
+ // Load pure QSS Themes
+ QDirIterator stylesheetFileIterator(dir.absoluteFilePath(""), { "*.qss", "*.css" }, QDir::Files);
+ while (stylesheetFileIterator.hasNext()) {
+ QFile customThemeFile(stylesheetFileIterator.next());
+ QFileInfo customThemeFileInfo(customThemeFile);
+ themeDebugLog() << "Loading QSS Theme from:" << customThemeFileInfo.absoluteFilePath();
+ AddTheme(std::make_unique<CustomTheme>(GetTheme(darkThemeId), customThemeFileInfo, false));
+ }
+ }
+ }
+
+ themeDebugLog() << "<> Widget themes initialized.";
+ }
+}
+
+QList<ITheme*> ThemeManager::getValidApplicationThemes()
+{
+ QList<ITheme*> ret;
+ ret.reserve(m_themes.size());
+ for (auto&& [id, theme] : m_themes) {
+ ret.append(theme.get());
+ }
+ return ret;
+}
+
+void ThemeManager::setIconTheme(const QString& name)
+{
+ QIcon::setThemeName(name);
+}
+
+void ThemeManager::applyCurrentlySelectedTheme()
+{
+ setIconTheme(APPLICATION->settings()->get("IconTheme").toString());
+ themeDebugLog() << "<> Icon theme set.";
+ setApplicationTheme(APPLICATION->settings()->get("ApplicationTheme").toString(), true);
+ themeDebugLog() << "<> Application theme set.";
+}
+
+void ThemeManager::setApplicationTheme(const QString& name, bool initial)
+{
+ auto systemPalette = qApp->palette();
+ auto themeIter = m_themes.find(name);
+ if (themeIter != m_themes.end()) {
+ auto& theme = themeIter->second;
+ themeDebugLog() << "applying theme" << theme->name();
+ theme->apply(initial);
+#ifdef Q_OS_WIN
+ if (m_mainWindow && IsWindows10OrGreater()) {
+ if (QString::compare(theme->id(), "dark") == 0) {
+ WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), true);
+ } else {
+ WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), false);
+ }
+ }
+#endif
+ } else {
+ themeWarningLog() << "Tried to set invalid theme:" << name;
+ }
+}
diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h new file mode 100644 index 00000000..b85cb742 --- /dev/null +++ b/launcher/ui/themes/ThemeManager.h @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Tayou <tayou@gmx.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <QString>
+
+#include "ui/MainWindow.h"
+#include "ui/themes/ITheme.h"
+
+inline auto themeDebugLog()
+{
+ return qDebug() << "[Theme]";
+}
+inline auto themeWarningLog()
+{
+ return qWarning() << "[Theme]";
+}
+
+class ThemeManager {
+ public:
+ ThemeManager(MainWindow* mainWindow);
+
+ // maybe make private? Or put in ctor?
+ void InitializeThemes();
+
+ QList<ITheme*> getValidApplicationThemes();
+ void setIconTheme(const QString& name);
+ void applyCurrentlySelectedTheme();
+ void setApplicationTheme(const QString& name, bool initial);
+
+ private:
+ std::map<QString, std::unique_ptr<ITheme>> m_themes;
+ MainWindow* m_mainWindow;
+
+ QString AddTheme(std::unique_ptr<ITheme> theme);
+ ITheme* GetTheme(QString themeId);
+};
diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 314a126e..c7c4dbbd 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -245,7 +245,7 @@ void JavaSettingsWidget::memoryValueChanged(int) } } -void JavaSettingsWidget::javaVersionSelected(BaseVersionPtr version) +void JavaSettingsWidget::javaVersionSelected(BaseVersion::Ptr version) { auto java = std::dynamic_pointer_cast<JavaInstall>(version); if(!java) diff --git a/launcher/ui/widgets/JavaSettingsWidget.h b/launcher/ui/widgets/JavaSettingsWidget.h index 0d280daf..5344e2cd 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.h +++ b/launcher/ui/widgets/JavaSettingsWidget.h @@ -60,7 +60,7 @@ public: protected slots: void memoryValueChanged(int); void javaPathEdited(const QString &path); - void javaVersionSelected(BaseVersionPtr version); + void javaVersionSelected(BaseVersion::Ptr version); void on_javaBrowseBtn_clicked(); void on_javaStatusBtn_clicked(); void checkFinished(JavaCheckResult result); diff --git a/launcher/ui/widgets/ModFilterWidget.h b/launcher/ui/widgets/ModFilterWidget.h index 958a1e2b..706ffd21 100644 --- a/launcher/ui/widgets/ModFilterWidget.h +++ b/launcher/ui/widgets/ModFilterWidget.h @@ -49,7 +49,7 @@ public: auto getFilter() -> std::shared_ptr<Filter>; auto changed() const -> bool { return m_last_version_id != m_version_id; } - Meta::VersionListPtr versionList() { return m_version_list; } + Meta::VersionList::Ptr versionList() { return m_version_list; } private: ModFilterWidget(Version def, QWidget* parent = nullptr); @@ -73,7 +73,7 @@ private: /* Version stuff */ QButtonGroup m_mcVersion_buttons; - Meta::VersionListPtr m_version_list; + Meta::VersionList::Ptr m_version_list; /* Used to tell if the filter was changed since the last getFilter() call */ VersionButtonID m_last_version_id = VersionButtonID::Strict; diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index cc4fc6a2..404860d9 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -142,7 +142,7 @@ void VersionSelectWidget::changeProgress(qint64 current, qint64 total) void VersionSelectWidget::currentRowChanged(const QModelIndex& current, const QModelIndex&) { auto variant = m_proxyModel->data(current, BaseVersionList::VersionPointerRole); - emit selectedVersionChanged(variant.value<BaseVersionPtr>()); + emit selectedVersionChanged(variant.value<BaseVersion::Ptr>()); } void VersionSelectWidget::preselect() @@ -186,11 +186,11 @@ bool VersionSelectWidget::hasVersions() const return m_proxyModel->rowCount(QModelIndex()) != 0; } -BaseVersionPtr VersionSelectWidget::selectedVersion() const +BaseVersion::Ptr VersionSelectWidget::selectedVersion() const { auto currentIndex = listView->selectionModel()->currentIndex(); auto variant = m_proxyModel->data(currentIndex, BaseVersionList::VersionPointerRole); - return variant.value<BaseVersionPtr>(); + return variant.value<BaseVersion::Ptr>(); } void VersionSelectWidget::setExactFilter(BaseVersionList::ModelRoles role, QString filter) diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index f56daa8a..e75efc6f 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -40,7 +40,7 @@ public: void loadList(); bool hasVersions() const; - BaseVersionPtr selectedVersion() const; + BaseVersion::Ptr selectedVersion() const; void selectRecommended(); void selectCurrent(); @@ -54,7 +54,7 @@ public: void setResizeOn(int column); signals: - void selectedVersionChanged(BaseVersionPtr version); + void selectedVersionChanged(BaseVersion::Ptr version); protected: virtual void closeEvent ( QCloseEvent* ); diff --git a/libraries/LocalPeer/src/LocalPeer.cpp b/libraries/LocalPeer/src/LocalPeer.cpp index 3c3d8b4c..b7149c40 100644 --- a/libraries/LocalPeer/src/LocalPeer.cpp +++ b/libraries/LocalPeer/src/LocalPeer.cpp @@ -210,7 +210,7 @@ void LocalPeer::receiveConnection() return; } - while (socket->bytesAvailable() < (int)sizeof(quint32)) + while (socket->bytesAvailable() < static_cast<int>(sizeof(quint32))) { socket->waitForReadyRead(); } diff --git a/libraries/extra-cmake-modules b/libraries/extra-cmake-modules new file mode 160000 +Subproject bbcbaff78283270c2beee69afd8d5b91da854af diff --git a/libraries/hoedown/src/autolink.c b/libraries/hoedown/src/autolink.c index 3063b1a0..3592b8e3 100644 --- a/libraries/hoedown/src/autolink.c +++ b/libraries/hoedown/src/autolink.c @@ -150,7 +150,7 @@ hoedown_autolink__www( uint8_t *data, size_t max_rewind, size_t size, - unsigned int flags) + hoedown_autolink_flags flags) { size_t link_end; @@ -186,7 +186,7 @@ hoedown_autolink__email( uint8_t *data, size_t max_rewind, size_t size, - unsigned int flags) + hoedown_autolink_flags flags) { size_t link_end, rewind; int nb = 0, np = 0; @@ -242,7 +242,7 @@ hoedown_autolink__url( uint8_t *data, size_t max_rewind, size_t size, - unsigned int flags) + hoedown_autolink_flags flags) { size_t link_end, rewind = 0, domain_len; diff --git a/libraries/katabasis/src/DeviceFlow.cpp b/libraries/katabasis/src/DeviceFlow.cpp index ba1d121d..f78fd620 100644 --- a/libraries/katabasis/src/DeviceFlow.cpp +++ b/libraries/katabasis/src/DeviceFlow.cpp @@ -445,7 +445,7 @@ void DeviceFlow::onRefreshError(QNetworkReply::NetworkError error, QNetworkReply if(refreshReply) { refreshReply->deleteLater(); } - qDebug() << "DeviceFlow::onRefreshFinished: Error" << (int)error << " - " << errorString; + qDebug() << "DeviceFlow::onRefreshFinished: Error" << static_cast<int>(error) << " - " << errorString; } } diff --git a/libraries/murmur2/src/MurmurHash2.cpp b/libraries/murmur2/src/MurmurHash2.cpp index b625efb1..c13608f0 100644 --- a/libraries/murmur2/src/MurmurHash2.cpp +++ b/libraries/murmur2/src/MurmurHash2.cpp @@ -55,12 +55,12 @@ uint32_t MurmurHash2(std::ifstream&& file_stream, std::size_t buffer_size, std:: // Mix 4 bytes at a time into the hash if (index == 0) - FourBytes_MurmurHash2((unsigned char*)&data, info); + FourBytes_MurmurHash2(reinterpret_cast<unsigned char*>(&data), info); } } while (!file_stream.eof()); // Do one last bit shuffle in the hash - FourBytes_MurmurHash2((unsigned char*)&data, info); + FourBytes_MurmurHash2(reinterpret_cast<unsigned char*>(&data), info); delete[] buffer; @@ -72,7 +72,7 @@ void FourBytes_MurmurHash2(const unsigned char* data, IncrementalHashInfo& prev) { if (prev.len >= 4) { // Not the final mix - uint32_t k = *(uint32_t*)data; + uint32_t k = *reinterpret_cast<const uint32_t*>(data); k *= m; k ^= k >> r; diff --git a/libraries/zlib b/libraries/zlib new file mode 160000 +Subproject 04f42ceca40f73e2978b50e93806c2a18c1281f diff --git a/program_info/CMakeLists.txt b/program_info/CMakeLists.txt index f6e2ea84..8c682711 100644 --- a/program_info/CMakeLists.txt +++ b/program_info/CMakeLists.txt @@ -15,14 +15,17 @@ set(Launcher_Name "${Launcher_CommonName}" PARENT_SCOPE) set(Launcher_DisplayName "${Launcher_DisplayName}" PARENT_SCOPE) set(Launcher_Copyright "Prism Launcher Contributors\\n© 2021-2022 PolyMC Contributors \\n© 2012-2021 MultiMC Contributors") +set(Launcher_Copyright_Mac "Prism Launcher Contributors, © 2021-2022 PolyMC Contributors and © 2012-2021 MultiMC Contributors" PARENT_SCOPE) set(Launcher_Copyright "${Launcher_Copyright}" PARENT_SCOPE) set(Launcher_Domain "prismlauncher.org" PARENT_SCOPE) set(Launcher_UserAgent "${Launcher_CommonName}/${Launcher_VERSION_NAME}" PARENT_SCOPE) set(Launcher_ConfigFile "prismlauncher.cfg" PARENT_SCOPE) set(Launcher_Git "https://github.com/PrismLauncher/PrismLauncher" PARENT_SCOPE) set(Launcher_DesktopFileName "org.prismlauncher.PrismLauncher.desktop" PARENT_SCOPE) +set(Launcher_SVGFileName "org.prismlauncher.PrismLauncher.svg" PARENT_SCOPE) set(Launcher_Desktop "program_info/org.prismlauncher.PrismLauncher.desktop" PARENT_SCOPE) +set(Launcher_mrpack_MIMEInfo "program_info/modrinth-mrpack-mime.xml" PARENT_SCOPE) set(Launcher_MetaInfo "program_info/org.prismlauncher.PrismLauncher.metainfo.xml" PARENT_SCOPE) set(Launcher_SVG "program_info/org.prismlauncher.PrismLauncher.svg" PARENT_SCOPE) set(Launcher_Branding_ICNS "program_info/prismlauncher.icns" PARENT_SCOPE) diff --git a/program_info/genicons.sh b/program_info/genicons.sh index bfe756d8..42592c4e 100755 --- a/program_info/genicons.sh +++ b/program_info/genicons.sh @@ -1,39 +1,73 @@ -#/bin/bash +#!/bin/bash -# ICO +svg2png() { + input_file="$1" + output_file="$2" + width="$3" + height="$4" -inkscape -w 16 -h 16 -o prismlauncher_16.png org.prismlauncher.PrismLauncher.svg -inkscape -w 24 -h 24 -o prismlauncher_24.png org.prismlauncher.PrismLauncher.svg -inkscape -w 32 -h 32 -o prismlauncher_32.png org.prismlauncher.PrismLauncher.svg -inkscape -w 48 -h 48 -o prismlauncher_48.png org.prismlauncher.PrismLauncher.svg -inkscape -w 64 -h 64 -o prismlauncher_64.png org.prismlauncher.PrismLauncher.svg -inkscape -w 128 -h 128 -o prismlauncher_128.png org.prismlauncher.PrismLauncher.svg + inkscape -w "$width" -h "$height" -o "$output_file" "$input_file" +} -convert prismlauncher_128.png prismlauncher_64.png prismlauncher_48.png prismlauncher_32.png prismlauncher_24.png prismlauncher_16.png prismlauncher.ico +sipsresize() { + input_file="$1" + output_file="$2" + width="$3" + height="$4" -rm -f prismlauncher_*.png + sips -z "$width" "$height" "$input_file" --out "$output_file" +} -inkscape -w 1024 -h 1024 -o prismlauncher_1024.png org.prismlauncher.PrismLauncher.bigsur.svg +if command -v "inkscape" && command -v "icotool"; then + # Windows ICO + d=$(mktemp -d) -mkdir prismlauncher.iconset + svg2png org.prismlauncher.PrismLauncher.svg "$d/prismlauncher_16.png" 16 16 + svg2png org.prismlauncher.PrismLauncher.svg "$d/prismlauncher_24.png" 24 24 + svg2png org.prismlauncher.PrismLauncher.svg "$d/prismlauncher_32.png" 32 32 + svg2png org.prismlauncher.PrismLauncher.svg "$d/prismlauncher_48.png" 48 48 + svg2png org.prismlauncher.PrismLauncher.svg "$d/prismlauncher_64.png" 64 64 + svg2png org.prismlauncher.PrismLauncher.svg "$d/prismlauncher_128.png" 128 128 + svg2png org.prismlauncher.PrismLauncher.svg "$d/prismlauncher_256.png" 256 256 -sips -z 16 16 prismlauncher_1024.png --out prismlauncher.iconset/icon_16x16.png -sips -z 32 32 prismlauncher_1024.png --out prismlauncher.iconset/icon_16x16@2x.png -sips -z 32 32 prismlauncher_1024.png --out prismlauncher.iconset/icon_32x32.png -sips -z 64 64 prismlauncher_1024.png --out prismlauncher.iconset/icon_32x32@2x.png -sips -z 128 128 prismlauncher_1024.png --out prismlauncher.iconset/icon_128x128.png -sips -z 256 256 prismlauncher_1024.png --out prismlauncher.iconset/icon_128x128@2x.png -sips -z 256 256 prismlauncher_1024.png --out prismlauncher.iconset/icon_256x256.png -sips -z 512 512 prismlauncher_1024.png --out prismlauncher.iconset/icon_256x256@2x.png -sips -z 512 512 prismlauncher_1024.png --out prismlauncher.iconset/icon_512x512.png -cp prismlauncher_1024.png prismlauncher.iconset/icon_512x512@2x.png + rm prismlauncher.ico && icotool -o prismlauncher.ico -c \ + "$d/prismlauncher_256.png" \ + "$d/prismlauncher_128.png" \ + "$d/prismlauncher_64.png" \ + "$d/prismlauncher_48.png" \ + "$d/prismlauncher_32.png" \ + "$d/prismlauncher_24.png" \ + "$d/prismlauncher_16.png" +else + echo "ERROR: Windows icons were NOT generated!" >&2 + echo "ERROR: requires inkscape and icotool in PATH" +fi -iconutil -c icns prismlauncher.iconset +if command -v "inkscape" && command -v "sips" && command -v "iconutil"; then + # macOS ICNS + d=$(mktemp -d) -rm -f prismlauncher_*.png -rm -rf prismlauncher.iconset + d="$d/prismlauncher.iconset" + mkdir -p "$d" + + svg2png org.prismlauncher.PrismLauncher.bigsur.svg "$d/icon_512x512@2x.png" 1024 1024 + sipsresize "$d/icon_512x512@2.png" "$d/icon_16x16.png" 16 16 + sipsresize "$d/icon_512x512@2.png" "$d/icon_16x16@2.png" 32 32 + sipsresize "$d/icon_512x512@2.png" "$d/icon_32x32.png" 32 32 + sipsresize "$d/icon_512x512@2.png" "$d/icon_32x32@2.png" 64 64 + sipsresize "$d/icon_512x512@2.png" "$d/icon_128x128.png" 128 128 + sipsresize "$d/icon_512x512@2.png" "$d/icon_128x128@2.png" 256 256 + sipsresize "$d/icon_512x512@2.png" "$d/icon_256x256.png" 256 256 + sipsresize "$d/icon_512x512@2.png" "$d/icon_256x256@2.png" 512 512 + iconutil -c icns "$d" +else + echo "ERROR: macOS icons were NOT generated!" >&2 + echo "ERROR: requires inkscape, sips and iconutil in PATH" +fi + +# replace icon in themes for dir in ../launcher/resources/*/scalable do - cp -v org.prismlauncher.PrismLauncher.svg $dir/launcher.svg + cp -v org.prismlauncher.PrismLauncher.svg "$dir/launcher.svg" done diff --git a/program_info/modrinth-mrpack-mime.xml b/program_info/modrinth-mrpack-mime.xml new file mode 100644 index 00000000..5001e5e7 --- /dev/null +++ b/program_info/modrinth-mrpack-mime.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+ <mime-type type="application/x-modrinth-modpack+zip">
+ <comment>Modrinth Modpack File</comment>
+ <icon name="application-x-modrinth-modpack"/>
+ <glob-deleteall/>
+ <glob pattern="*.mrpack"/>
+ </mime-type>
+</mime-info>
diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in index e608f588..f08f2ba4 100644 --- a/program_info/org.prismlauncher.PrismLauncher.desktop.in +++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in @@ -10,3 +10,4 @@ Icon=org.prismlauncher.PrismLauncher Categories=Game;ActionGame;AdventureGame;Simulation; Keywords=game;minecraft;launcher;mc;multimc;polymc; StartupWMClass=PrismLauncher +MimeType=application/zip;application/x-modrinth-modpack+zip diff --git a/program_info/prismlauncher.6.scd b/program_info/prismlauncher.6.scd index e3c7de86..f979e457 100644 --- a/program_info/prismlauncher.6.scd +++ b/program_info/prismlauncher.6.scd @@ -26,6 +26,9 @@ Here are the current features of Prism Launcher. *-l, --launch*=INSTANCE_ID Launch the instance specified by INSTANCE_ID. +*--show*=INSTANCE_ID + Show the configuration window of the instance specified by INSTANCE_ID. + *--alive* Write a small 'live.check' file after Prism Launcher starts. diff --git a/program_info/prismlauncher.ico b/program_info/prismlauncher.ico Binary files differindex e4529f93..2f0fa67f 100644 --- a/program_info/prismlauncher.ico +++ b/program_info/prismlauncher.ico diff --git a/program_info/prismlauncher.manifest.in b/program_info/prismlauncher.manifest.in index 1d764445..6f4467c7 100644 --- a/program_info/prismlauncher.manifest.in +++ b/program_info/prismlauncher.manifest.in @@ -10,7 +10,7 @@ </trustInfo> <dependency> <dependentAssembly> - <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"/> + <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/> </dependentAssembly> </dependency> <description>Custom Minecraft launcher for managing multiple installs.</description> diff --git a/program_info/win_install.nsi.in b/program_info/win_install.nsi.in index 1c1f29da..0cd7ea11 100644 --- a/program_info/win_install.nsi.in +++ b/program_info/win_install.nsi.in @@ -4,7 +4,7 @@ Unicode true -Name "@Launcher_CommonName@" +Name "@Launcher_DisplayName@" InstallDir "$LOCALAPPDATA\Programs\@Launcher_CommonName@" InstallDirRegKey HKCU "Software\@Launcher_CommonName@" "InstallDir" RequestExecutionLevel user @@ -113,7 +113,7 @@ VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductVersion" "@Launcher_VERSION_NAME4@ ;-------------------------------- ; The stuff to install -Section "@Launcher_CommonName@" +Section "@Launcher_DisplayName@" SectionIn RO diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml new file mode 100644 index 00000000..8e647eea --- /dev/null +++ b/snap/snapcraft.yaml @@ -0,0 +1,55 @@ +name: prismlauncher +license: GPL-3.0-only +base: core20 +website: https://prismlauncher.org/ +source-code: https://github.com/PrismLauncher/PrismLauncher +issues: https://github.com/PrismLauncher/PrismLauncher/issues +donation: https://opencollective.com/prismlauncher +contact: https://discord.gg/prismlauncher +summary: A custom Minecraft launcher with modpack support +adopt-info: prismlauncher + +grade: devel +confinement: strict + +architectures: + - build-on: amd64 + - build-on: arm64 + +parts: + prismlauncher: + parse-info: + - usr/share/metainfo/org.prismlauncher.PrismLauncher.metainfo.xml + plugin: cmake + build-packages: + - default-jdk-headless + stage-packages: + - openjdk-17-jre + - openjdk-8-jre + source: . + override-pull: | + snapcraftctl pull + # Fix the icon reference in the desktop file + sed -i.bak -e 's|Icon=org.prismlauncher.PrismLauncher|Icon=/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg|g' program_info/org.prismlauncher.PrismLauncher.desktop.in + # Remove the build directory so that local development doesn't interfere with Snap compilation + rm -rf build + cmake-generator: Ninja + cmake-parameters: + - "-DCMAKE_INSTALL_PREFIX=/usr" + - "-DCMAKE_BUILD_TYPE=RelWithDebInfo" + - "-DENABLE_LTO=ON" + - "-DLauncher_BUILD_PLATFORM=snap" + +apps: + prismlauncher: + common-id: org.prismlauncher.PrismLauncher + desktop: usr/share/applications/org.prismlauncher.PrismLauncher.desktop + command: usr/bin/prismlauncher + extensions: + - kde-neon + plugs: + - home + - opengl + - network + - network-bind + - audio-playback diff --git a/tests/FileSystem_test.cpp b/tests/FileSystem_test.cpp index 47a963b0..21270f6f 100644 --- a/tests/FileSystem_test.cpp +++ b/tests/FileSystem_test.cpp @@ -183,6 +183,32 @@ slots: f(); } + void test_copy_single_file() + { + QTemporaryDir tempDir; + tempDir.setAutoRemove(true); + + { + QString file = QFINDTESTDATA("testdata/FileSystem/test_folder/pack.mcmeta"); + + qDebug() << "From:" << file << "To:" << tempDir.path(); + + QDir target_dir(FS::PathCombine(tempDir.path(), "pack.mcmeta")); + qDebug() << tempDir.path(); + qDebug() << target_dir.path(); + FS::copy c(file, target_dir.filePath("pack.mcmeta")); + c(); + + auto filter = QDir::Filter::Files; + + for (auto entry: target_dir.entryList(filter)) { + qDebug() << entry; + } + + QVERIFY(target_dir.entryList(filter).contains("pack.mcmeta")); + } + } + void test_getDesktop() { QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); diff --git a/tests/GZip_test.cpp b/tests/GZip_test.cpp index 1e762b2e..82503d81 100644 --- a/tests/GZip_test.cpp +++ b/tests/GZip_test.cpp @@ -24,7 +24,7 @@ slots: QByteArray compressed; QByteArray decompressed; std::default_random_engine eng((std::random_device())()); - std::uniform_int_distribution<uint8_t> idis(0, std::numeric_limits<uint8_t>::max()); + std::uniform_int_distribution<uint16_t> idis(0, std::numeric_limits<uint8_t>::max()); // initialize random buffer for(int i = 0; i < size; i++) |