Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into current_time
4
.clang-tidy
Normal file
@ -0,0 +1,4 @@
|
||||
Checks:
|
||||
- modernize-use-using
|
||||
|
||||
SystemHeaders: false
|
2
.github/workflows/backport.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Create backport PRs
|
||||
uses: korthout/backport-action@v1.4.0
|
||||
uses: korthout/backport-action@v2.1.1
|
||||
with:
|
||||
# Config README: https://github.com/korthout/backport-action#backport-action
|
||||
pull_description: |-
|
||||
|
114
.github/workflows/build.yml
vendored
@ -37,44 +37,43 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
|
||||
- os: ubuntu-20.04
|
||||
qt_ver: 5
|
||||
|
||||
- os: ubuntu-20.04
|
||||
qt_ver: 6
|
||||
qt_host: linux
|
||||
qt_arch: ''
|
||||
qt_version: '6.2.4'
|
||||
qt_modules: 'qt5compat qtimageformats'
|
||||
qt_tools: ''
|
||||
qt_arch: ""
|
||||
qt_version: "6.2.4"
|
||||
qt_modules: "qt5compat qtimageformats"
|
||||
qt_tools: ""
|
||||
|
||||
- os: windows-2022
|
||||
name: "Windows-MinGW-w64"
|
||||
msystem: clang64
|
||||
vcvars_arch: 'amd64_x86'
|
||||
vcvars_arch: "amd64_x86"
|
||||
|
||||
- os: windows-2022
|
||||
name: "Windows-MSVC"
|
||||
msystem: ''
|
||||
architecture: 'x64'
|
||||
vcvars_arch: 'amd64'
|
||||
msystem: ""
|
||||
architecture: "x64"
|
||||
vcvars_arch: "amd64"
|
||||
qt_ver: 6
|
||||
qt_host: windows
|
||||
qt_arch: ''
|
||||
qt_version: '6.5.2'
|
||||
qt_version: '6.6.0'
|
||||
qt_modules: 'qt5compat qtimageformats'
|
||||
qt_tools: ''
|
||||
|
||||
- os: windows-2022
|
||||
name: "Windows-MSVC-arm64"
|
||||
msystem: ''
|
||||
architecture: 'arm64'
|
||||
vcvars_arch: 'amd64_arm64'
|
||||
msystem: ""
|
||||
architecture: "arm64"
|
||||
vcvars_arch: "amd64_arm64"
|
||||
qt_ver: 6
|
||||
qt_host: windows
|
||||
qt_arch: 'win64_msvc2019_arm64'
|
||||
qt_version: '6.5.2'
|
||||
qt_version: '6.6.0'
|
||||
qt_modules: 'qt5compat qtimageformats'
|
||||
qt_tools: ''
|
||||
|
||||
@ -84,7 +83,7 @@ jobs:
|
||||
qt_ver: 6
|
||||
qt_host: mac
|
||||
qt_arch: ''
|
||||
qt_version: '6.5.2'
|
||||
qt_version: '6.6.0'
|
||||
qt_modules: 'qt5compat qtimageformats'
|
||||
qt_tools: ''
|
||||
|
||||
@ -93,9 +92,9 @@ jobs:
|
||||
macosx_deployment_target: 10.13
|
||||
qt_ver: 5
|
||||
qt_host: mac
|
||||
qt_version: '5.15.2'
|
||||
qt_modules: ''
|
||||
qt_tools: ''
|
||||
qt_version: "5.15.2"
|
||||
qt_modules: ""
|
||||
qt_tools: ""
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
@ -115,9 +114,9 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'true'
|
||||
submodules: "true"
|
||||
|
||||
- name: 'Setup MSYS2'
|
||||
- name: "Setup MSYS2"
|
||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
@ -157,7 +156,7 @@ jobs:
|
||||
path: '${{ github.workspace }}\.ccache'
|
||||
key: ${{ matrix.os }}-mingw-w64-ccache-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ matrix.os }}-mingw-w64-ccache
|
||||
${{ matrix.os }}-mingw-w64-ccache
|
||||
|
||||
- name: Setup ccache (Windows MinGW-w64)
|
||||
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
|
||||
@ -202,35 +201,35 @@ jobs:
|
||||
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
aqtversion: '==3.1.*'
|
||||
py7zrversion: '>=0.20.2'
|
||||
version: ${{ matrix.qt_version }}
|
||||
host: 'windows'
|
||||
target: 'desktop'
|
||||
arch: ''
|
||||
modules: ${{ matrix.qt_modules }}
|
||||
tools: ${{ matrix.qt_tools }}
|
||||
cache: ${{ inputs.is_qt_cached }}
|
||||
cache-key-prefix: host-qt-arm64-windows
|
||||
dir: ${{ github.workspace }}\HostQt
|
||||
set-env: false
|
||||
aqtversion: "==3.1.*"
|
||||
py7zrversion: ">=0.20.2"
|
||||
version: ${{ matrix.qt_version }}
|
||||
host: "windows"
|
||||
target: "desktop"
|
||||
arch: ""
|
||||
modules: ${{ matrix.qt_modules }}
|
||||
tools: ${{ matrix.qt_tools }}
|
||||
cache: ${{ inputs.is_qt_cached }}
|
||||
cache-key-prefix: host-qt-arm64-windows
|
||||
dir: ${{ github.workspace }}\HostQt
|
||||
set-env: false
|
||||
|
||||
- name: Install Qt (macOS, Linux, Qt 6 & 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:
|
||||
aqtversion: '==3.1.*'
|
||||
py7zrversion: '>=0.20.2'
|
||||
version: ${{ matrix.qt_version }}
|
||||
host: ${{ matrix.qt_host }}
|
||||
target: 'desktop'
|
||||
arch: ${{ matrix.qt_arch }}
|
||||
modules: ${{ matrix.qt_modules }}
|
||||
tools: ${{ matrix.qt_tools }}
|
||||
cache: ${{ inputs.is_qt_cached }}
|
||||
aqtversion: "==3.1.*"
|
||||
py7zrversion: ">=0.20.2"
|
||||
version: ${{ matrix.qt_version }}
|
||||
host: ${{ matrix.qt_host }}
|
||||
target: "desktop"
|
||||
arch: ${{ matrix.qt_arch }}
|
||||
modules: ${{ matrix.qt_modules }}
|
||||
tools: ${{ matrix.qt_tools }}
|
||||
cache: ${{ inputs.is_qt_cached }}
|
||||
|
||||
- name: Install MSVC (Windows MSVC)
|
||||
if: runner.os == 'Windows' # We want this for MinGW builds as well, as we need SignTool
|
||||
if: runner.os == 'Windows' # We want this for MinGW builds as well, as we need SignTool
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
vsversion: 2022
|
||||
@ -271,12 +270,12 @@ jobs:
|
||||
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=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -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=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} -G Ninja
|
||||
|
||||
- name: Configure CMake (Windows MSVC)
|
||||
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=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON
|
||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }}
|
||||
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix)
|
||||
if ("${{ env.CCACHE_VAR }}")
|
||||
{
|
||||
@ -291,7 +290,7 @@ jobs:
|
||||
- name: Configure CMake (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -G Ninja
|
||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -G Ninja
|
||||
|
||||
##
|
||||
# BUILD
|
||||
@ -390,10 +389,9 @@ jobs:
|
||||
|
||||
Get-ChildItem ${{ env.INSTALL_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
|
||||
|
||||
|
||||
- name: Fetch codesign certificate (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash # yes, we are not using MSYS2 or PowerShell here
|
||||
shell: bash # yes, we are not using MSYS2 or PowerShell here
|
||||
run: |
|
||||
echo '${{ secrets.WINDOWS_CODESIGN_CERT }}' | base64 --decode > codesign.pfx
|
||||
|
||||
@ -403,7 +401,7 @@ jobs:
|
||||
if (Get-Content ./codesign.pfx){
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
# We ship the exact same executable for portable and non-portable editions, so signing just once is fine
|
||||
SignTool sign /fd sha256 /td sha256 /f ../codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com prismlauncher.exe prismlauncher_filelink.exe
|
||||
SignTool sign /fd sha256 /td sha256 /f ../codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com prismlauncher.exe prismlauncher_updater.exe prismlauncher_filelink.exe
|
||||
} else {
|
||||
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
|
||||
}
|
||||
@ -495,15 +493,7 @@ jobs:
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
chmod +x AppImageUpdate-x86_64.AppImage
|
||||
./AppImageUpdate-x86_64.AppImage --appimage-extract
|
||||
|
||||
mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/optional
|
||||
mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins
|
||||
|
||||
cp -r squashfs-root/usr/bin/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin
|
||||
cp -r squashfs-root/usr/lib/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib
|
||||
cp -r squashfs-root/usr/optional/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/optional
|
||||
cp -r squashfs-root/usr/optional/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins
|
||||
cp AppImageUpdate-x86_64.AppImage ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin
|
||||
|
||||
export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-x86_64.AppImage.zsync"
|
||||
|
||||
@ -511,7 +501,7 @@ jobs:
|
||||
export SIGN=1
|
||||
export SIGN_KEY=${{ secrets.GPG_PRIVATE_KEY_ID }}
|
||||
mkdir -p ~/.gnupg/
|
||||
printf "$GPG_PRIVATE_KEY" | base64 --decode > ~/.gnupg/private.key
|
||||
echo "$GPG_PRIVATE_KEY" > ~/.gnupg/private.key
|
||||
gpg --import ~/.gnupg/private.key
|
||||
else
|
||||
echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $GITHUB_STEP_SUMMARY
|
||||
@ -557,14 +547,14 @@ jobs:
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
name: PrismLauncher-${{ runner.os }}-Qt5-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher.tar.gz
|
||||
|
||||
- name: Upload binary tarball (Linux, portable, Qt 5)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
name: PrismLauncher-${{ runner.os }}-Qt5-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher-portable.tar.gz
|
||||
|
||||
- name: Upload binary tarball (Linux, Qt 6)
|
||||
@ -611,7 +601,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
if: inputs.build_type == 'Debug'
|
||||
with:
|
||||
submodules: 'true'
|
||||
submodules: "true"
|
||||
- name: Build Flatpak (Linux)
|
||||
if: inputs.build_type == 'Debug'
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||
|
29
.github/workflows/trigger_builds.yml
vendored
@ -3,26 +3,25 @@ name: Build Application
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- 'renovate/**'
|
||||
- "renovate/**"
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '**/LICENSE'
|
||||
- 'flake.lock'
|
||||
- 'packages/**'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
- '.markdownlint**'
|
||||
- "**.md"
|
||||
- "**/LICENSE"
|
||||
- "flake.lock"
|
||||
- "packages/**"
|
||||
- ".github/ISSUE_TEMPLATE/**"
|
||||
- ".markdownlint**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '**/LICENSE'
|
||||
- 'flake.lock'
|
||||
- 'packages/**'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
- '.markdownlint**'
|
||||
- "**.md"
|
||||
- "**/LICENSE"
|
||||
- "flake.lock"
|
||||
- "packages/**"
|
||||
- ".github/ISSUE_TEMPLATE/**"
|
||||
- ".markdownlint**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
build_debug:
|
||||
name: Build Debug
|
||||
uses: ./.github/workflows/build.yml
|
||||
@ -34,3 +33,5 @@ jobs:
|
||||
WINDOWS_CODESIGN_CERT: ${{ secrets.WINDOWS_CODESIGN_CERT }}
|
||||
WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }}
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
GPG_PRIVATE_KEY_ID: ${{ secrets.GPG_PRIVATE_KEY_ID }}
|
||||
|
10
.github/workflows/trigger_release.yml
vendored
@ -17,6 +17,8 @@ jobs:
|
||||
WINDOWS_CODESIGN_CERT: ${{ secrets.WINDOWS_CODESIGN_CERT }}
|
||||
WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }}
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
GPG_PRIVATE_KEY_ID: ${{ secrets.GPG_PRIVATE_KEY_ID }}
|
||||
|
||||
create_release:
|
||||
needs: build_release
|
||||
@ -40,8 +42,8 @@ jobs:
|
||||
mv ${{ github.workspace }}/PrismLauncher-source PrismLauncher-${{ env.VERSION }}
|
||||
mv PrismLauncher-Linux-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-Linux-Qt6*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-Linux-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-Linux*/PrismLauncher.tar.gz PrismLauncher-Linux-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-Linux-Qt5-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt5-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-Linux-Qt5*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt5-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-x86_64.AppImage
|
||||
mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync
|
||||
mv PrismLauncher-macOS-Legacy*/PrismLauncher.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz
|
||||
@ -85,8 +87,8 @@ jobs:
|
||||
draft: true
|
||||
prerelease: false
|
||||
files: |
|
||||
PrismLauncher-Linux-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Linux-Qt5-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Linux-Qt5-Portable-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Linux-x86_64.AppImage
|
||||
PrismLauncher-Linux-x86_64.AppImage.zsync
|
||||
PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
|
||||
|
@ -188,8 +188,11 @@ set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_M
|
||||
# Build platform.
|
||||
set(Launcher_BUILD_PLATFORM "unknown" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.")
|
||||
|
||||
# Channel list URL
|
||||
set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.")
|
||||
# Github repo URL with releases for updater
|
||||
set(Launcher_UPDATER_GITHUB_REPO "https://github.com/PrismLauncher/PrismLauncher" CACHE STRING "Base github URL for the updater.")
|
||||
|
||||
# Name to help updater identify valid artifacts
|
||||
set(Launcher_BUILD_ARTIFACT "" CACHE STRING "Artifact name to help the updater identify valid artifacts.")
|
||||
|
||||
# The metadata server
|
||||
set(Launcher_META_URL "https://meta.prismlauncher.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.")
|
||||
@ -245,6 +248,11 @@ set(Launcher_MSA_CLIENT_ID "c36a9fb6-4f2a-41ff-90bd-ae7cc92031eb" CACHE STRING "
|
||||
# This key was issued specifically for Prism Launcher
|
||||
set(Launcher_CURSEFORGE_API_KEY "$2a$10$wuAJuNZuted3NORVmpgUC.m8sI.pv1tOPKZyBgLFGjxFp/br0lZCC" CACHE STRING "API key for the CurseForge platform")
|
||||
|
||||
set(Launcher_COMPILER_NAME ${CMAKE_CXX_COMPILER_ID})
|
||||
set(Launcher_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION})
|
||||
set(Launcher_COMPILER_TARGET_SYSTEM ${CMAKE_SYSTEM_NAME})
|
||||
set(Launcher_COMPILER_TARGET_SYSTEM_VERSION ${CMAKE_SYSTEM_VERSION})
|
||||
set(Launcher_COMPILER_TARGET_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR})
|
||||
|
||||
#### Check the current Git commit and branch
|
||||
include(GetGitRevisionDescription)
|
||||
@ -339,6 +347,11 @@ add_subdirectory(program_info)
|
||||
####################################### Install layout #######################################
|
||||
|
||||
set(Launcher_ENABLE_UPDATER NO)
|
||||
set(Launcher_BUILD_UPDATER NO)
|
||||
|
||||
if (NOT APPLE AND (NOT Launcher_UPDATER_GITHUB_REPO STREQUAL "" AND NOT Launcher_BUILD_ARTIFACT STREQUAL ""))
|
||||
set(Launcher_BUILD_UPDATER YES)
|
||||
endif()
|
||||
|
||||
if(NOT (UNIX AND APPLE))
|
||||
# Install "portable.txt" if selected component is "portable"
|
||||
|
13
README.md
@ -18,11 +18,18 @@
|
||||
</a>
|
||||
|
||||
- All downloads and instructions for Prism Launcher can be found on our [Website](https://prismlauncher.org/download).
|
||||
- Last build status can be found in the [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions).
|
||||
- Last build status can be found in the [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions) tab (this also includes the pull requests status).
|
||||
|
||||
### Development Builds
|
||||
|
||||
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.
|
||||
Please understand that these builds are not intended for most users. There may be bugs, and other instabilities. You have been warned.
|
||||
|
||||
There are development builds available through:
|
||||
|
||||
- [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions) (includes builds from pull requests opened by contribuitors)
|
||||
- [nightly.link](https://nightly.link/PrismLauncher/PrismLauncher/workflows/trigger_builds/develop) (this will always point only to the latest version of develop)
|
||||
|
||||
These have debug information in the binaries, so their file sizes are relatively larger.
|
||||
|
||||
Prebuilt Development builds are provided for **Linux**, **Windows** and **macOS**.
|
||||
|
||||
@ -30,7 +37,7 @@ For **Arch**, **Debian**, **Fedora**, **OpenSUSE (Tumbleweed)** and **Gentoo**,
|
||||
|
||||
[](https://aur.archlinux.org/packages/prismlauncher-git) [](https://aur.archlinux.org/packages/prismlauncher-qt5-git) [](https://mpr.makedeb.org/packages/prismlauncher-git)<br />[](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [](https://build.opensuse.org/project/show/home:getchoo) [](https://packages.gentoo.org/packages/games-action/prismlauncher)
|
||||
|
||||
These packages are also availiable to all the distributions based on the ones mentioned above.
|
||||
These packages are also available to all the distributions based on the ones mentioned above.
|
||||
|
||||
## Community & Support
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <qstringliteral.h>
|
||||
#include "BuildConfig.h"
|
||||
#include <QObject>
|
||||
|
||||
@ -59,8 +60,16 @@ Config::Config()
|
||||
VERSION_MINOR = @Launcher_VERSION_MINOR@;
|
||||
|
||||
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
|
||||
BUILD_ARTIFACT = "@Launcher_BUILD_ARTIFACT@";
|
||||
BUILD_DATE = "@Launcher_BUILD_TIMESTAMP@";
|
||||
UPDATER_BASE = "@Launcher_UPDATER_BASE@";
|
||||
UPDATER_GITHUB_REPO = "@Launcher_UPDATER_GITHUB_REPO@";
|
||||
|
||||
COMPILER_NAME = "@Launcher_COMPILER_NAME@";
|
||||
COMPILER_VERSION = "@Launcher_COMPILER_VERSION@";
|
||||
|
||||
COMPILER_TARGET_SYSTEM = "@Launcher_COMPILER_TARGET_SYSTEM@";
|
||||
COMPILER_TARGET_SYSTEM_VERSION = "@Launcher_COMPILER_TARGET_SYSTEM_VERSION@";
|
||||
COMPILER_TARGET_SYSTEM_PROCESSOR = "@Launcher_COMPILER_TARGET_PROCESSOR@";
|
||||
|
||||
MAC_SPARKLE_PUB_KEY = "@MACOSX_SPARKLE_UPDATE_PUBLIC_KEY@";
|
||||
MAC_SPARKLE_APPCAST_URL = "@MACOSX_SPARKLE_UPDATE_FEED_URL@";
|
||||
@ -68,6 +77,8 @@ Config::Config()
|
||||
if (!MAC_SPARKLE_PUB_KEY.isEmpty() && !MAC_SPARKLE_APPCAST_URL.isEmpty())
|
||||
{
|
||||
UPDATER_ENABLED = true;
|
||||
} else if(!UPDATER_GITHUB_REPO.isEmpty() && !BUILD_ARTIFACT.isEmpty()) {
|
||||
UPDATER_ENABLED = true;
|
||||
}
|
||||
|
||||
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
|
||||
@ -89,9 +100,6 @@ Config::Config()
|
||||
{
|
||||
VERSION_CHANNEL = GIT_REFSPEC;
|
||||
VERSION_CHANNEL.remove("refs/heads/");
|
||||
if(!UPDATER_BASE.isEmpty() && !BUILD_PLATFORM.isEmpty()) {
|
||||
UPDATER_ENABLED = true;
|
||||
}
|
||||
}
|
||||
else if (!GIT_COMMIT.isEmpty())
|
||||
{
|
||||
@ -136,3 +144,16 @@ QString Config::printableVersionString() const
|
||||
}
|
||||
return vstr;
|
||||
}
|
||||
|
||||
QString Config::compilerID() const
|
||||
{
|
||||
if (COMPILER_VERSION.isEmpty())
|
||||
return COMPILER_NAME;
|
||||
return QStringLiteral("%1 - %2").arg(COMPILER_NAME).arg(COMPILER_VERSION);
|
||||
}
|
||||
|
||||
QString Config::systemID() const
|
||||
{
|
||||
return QStringLiteral("%1 %2 %3").arg(COMPILER_TARGET_SYSTEM, COMPILER_TARGET_SYSTEM_VERSION, COMPILER_TARGET_SYSTEM_PROCESSOR);
|
||||
}
|
||||
|
||||
|
@ -71,11 +71,29 @@ class Config {
|
||||
/// A short string identifying this build's platform or distribution.
|
||||
QString BUILD_PLATFORM;
|
||||
|
||||
/// A short string identifying this build's valid artifacts int he updater. For example, "lin64" or "win32".
|
||||
QString BUILD_ARTIFACT;
|
||||
|
||||
/// A string containing the build timestamp
|
||||
QString BUILD_DATE;
|
||||
|
||||
/// A string identifying the compiler use to build
|
||||
QString COMPILER_NAME;
|
||||
|
||||
/// A string identifying the compiler version used to build
|
||||
QString COMPILER_VERSION;
|
||||
|
||||
/// A string identifying the compiler target system os
|
||||
QString COMPILER_TARGET_SYSTEM;
|
||||
|
||||
/// A String identifying the compiler target system version
|
||||
QString COMPILER_TARGET_SYSTEM_VERSION;
|
||||
|
||||
/// A String identifying the compiler target processor
|
||||
QString COMPILER_TARGET_SYSTEM_PROCESSOR;
|
||||
|
||||
/// URL for the updater's channel
|
||||
QString UPDATER_BASE;
|
||||
QString UPDATER_GITHUB_REPO;
|
||||
|
||||
/// The public key used to sign releases for the Sparkle updater appcast
|
||||
QString MAC_SPARKLE_PUB_KEY;
|
||||
@ -175,6 +193,18 @@ class Config {
|
||||
* \return The version number in string format (major.minor.revision.build).
|
||||
*/
|
||||
QString printableVersionString() const;
|
||||
|
||||
/**
|
||||
* \brief Compiler ID String
|
||||
* \return a string of the form "Name - Version" of just "Name" if the version is empty
|
||||
*/
|
||||
QString compilerID() const;
|
||||
|
||||
/**
|
||||
* \brief System ID String
|
||||
* \return a string of the form "OS Verison Processor"
|
||||
*/
|
||||
QString systemID() const;
|
||||
};
|
||||
|
||||
extern const Config BuildConfig;
|
||||
|
30
flake.lock
generated
@ -21,11 +21,11 @@
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1696343447,
|
||||
"narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=",
|
||||
"lastModified": 1698882062,
|
||||
"narHash": "sha256-HkhafUayIqxXyHH1X8d9RDl1M2CkFgZLjKD3MzabiEo=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4",
|
||||
"rev": "8c9fa2545007b49a5db5f650ae91f227672c3877",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -76,11 +76,11 @@
|
||||
"libnbtplusplus": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1690036783,
|
||||
"narHash": "sha256-A5kTgICnx+Qdq3Fir/bKTfdTt/T1NQP2SC+nhN1ENug=",
|
||||
"lastModified": 1699286814,
|
||||
"narHash": "sha256-yy0q+bky80LtK1GWzz7qpM+aAGrOqLuewbid8WT1ilk=",
|
||||
"owner": "PrismLauncher",
|
||||
"repo": "libnbtplusplus",
|
||||
"rev": "a5e8fd52b8bf4ab5d5bcc042b2a247867589985f",
|
||||
"rev": "23b955121b8217c1c348a9ed2483167a6f3ff4ad",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -106,11 +106,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1697009197,
|
||||
"narHash": "sha256-viVRhBTFT8fPJTb1N3brQIpFZnttmwo3JVKNuWRVc3s=",
|
||||
"lastModified": 1699343069,
|
||||
"narHash": "sha256-s7BBhyLA6MI6FuJgs4F/SgpntHBzz40/qV0xLPW6A1Q=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "01441e14af5e29c9d27ace398e6dd0b293e25a54",
|
||||
"rev": "ec750fd01963ab6b20ee1f0cb488754e8036d89d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -123,11 +123,11 @@
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"lastModified": 1696019113,
|
||||
"narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=",
|
||||
"lastModified": 1698611440,
|
||||
"narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a",
|
||||
"rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -153,11 +153,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1696846637,
|
||||
"narHash": "sha256-0hv4kbXxci2+pxhuXlVgftj/Jq79VSmtAyvfabCCtYk=",
|
||||
"lastModified": 1699271226,
|
||||
"narHash": "sha256-8Jt1KW3xTjolD6c6OjJm9USx/jmL+VVmbooADCkdDfU=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "42e1b6095ef80a51f79595d9951eb38e91c4e6ca",
|
||||
"rev": "ea758da1a6dcde6dc36db348ed690d09b9864128",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include "ui/pages/global/APIPage.h"
|
||||
#include "ui/pages/global/AccountListPage.h"
|
||||
#include "ui/pages/global/CustomCommandsPage.h"
|
||||
#include "ui/pages/global/EnvironmentVariablesPage.h"
|
||||
#include "ui/pages/global/ExternalToolsPage.h"
|
||||
#include "ui/pages/global/JavaPage.h"
|
||||
#include "ui/pages/global/LanguagePage.h"
|
||||
@ -122,6 +123,7 @@
|
||||
#include <FileSystem.h>
|
||||
#include <LocalPeer.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys.h>
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
@ -130,9 +132,13 @@
|
||||
#include "gamemode_client.h"
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MAC) && defined(SPARKLE_ENABLED)
|
||||
#if defined(Q_OS_MAC)
|
||||
#if defined(SPARKLE_ENABLED)
|
||||
#include "updater/MacSparkleUpdater.h"
|
||||
#endif
|
||||
#else
|
||||
#include "updater/PrismExternalUpdater.h"
|
||||
#endif
|
||||
|
||||
#if defined Q_OS_WIN32
|
||||
#include "WindowsConsole.h"
|
||||
@ -164,6 +170,34 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QSt
|
||||
|
||||
} // namespace
|
||||
|
||||
std::tuple<QDateTime, QString, QString, QString, QString> read_lock_File(const QString& path)
|
||||
{
|
||||
auto contents = QString(FS::read(path));
|
||||
auto lines = contents.split('\n');
|
||||
|
||||
QDateTime timestamp;
|
||||
QString from, to, target, data_path;
|
||||
for (auto line : lines) {
|
||||
auto index = line.indexOf("=");
|
||||
if (index < 0)
|
||||
continue;
|
||||
auto left = line.left(index);
|
||||
auto right = line.mid(index + 1);
|
||||
if (left.toLower() == "timestamp") {
|
||||
timestamp = QDateTime::fromString(right, Qt::ISODate);
|
||||
} else if (left.toLower() == "from") {
|
||||
from = right;
|
||||
} else if (left.toLower() == "to") {
|
||||
to = right;
|
||||
} else if (left.toLower() == "target") {
|
||||
target = right;
|
||||
} else if (left.toLower() == "data_path") {
|
||||
data_path = right;
|
||||
}
|
||||
}
|
||||
return std::make_tuple(timestamp, from, to, target, data_path);
|
||||
}
|
||||
|
||||
Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
{
|
||||
#if defined Q_OS_WIN32
|
||||
@ -296,6 +330,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
.arg(dataPath));
|
||||
return;
|
||||
}
|
||||
m_dataPath = dataPath;
|
||||
|
||||
/*
|
||||
* Establish the mechanism for communication with an already running PrismLauncher that uses the same data path.
|
||||
@ -450,11 +485,16 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
}
|
||||
|
||||
{
|
||||
qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT;
|
||||
qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << ", (c) 2022-2023 "
|
||||
<< qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
|
||||
qDebug() << "Version : " << BuildConfig.printableVersionString();
|
||||
qDebug() << "Platform : " << BuildConfig.BUILD_PLATFORM;
|
||||
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
||||
qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
|
||||
qDebug() << "Compiled for : " << BuildConfig.systemID();
|
||||
qDebug() << "Compiled by : " << BuildConfig.compilerID();
|
||||
qDebug() << "Build Artifact : " << BuildConfig.BUILD_ARTIFACT;
|
||||
qDebug() << "Updates Enabled : " << (updaterEnabled() ? "Yes" : "No");
|
||||
if (adjustedBy.size()) {
|
||||
qDebug() << "Work dir before adjustment : " << origcwdPath;
|
||||
qDebug() << "Work dir after adjustment : " << QDir::currentPath();
|
||||
@ -582,6 +622,9 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
m_settings->registerSetting("IgnoreJavaCompatibility", false);
|
||||
m_settings->registerSetting("IgnoreJavaWizard", false);
|
||||
|
||||
// Legacy settings
|
||||
m_settings->registerSetting("OnlineFixes", false);
|
||||
|
||||
// Native library workarounds
|
||||
m_settings->registerSetting("UseNativeOpenAL", false);
|
||||
m_settings->registerSetting("CustomOpenALPath", "");
|
||||
@ -601,6 +644,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
|
||||
// Minecraft mods
|
||||
m_settings->registerSetting("ModMetadataDisabled", false);
|
||||
m_settings->registerSetting("ModDependenciesDisabled", false);
|
||||
|
||||
// Minecraft offline player name
|
||||
m_settings->registerSetting("LastOfflinePlayerName", "");
|
||||
@ -677,6 +721,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
m_settings->registerSetting("CloseAfterLaunch", false);
|
||||
m_settings->registerSetting("QuitAfterGameStop", false);
|
||||
|
||||
m_settings->registerSetting("Env", QVariant(QMap<QString, QVariant>()));
|
||||
|
||||
// Custom Microsoft Authentication Client ID
|
||||
m_settings->registerSetting("MSAClientIDOverride", "");
|
||||
|
||||
@ -702,6 +748,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
m_globalSettingsProvider->addPage<JavaPage>();
|
||||
m_globalSettingsProvider->addPage<LanguagePage>();
|
||||
m_globalSettingsProvider->addPage<CustomCommandsPage>();
|
||||
m_globalSettingsProvider->addPage<EnvironmentVariablesPage>();
|
||||
m_globalSettingsProvider->addPage<ProxyPage>();
|
||||
m_globalSettingsProvider->addPage<ExternalToolsPage>();
|
||||
m_globalSettingsProvider->addPage<AccountListPage>();
|
||||
@ -738,15 +785,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
qDebug() << "<> Translations loaded.";
|
||||
}
|
||||
|
||||
// initialize the updater
|
||||
if (BuildConfig.UPDATER_ENABLED) {
|
||||
qDebug() << "Initializing updater";
|
||||
#if defined(Q_OS_MAC) && defined(SPARKLE_ENABLED)
|
||||
m_updater.reset(new MacSparkleUpdater());
|
||||
#endif
|
||||
qDebug() << "<> Updater started.";
|
||||
}
|
||||
|
||||
// Instance icons
|
||||
{
|
||||
auto setting = APPLICATION->settings()->getSetting("IconsDir");
|
||||
@ -849,6 +887,107 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
|
||||
detectLibraries();
|
||||
|
||||
// check update locks
|
||||
{
|
||||
auto update_log_path = FS::PathCombine(m_dataPath, "logs", "prism_launcher_update.log");
|
||||
|
||||
auto update_lock = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.lock"));
|
||||
if (update_lock.exists()) {
|
||||
auto [timestamp, from, to, target, data_path] = read_lock_File(update_lock.absoluteFilePath());
|
||||
auto infoMsg = tr("This installation has a update lock file present at: %1\n"
|
||||
"\n"
|
||||
"Timestamp: %2\n"
|
||||
"Updating from version %3 to %4\n"
|
||||
"Target install path: %5\n"
|
||||
"Data Path: %6"
|
||||
"\n"
|
||||
"This likely means that a update attempt failed. Please ensure your installation is in working order before "
|
||||
"proceeding.\n"
|
||||
"Check the Prism Launcher updater log at: \n"
|
||||
"%7\n"
|
||||
"for details on the last update attempt.\n"
|
||||
"\n"
|
||||
"To delete this lock and proceed select \"Ignore\" below.")
|
||||
.arg(update_lock.absoluteFilePath())
|
||||
.arg(timestamp.toString(Qt::ISODate), from, to, target, data_path)
|
||||
.arg(update_log_path);
|
||||
auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update In Progress"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort);
|
||||
msgBox.setDefaultButton(QMessageBox::Abort);
|
||||
msgBox.setModal(true);
|
||||
msgBox.setDetailedText(FS::read(update_log_path));
|
||||
msgBox.setMinimumWidth(460);
|
||||
msgBox.adjustSize();
|
||||
auto res = msgBox.exec();
|
||||
switch (res) {
|
||||
case QMessageBox::Ignore: {
|
||||
FS::deletePath(update_lock.absoluteFilePath());
|
||||
break;
|
||||
}
|
||||
case QMessageBox::Abort:
|
||||
[[fallthrough]];
|
||||
default: {
|
||||
qDebug() << "Exiting because update lockfile is present";
|
||||
QMetaObject::invokeMethod(
|
||||
this, []() { exit(1); }, Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto update_fail_marker = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.fail"));
|
||||
if (update_fail_marker.exists()) {
|
||||
auto infoMsg = tr("An update attempt failed\n"
|
||||
"\n"
|
||||
"Please ensure your installation is in working order before "
|
||||
"proceeding.\n"
|
||||
"Check the Prism Launcher updater log at: \n"
|
||||
"%1\n"
|
||||
"for details on the last update attempt.")
|
||||
.arg(update_log_path);
|
||||
auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Failed"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort);
|
||||
msgBox.setDefaultButton(QMessageBox::Abort);
|
||||
msgBox.setModal(true);
|
||||
msgBox.setDetailedText(FS::read(update_log_path));
|
||||
msgBox.setMinimumWidth(460);
|
||||
msgBox.adjustSize();
|
||||
auto res = msgBox.exec();
|
||||
switch (res) {
|
||||
case QMessageBox::Ignore: {
|
||||
FS::deletePath(update_fail_marker.absoluteFilePath());
|
||||
break;
|
||||
}
|
||||
case QMessageBox::Abort:
|
||||
[[fallthrough]];
|
||||
default: {
|
||||
qDebug() << "Exiting because update lockfile is present";
|
||||
QMetaObject::invokeMethod(
|
||||
this, []() { exit(1); }, Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto update_success_marker = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.success"));
|
||||
if (update_success_marker.exists()) {
|
||||
auto infoMsg = tr("Update succeeded\n"
|
||||
"\n"
|
||||
"You are now running %1 .\n"
|
||||
"Check the Prism Launcher updater log at: \n"
|
||||
"%1\n"
|
||||
"for details.")
|
||||
.arg(BuildConfig.printableVersionString())
|
||||
.arg(update_log_path);
|
||||
auto msgBox = new QMessageBox(QMessageBox::Information, tr("Update Succeeded"), infoMsg, QMessageBox::Ok);
|
||||
msgBox->setDefaultButton(QMessageBox::Ok);
|
||||
msgBox->setDetailedText(FS::read(update_log_path));
|
||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||
msgBox->setMinimumWidth(460);
|
||||
msgBox->adjustSize();
|
||||
msgBox->open();
|
||||
FS::deletePath(update_success_marker.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
if (createSetupWizard()) {
|
||||
return;
|
||||
}
|
||||
@ -917,6 +1056,26 @@ bool Application::createSetupWizard()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Application::updaterEnabled()
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
return BuildConfig.UPDATER_ENABLED;
|
||||
#else
|
||||
return BuildConfig.UPDATER_ENABLED && QFileInfo(FS::PathCombine(m_rootPath, updaterBinaryName())).isFile();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString Application::updaterBinaryName()
|
||||
{
|
||||
auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME);
|
||||
#if defined Q_OS_WIN32
|
||||
exe_name.append(".exe");
|
||||
#else
|
||||
exe_name.prepend("bin/");
|
||||
#endif
|
||||
return exe_name;
|
||||
}
|
||||
|
||||
bool Application::event(QEvent* event)
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
@ -985,6 +1144,20 @@ void Application::performMainStartupAction()
|
||||
showMainWindow(false);
|
||||
qDebug() << "<> Main window shown.";
|
||||
}
|
||||
|
||||
// initialize the updater
|
||||
if (updaterEnabled()) {
|
||||
qDebug() << "Initializing updater";
|
||||
#ifdef Q_OS_MAC
|
||||
#if defined(SPARKLE_ENABLED)
|
||||
m_updater.reset(new MacSparkleUpdater());
|
||||
#endif
|
||||
#else
|
||||
m_updater.reset(new PrismExternalUpdater(m_mainWindow, m_rootPath, m_dataPath));
|
||||
#endif
|
||||
qDebug() << "<> Updater started.";
|
||||
}
|
||||
|
||||
if (!m_urlsToImport.isEmpty()) {
|
||||
qDebug() << "<> Importing from url:" << m_urlsToImport;
|
||||
m_mainWindow->processURLs(m_urlsToImport);
|
||||
|
@ -159,6 +159,9 @@ class Application : public QApplication {
|
||||
/// this is the root of the 'installation'. Used for automatic updates
|
||||
const QString& root() { return m_rootPath; }
|
||||
|
||||
/// the data path the application is using
|
||||
const QString& dataRoot() { return m_dataPath; }
|
||||
|
||||
bool isPortable() { return m_portable; }
|
||||
|
||||
const Capabilities capabilities() { return m_capabilities; }
|
||||
@ -179,6 +182,9 @@ class Application : public QApplication {
|
||||
|
||||
int suitableMaxMem();
|
||||
|
||||
bool updaterEnabled();
|
||||
QString updaterBinaryName();
|
||||
|
||||
QUrl normalizeImportUrl(QString const& url);
|
||||
|
||||
signals:
|
||||
@ -244,6 +250,7 @@ class Application : public QApplication {
|
||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
|
||||
|
||||
QString m_rootPath;
|
||||
QString m_dataPath;
|
||||
Status m_status = Application::StartingUp;
|
||||
Capabilities m_capabilities;
|
||||
bool m_portable = false;
|
||||
|
@ -390,7 +390,7 @@ QString BaseInstance::name() const
|
||||
|
||||
QString BaseInstance::windowTitle() const
|
||||
{
|
||||
return BuildConfig.LAUNCHER_DISPLAYNAME + ": " + name().replace(QRegularExpression("\\s+"), " ");
|
||||
return BuildConfig.LAUNCHER_DISPLAYNAME + ": " + name();
|
||||
}
|
||||
|
||||
// FIXME: why is this here? move it to MinecraftInstance!!!
|
||||
|
@ -64,7 +64,7 @@ class LaunchTask;
|
||||
class BaseInstance;
|
||||
|
||||
// pointer for lazy people
|
||||
typedef std::shared_ptr<BaseInstance> InstancePtr;
|
||||
using InstancePtr = std::shared_ptr<BaseInstance>;
|
||||
|
||||
/*!
|
||||
* \brief Base class for instances.
|
||||
|
@ -51,7 +51,7 @@ class BaseVersionList : public QAbstractListModel {
|
||||
ArchitectureRole,
|
||||
SortRole
|
||||
};
|
||||
typedef QList<int> RoleList;
|
||||
using RoleList = QList<int>;
|
||||
|
||||
explicit BaseVersionList(QObject* parent = 0);
|
||||
|
||||
|
@ -139,6 +139,7 @@ set(NET_SOURCES
|
||||
net/HeaderProxy.h
|
||||
net/RawHeaderProxy.h
|
||||
net/ApiHeaderProxy.h
|
||||
net/StaticHeaderProxy.h
|
||||
net/ApiDownload.h
|
||||
net/ApiDownload.cpp
|
||||
net/ApiUpload.cpp
|
||||
@ -181,6 +182,11 @@ set(MAC_UPDATE_SOURCES
|
||||
updater/MacSparkleUpdater.mm
|
||||
)
|
||||
|
||||
set(PRISM_UPDATE_SOURCES
|
||||
updater/PrismExternalUpdater.h
|
||||
updater/PrismExternalUpdater.cpp
|
||||
)
|
||||
|
||||
# Backend for the news bar... there's usually no news.
|
||||
set(NEWS_SOURCES
|
||||
# News System
|
||||
@ -579,6 +585,63 @@ set(LINKEXE_SOURCES
|
||||
DesktopServices.cpp
|
||||
)
|
||||
|
||||
set(PRISMUPDATER_SOURCES
|
||||
updater/prismupdater/PrismUpdater.h
|
||||
updater/prismupdater/PrismUpdater.cpp
|
||||
updater/prismupdater/UpdaterDialogs.h
|
||||
updater/prismupdater/UpdaterDialogs.cpp
|
||||
updater/prismupdater/GitHubRelease.h
|
||||
updater/prismupdater/GitHubRelease.cpp
|
||||
|
||||
Json.h
|
||||
Json.cpp
|
||||
FileSystem.h
|
||||
FileSystem.cpp
|
||||
StringUtils.h
|
||||
StringUtils.cpp
|
||||
DesktopServices.h
|
||||
DesktopServices.cpp
|
||||
Version.h
|
||||
Version.cpp
|
||||
Markdown.h
|
||||
Markdown.cpp
|
||||
|
||||
# Zip
|
||||
MMCZip.h
|
||||
MMCZip.cpp
|
||||
|
||||
# Time
|
||||
MMCTime.h
|
||||
MMCTime.cpp
|
||||
|
||||
net/ByteArraySink.h
|
||||
net/ChecksumValidator.h
|
||||
net/Download.cpp
|
||||
net/Download.h
|
||||
net/FileSink.cpp
|
||||
net/FileSink.h
|
||||
net/HttpMetaCache.cpp
|
||||
net/HttpMetaCache.h
|
||||
net/Logging.h
|
||||
net/Logging.cpp
|
||||
net/NetAction.h
|
||||
net/NetRequest.cpp
|
||||
net/NetRequest.h
|
||||
net/NetJob.cpp
|
||||
net/NetJob.h
|
||||
net/NetUtils.h
|
||||
net/Sink.h
|
||||
net/Validator.h
|
||||
net/HeaderProxy.h
|
||||
net/RawHeaderProxy.h
|
||||
|
||||
ui/dialogs/ProgressDialog.cpp
|
||||
ui/dialogs/ProgressDialog.h
|
||||
ui/widgets/SubTaskProgressBar.h
|
||||
ui/widgets/SubTaskProgressBar.cpp
|
||||
|
||||
)
|
||||
|
||||
######## Logging categories ########
|
||||
|
||||
ecm_qt_declare_logging_category(CORE_SOURCES
|
||||
@ -675,6 +738,8 @@ set(LOGIC_SOURCES
|
||||
|
||||
if(APPLE AND Launcher_ENABLE_UPDATER)
|
||||
set (LOGIC_SOURCES ${LOGIC_SOURCES} ${MAC_UPDATE_SOURCES})
|
||||
else()
|
||||
set (LOGIC_SOURCES ${LOGIC_SOURCES} ${PRISM_UPDATE_SOURCES})
|
||||
endif()
|
||||
|
||||
SET(LAUNCHER_SOURCES
|
||||
@ -824,6 +889,8 @@ SET(LAUNCHER_SOURCES
|
||||
ui/pages/global/AccountListPage.h
|
||||
ui/pages/global/CustomCommandsPage.cpp
|
||||
ui/pages/global/CustomCommandsPage.h
|
||||
ui/pages/global/EnvironmentVariablesPage.cpp
|
||||
ui/pages/global/EnvironmentVariablesPage.h
|
||||
ui/pages/global/ExternalToolsPage.cpp
|
||||
ui/pages/global/ExternalToolsPage.h
|
||||
ui/pages/global/JavaPage.cpp
|
||||
@ -975,6 +1042,8 @@ SET(LAUNCHER_SOURCES
|
||||
ui/widgets/Common.h
|
||||
ui/widgets/CustomCommands.cpp
|
||||
ui/widgets/CustomCommands.h
|
||||
ui/widgets/EnvironmentVariables.cpp
|
||||
ui/widgets/EnvironmentVariables.h
|
||||
ui/widgets/DropLabel.cpp
|
||||
ui/widgets/DropLabel.h
|
||||
ui/widgets/FocusLineEdit.cpp
|
||||
@ -1033,6 +1102,15 @@ SET(LAUNCHER_SOURCES
|
||||
ui/instanceview/VisualGroup.h
|
||||
)
|
||||
|
||||
if (NOT Apple)
|
||||
set(LAUNCHER_SOURCES
|
||||
${LAUNCHER_SOURCES}
|
||||
|
||||
ui/dialogs/UpdateAvailableDialog.h
|
||||
ui/dialogs/UpdateAvailableDialog.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(LAUNCHER_SOURCES
|
||||
WindowsConsole.cpp
|
||||
@ -1076,6 +1154,7 @@ qt_wrap_ui(LAUNCHER_UI
|
||||
ui/pages/modplatform/technic/TechnicPage.ui
|
||||
ui/widgets/InstanceCardWidget.ui
|
||||
ui/widgets/CustomCommands.ui
|
||||
ui/widgets/EnvironmentVariables.ui
|
||||
ui/widgets/InfoFrame.ui
|
||||
ui/widgets/ModFilterWidget.ui
|
||||
ui/widgets/SubTaskProgressBar.ui
|
||||
@ -1103,6 +1182,14 @@ qt_wrap_ui(LAUNCHER_UI
|
||||
ui/dialogs/ChooseProviderDialog.ui
|
||||
)
|
||||
|
||||
qt_wrap_ui(PRISM_UPDATE_UI
|
||||
ui/dialogs/UpdateAvailableDialog.ui
|
||||
)
|
||||
|
||||
if (NOT Apple)
|
||||
set (LAUNCHER_UI ${LAUNCHER_UI} ${PRISM_UPDATE_UI})
|
||||
endif()
|
||||
|
||||
qt_add_resources(LAUNCHER_RESOURCES
|
||||
resources/backgrounds/backgrounds.qrc
|
||||
resources/multimc/multimc.qrc
|
||||
@ -1119,6 +1206,12 @@ qt_add_resources(LAUNCHER_RESOURCES
|
||||
../${Launcher_Branding_LogoQRC}
|
||||
)
|
||||
|
||||
qt_wrap_ui(PRISMUPDATER_UI
|
||||
updater/prismupdater/SelectReleaseDialog.ui
|
||||
ui/widgets/SubTaskProgressBar.ui
|
||||
ui/dialogs/ProgressDialog.ui
|
||||
)
|
||||
|
||||
######## Windows resource files ########
|
||||
if(WIN32)
|
||||
set(LAUNCHER_RCS ${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_WindowsRC})
|
||||
@ -1137,6 +1230,7 @@ set_project_warnings(Launcher_logic
|
||||
"${Launcher_GCC_WARNINGS}")
|
||||
target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION)
|
||||
target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION)
|
||||
target_link_libraries(Launcher_logic
|
||||
systeminfo
|
||||
Launcher_murmur2
|
||||
@ -1218,7 +1312,45 @@ install(TARGETS ${Launcher_Name}
|
||||
FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
if(Launcher_BUILD_UPDATER)
|
||||
# Updater
|
||||
add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI})
|
||||
target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(prism_updater_logic
|
||||
QuaZip::QuaZip
|
||||
${ZLIB_LIBRARIES}
|
||||
systeminfo
|
||||
BuildConfig
|
||||
ghcFilesystem::ghc_filesystem
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
${Launcher_QT_LIBS}
|
||||
cmark::cmark
|
||||
Katabasis
|
||||
)
|
||||
|
||||
add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp)
|
||||
target_sources("${Launcher_Name}_updater" PRIVATE updater/prismupdater/updater.exe.manifest)
|
||||
target_link_libraries("${Launcher_Name}_updater" prism_updater_logic)
|
||||
|
||||
if(DEFINED Launcher_APP_BINARY_NAME)
|
||||
set_target_properties("${Launcher_Name}_updater" PROPERTIES OUTPUT_NAME "${Launcher_APP_BINARY_NAME}_updater")
|
||||
endif()
|
||||
if(DEFINED Launcher_BINARY_RPATH)
|
||||
SET_TARGET_PROPERTIES("${Launcher_Name}_updater" PROPERTIES INSTALL_RPATH "${Launcher_BINARY_RPATH}")
|
||||
endif()
|
||||
|
||||
install(TARGETS "${Launcher_Name}_updater"
|
||||
BUNDLE DESTINATION "." COMPONENT Runtime
|
||||
LIBRARY DESTINATION ${LIBRARY_DEST_DIR} COMPONENT Runtime
|
||||
RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime
|
||||
FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER))
|
||||
# File link
|
||||
add_library(filelink_logic STATIC ${LINKEXE_SOURCES})
|
||||
set_project_warnings(filelink_logic
|
||||
"${Launcher_MSVC_WARNINGS}"
|
||||
@ -1237,7 +1369,7 @@ if(WIN32)
|
||||
${Launcher_QT_LIBS}
|
||||
)
|
||||
|
||||
add_executable("${Launcher_Name}_filelink" WIN32 filelink/main.cpp)
|
||||
add_executable("${Launcher_Name}_filelink" WIN32 filelink/filelink_main.cpp)
|
||||
|
||||
target_sources("${Launcher_Name}_filelink" PRIVATE filelink/filelink.exe.manifest)
|
||||
|
||||
|
@ -123,26 +123,35 @@ namespace fs = ghc::filesystem;
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
|
||||
typedef struct _DUPLICATE_EXTENTS_DATA {
|
||||
struct _DUPLICATE_EXTENTS_DATA {
|
||||
HANDLE FileHandle;
|
||||
LARGE_INTEGER SourceFileOffset;
|
||||
LARGE_INTEGER TargetFileOffset;
|
||||
LARGE_INTEGER ByteCount;
|
||||
} DUPLICATE_EXTENTS_DATA, *PDUPLICATE_EXTENTS_DATA;
|
||||
};
|
||||
|
||||
typedef struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER {
|
||||
using DUPLICATE_EXTENTS_DATA = _DUPLICATE_EXTENTS_DATA;
|
||||
using PDUPLICATE_EXTENTS_DATA = _DUPLICATE_EXTENTS_DATA*;
|
||||
|
||||
struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER {
|
||||
WORD ChecksumAlgorithm; // Checksum algorithm. e.g. CHECKSUM_TYPE_UNCHANGED, CHECKSUM_TYPE_NONE, CHECKSUM_TYPE_CRC32
|
||||
WORD Reserved; // Must be 0
|
||||
DWORD Flags; // FSCTL_INTEGRITY_FLAG_xxx
|
||||
DWORD ChecksumChunkSizeInBytes;
|
||||
DWORD ClusterSizeInBytes;
|
||||
} FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, *PFSCTL_GET_INTEGRITY_INFORMATION_BUFFER;
|
||||
};
|
||||
|
||||
typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER {
|
||||
using FSCTL_GET_INTEGRITY_INFORMATION_BUFFER = _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER;
|
||||
using PFSCTL_GET_INTEGRITY_INFORMATION_BUFFER = _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER*;
|
||||
|
||||
struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER {
|
||||
WORD ChecksumAlgorithm; // Checksum algorithm. e.g. CHECKSUM_TYPE_UNCHANGED, CHECKSUM_TYPE_NONE, CHECKSUM_TYPE_CRC32
|
||||
WORD Reserved; // Must be 0
|
||||
DWORD Flags; // FSCTL_INTEGRITY_FLAG_xxx
|
||||
} FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, *PFSCTL_SET_INTEGRITY_INFORMATION_BUFFER;
|
||||
};
|
||||
|
||||
using FSCTL_SET_INTEGRITY_INFORMATION_BUFFER = _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER;
|
||||
using PFSCTL_SET_INTEGRITY_INFORMATION_BUFFER = _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER*;
|
||||
|
||||
#endif
|
||||
|
||||
@ -194,6 +203,40 @@ void write(const QString& filename, const QByteArray& data)
|
||||
}
|
||||
}
|
||||
|
||||
void appendSafe(const QString& filename, const QByteArray& data)
|
||||
{
|
||||
ensureExists(QFileInfo(filename).dir());
|
||||
QByteArray buffer;
|
||||
try {
|
||||
buffer = read(filename);
|
||||
} catch (FileSystemException&) {
|
||||
buffer = QByteArray();
|
||||
}
|
||||
buffer.append(data);
|
||||
QSaveFile file(filename);
|
||||
if (!file.open(QSaveFile::WriteOnly)) {
|
||||
throw FileSystemException("Couldn't open " + filename + " for writing: " + file.errorString());
|
||||
}
|
||||
if (buffer.size() != file.write(buffer)) {
|
||||
throw FileSystemException("Error writing data to " + filename + ": " + file.errorString());
|
||||
}
|
||||
if (!file.commit()) {
|
||||
throw FileSystemException("Error while committing data to " + filename + ": " + file.errorString());
|
||||
}
|
||||
}
|
||||
|
||||
void append(const QString& filename, const QByteArray& data)
|
||||
{
|
||||
ensureExists(QFileInfo(filename).dir());
|
||||
QFile file(filename);
|
||||
if (!file.open(QFile::Append)) {
|
||||
throw FileSystemException("Couldn't open " + filename + " for writing: " + file.errorString());
|
||||
}
|
||||
if (data.size() != file.write(data)) {
|
||||
throw FileSystemException("Error writing data to " + filename + ": " + file.errorString());
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray read(const QString& filename)
|
||||
{
|
||||
QFile file(filename);
|
||||
@ -238,6 +281,28 @@ bool ensureFolderPathExists(QString foldernamepath)
|
||||
return success;
|
||||
}
|
||||
|
||||
bool copyFileAttributes(QString src, QString dst)
|
||||
{
|
||||
#ifdef Q_OS_WIN32
|
||||
auto attrs = GetFileAttributesW(src.toStdWString().c_str());
|
||||
if (attrs == INVALID_FILE_ATTRIBUTES)
|
||||
return false;
|
||||
return SetFileAttributesW(dst.toStdWString().c_str(), attrs);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// needs folders to exists
|
||||
void copyFolderAttributes(QString src, QString dst, QString relative)
|
||||
{
|
||||
auto path = PathCombine(src, relative);
|
||||
QDir dsrc(src);
|
||||
while ((path = QFileInfo(path).path()).length() >= src.length()) {
|
||||
auto dst_path = PathCombine(dst, dsrc.relativeFilePath(path));
|
||||
copyFileAttributes(path, dst_path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copies a directory and it's contents from src to dest
|
||||
* @param offset subdirectory form src to copy to dest
|
||||
@ -265,6 +330,9 @@ bool copy::operator()(const QString& offset, bool dryRun)
|
||||
if (!m_followSymlinks)
|
||||
opt |= copy_opts::copy_symlinks;
|
||||
|
||||
if (m_overwrite)
|
||||
opt |= copy_opts::overwrite_existing;
|
||||
|
||||
// Function that'll do the actual copying
|
||||
auto copy_file = [&](QString src_path, QString relative_dst_path) {
|
||||
if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist))
|
||||
@ -273,6 +341,9 @@ bool copy::operator()(const QString& offset, bool dryRun)
|
||||
auto dst_path = PathCombine(dst, relative_dst_path);
|
||||
if (!dryRun) {
|
||||
ensureFilePathExists(dst_path);
|
||||
#ifdef Q_OS_WIN32
|
||||
copyFolderAttributes(src, dst, relative_dst_path);
|
||||
#endif
|
||||
fs::copy(StringUtils::toStdString(src_path), StringUtils::toStdString(dst_path), opt, err);
|
||||
}
|
||||
if (err) {
|
||||
@ -872,6 +943,8 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
|
||||
<< "\n";
|
||||
stream << "Type=Application"
|
||||
<< "\n";
|
||||
stream << "Categories=Game;ActionGame;AdventureGame;Simulation"
|
||||
<< "\n";
|
||||
stream << "Exec=\"" << target.toLocal8Bit() << "\"" << argstring.toLocal8Bit() << "\n";
|
||||
stream << "Name=" << name.toLocal8Bit() << "\n";
|
||||
if (!icon.isEmpty()) {
|
||||
|
@ -61,6 +61,16 @@ class FileSystemException : public ::Exception {
|
||||
*/
|
||||
void write(const QString& filename, const QByteArray& data);
|
||||
|
||||
/**
|
||||
* append data to a file safely
|
||||
*/
|
||||
void appendSafe(const QString& filename, const QByteArray& data);
|
||||
|
||||
/**
|
||||
* append data to a file
|
||||
*/
|
||||
void append(const QString& filename, const QByteArray& data);
|
||||
|
||||
/**
|
||||
* read data from a file safely\
|
||||
*/
|
||||
@ -109,6 +119,11 @@ class copy : public QObject {
|
||||
m_whitelist = whitelist;
|
||||
return *this;
|
||||
}
|
||||
copy& overwrite(const bool overwrite)
|
||||
{
|
||||
m_overwrite = overwrite;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); }
|
||||
|
||||
@ -128,6 +143,7 @@ class copy : public QObject {
|
||||
bool m_followSymlinks = true;
|
||||
const IPathMatcher* m_matcher = nullptr;
|
||||
bool m_whitelist = false;
|
||||
bool m_overwrite = false;
|
||||
QDir m_src;
|
||||
QDir m_dst;
|
||||
qsizetype m_copied;
|
||||
|
@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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
|
||||
@ -237,8 +238,11 @@ GroupId InstanceList::getInstanceGroup(const InstanceId& id) const
|
||||
return GroupId();
|
||||
}
|
||||
|
||||
void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
|
||||
void InstanceList::setInstanceGroup(const InstanceId& id, GroupId name)
|
||||
{
|
||||
if (name.isEmpty() && !name.isNull())
|
||||
name = QString();
|
||||
|
||||
auto inst = getInstanceById(id);
|
||||
if (!inst) {
|
||||
qDebug() << "Attempt to set a null instance's group";
|
||||
@ -249,6 +253,7 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
|
||||
auto iter = m_instanceGroupIndex.find(inst->id());
|
||||
if (iter != m_instanceGroupIndex.end()) {
|
||||
if (*iter != name) {
|
||||
decreaseGroupCount(*iter);
|
||||
*iter = name;
|
||||
changed = true;
|
||||
}
|
||||
@ -258,7 +263,7 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
m_groupNameCache.insert(name);
|
||||
increaseGroupCount(name);
|
||||
auto idx = getInstIndex(inst.get());
|
||||
emit dataChanged(index(idx), index(idx), { GroupRole });
|
||||
saveGroupList();
|
||||
@ -267,29 +272,55 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
|
||||
|
||||
QStringList InstanceList::getGroups()
|
||||
{
|
||||
return m_groupNameCache.values();
|
||||
return m_groupNameCache.keys();
|
||||
}
|
||||
|
||||
void InstanceList::deleteGroup(const QString& name)
|
||||
void InstanceList::deleteGroup(const GroupId& name)
|
||||
{
|
||||
m_groupNameCache.remove(name);
|
||||
m_collapsedGroups.remove(name);
|
||||
|
||||
bool removed = false;
|
||||
qDebug() << "Delete group" << name;
|
||||
for (auto& instance : m_instances) {
|
||||
const auto& instID = instance->id();
|
||||
auto instGroupName = getInstanceGroup(instID);
|
||||
const QString& instID = instance->id();
|
||||
const QString instGroupName = getInstanceGroup(instID);
|
||||
if (instGroupName == name) {
|
||||
m_instanceGroupIndex.remove(instID);
|
||||
qDebug() << "Remove" << instID << "from group" << name;
|
||||
removed = true;
|
||||
auto idx = getInstIndex(instance.get());
|
||||
if (idx > 0) {
|
||||
if (idx >= 0)
|
||||
emit dataChanged(index(idx), index(idx), { GroupRole });
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removed) {
|
||||
if (removed)
|
||||
saveGroupList();
|
||||
}
|
||||
|
||||
void InstanceList::renameGroup(const QString& src, const QString& dst)
|
||||
{
|
||||
m_groupNameCache.remove(src);
|
||||
if (m_collapsedGroups.remove(src))
|
||||
m_collapsedGroups.insert(dst);
|
||||
|
||||
bool modified = false;
|
||||
qDebug() << "Rename group" << src << "to" << dst;
|
||||
for (auto& instance : m_instances) {
|
||||
const QString& instID = instance->id();
|
||||
const QString instGroupName = getInstanceGroup(instID);
|
||||
if (instGroupName == src) {
|
||||
m_instanceGroupIndex[instID] = dst;
|
||||
increaseGroupCount(dst);
|
||||
qDebug() << "Set" << instID << "group to" << dst;
|
||||
modified = true;
|
||||
auto idx = getInstIndex(instance.get());
|
||||
if (idx >= 0)
|
||||
emit dataChanged(index(idx), index(idx), { GroupRole });
|
||||
}
|
||||
}
|
||||
if (modified)
|
||||
saveGroupList();
|
||||
}
|
||||
|
||||
bool InstanceList::isGroupCollapsed(const QString& group)
|
||||
@ -305,12 +336,13 @@ bool InstanceList::trashInstance(const InstanceId& id)
|
||||
return false;
|
||||
}
|
||||
|
||||
auto cachedGroupId = m_instanceGroupIndex[id];
|
||||
QString cachedGroupId = m_instanceGroupIndex[id];
|
||||
|
||||
qDebug() << "Will trash instance" << id;
|
||||
QString trashedLoc;
|
||||
|
||||
if (m_instanceGroupIndex.remove(id)) {
|
||||
decreaseGroupCount(cachedGroupId);
|
||||
saveGroupList();
|
||||
}
|
||||
|
||||
@ -348,7 +380,7 @@ void InstanceList::undoTrashInstance()
|
||||
QFile(top.trashPath).rename(top.polyPath);
|
||||
|
||||
m_instanceGroupIndex[top.id] = top.groupName;
|
||||
m_groupNameCache.insert(top.groupName);
|
||||
increaseGroupCount(top.groupName);
|
||||
|
||||
saveGroupList();
|
||||
emit instancesChanged();
|
||||
@ -362,7 +394,10 @@ void InstanceList::deleteInstance(const InstanceId& id)
|
||||
return;
|
||||
}
|
||||
|
||||
QString cachedGroupId = m_instanceGroupIndex[id];
|
||||
|
||||
if (m_instanceGroupIndex.remove(id)) {
|
||||
decreaseGroupCount(cachedGroupId);
|
||||
saveGroupList();
|
||||
}
|
||||
|
||||
@ -610,6 +645,25 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id)
|
||||
return inst;
|
||||
}
|
||||
|
||||
void InstanceList::increaseGroupCount(const QString& group)
|
||||
{
|
||||
if (group.isEmpty())
|
||||
return;
|
||||
|
||||
++m_groupNameCache[group];
|
||||
}
|
||||
|
||||
void InstanceList::decreaseGroupCount(const QString& group)
|
||||
{
|
||||
if (group.isEmpty())
|
||||
return;
|
||||
|
||||
if (--m_groupNameCache[group] < 1) {
|
||||
m_groupNameCache.remove(group);
|
||||
m_collapsedGroups.remove(group);
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceList::saveGroupList()
|
||||
{
|
||||
qDebug() << "Will save group list now.";
|
||||
@ -621,7 +675,7 @@ void InstanceList::saveGroupList()
|
||||
QString groupFileName = m_instDir + "/instgroups.json";
|
||||
QMap<QString, QSet<QString>> reverseGroupMap;
|
||||
for (auto iter = m_instanceGroupIndex.begin(); iter != m_instanceGroupIndex.end(); iter++) {
|
||||
QString id = iter.key();
|
||||
const QString& id = iter.key();
|
||||
QString group = iter.value();
|
||||
if (group.isEmpty())
|
||||
continue;
|
||||
@ -711,17 +765,22 @@ void InstanceList::loadGroupList()
|
||||
return;
|
||||
}
|
||||
|
||||
QSet<QString> groupSet;
|
||||
m_instanceGroupIndex.clear();
|
||||
m_groupNameCache.clear();
|
||||
|
||||
// Iterate through all the groups.
|
||||
QJsonObject groupMapping = rootObj.value("groups").toObject();
|
||||
for (QJsonObject::iterator iter = groupMapping.begin(); iter != groupMapping.end(); iter++) {
|
||||
QString groupName = iter.key();
|
||||
|
||||
if (iter.key().isEmpty()) {
|
||||
qWarning() << "Redundant empty group found";
|
||||
continue;
|
||||
}
|
||||
|
||||
// If not an object, complain and skip to the next one.
|
||||
if (!iter.value().isObject()) {
|
||||
qWarning() << QString("Group '%1' in the group list should be an object.").arg(groupName).toUtf8();
|
||||
qWarning() << QString("Group '%1' in the group list should be an object").arg(groupName).toUtf8();
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -733,23 +792,19 @@ void InstanceList::loadGroupList()
|
||||
continue;
|
||||
}
|
||||
|
||||
// keep a list/set of groups for choosing
|
||||
groupSet.insert(groupName);
|
||||
|
||||
auto hidden = groupObj.value("hidden").toBool(false);
|
||||
if (hidden) {
|
||||
if (hidden)
|
||||
m_collapsedGroups.insert(groupName);
|
||||
}
|
||||
|
||||
// Iterate through the list of instances in the group.
|
||||
QJsonArray instancesArray = groupObj.value("instances").toArray();
|
||||
|
||||
for (QJsonArray::iterator iter2 = instancesArray.begin(); iter2 != instancesArray.end(); iter2++) {
|
||||
m_instanceGroupIndex[(*iter2).toString()] = groupName;
|
||||
for (auto value : instancesArray) {
|
||||
m_instanceGroupIndex[value.toString()] = groupName;
|
||||
increaseGroupCount(groupName);
|
||||
}
|
||||
}
|
||||
m_groupsLoaded = true;
|
||||
m_groupNameCache.unite(groupSet);
|
||||
qDebug() << "Group list loaded.";
|
||||
}
|
||||
|
||||
@ -892,9 +947,12 @@ QString InstanceList::getStagedInstancePath()
|
||||
|
||||
bool InstanceList::commitStagedInstance(const QString& path,
|
||||
InstanceName const& instanceName,
|
||||
const QString& groupName,
|
||||
QString groupName,
|
||||
InstanceTask const& commiting)
|
||||
{
|
||||
if (groupName.isEmpty() && !groupName.isNull())
|
||||
groupName = QString();
|
||||
|
||||
QDir dir;
|
||||
QString instID;
|
||||
InstancePtr inst;
|
||||
@ -925,7 +983,7 @@ bool InstanceList::commitStagedInstance(const QString& path,
|
||||
}
|
||||
|
||||
m_instanceGroupIndex[instID] = groupName;
|
||||
m_groupNameCache.insert(groupName);
|
||||
increaseGroupCount(groupName);
|
||||
}
|
||||
|
||||
instanceSet.insert(instID);
|
||||
|
@ -1,16 +1,36 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
@ -86,9 +106,10 @@ class InstanceList : public QAbstractListModel {
|
||||
bool isGroupCollapsed(const QString& groupName);
|
||||
|
||||
GroupId getInstanceGroup(const InstanceId& id) const;
|
||||
void setInstanceGroup(const InstanceId& id, const GroupId& name);
|
||||
void setInstanceGroup(const InstanceId& id, GroupId name);
|
||||
|
||||
void deleteGroup(const GroupId& name);
|
||||
void renameGroup(const GroupId& src, const GroupId& dst);
|
||||
bool trashInstance(const InstanceId& id);
|
||||
bool trashedSomething();
|
||||
void undoTrashInstance();
|
||||
@ -109,7 +130,7 @@ class InstanceList : public QAbstractListModel {
|
||||
* should_override is used when another similar instance already exists, and we want to override it
|
||||
* - for instance, when updating it.
|
||||
*/
|
||||
bool commitStagedInstance(const QString& keyPath, const InstanceName& instanceName, const QString& groupName, const InstanceTask&);
|
||||
bool commitStagedInstance(const QString& keyPath, const InstanceName& instanceName, QString groupName, const InstanceTask&);
|
||||
|
||||
/**
|
||||
* Destroy a previously created staging area given by @keyPath - used when creation fails.
|
||||
@ -158,12 +179,16 @@ class InstanceList : public QAbstractListModel {
|
||||
QList<InstanceId> discoverInstances();
|
||||
InstancePtr loadInstance(const InstanceId& id);
|
||||
|
||||
void increaseGroupCount(const QString& group);
|
||||
void decreaseGroupCount(const QString& group);
|
||||
|
||||
private:
|
||||
int m_watchLevel = 0;
|
||||
int totalPlayTime = 0;
|
||||
bool m_dirty = false;
|
||||
QList<InstancePtr> m_instances;
|
||||
QSet<QString> m_groupNameCache;
|
||||
// id -> refs
|
||||
QMap<QString, int> m_groupNameCache;
|
||||
|
||||
SettingsObjectPtr m_globalSettings;
|
||||
QString m_instDir;
|
||||
|
@ -89,7 +89,7 @@ void LaunchController::decideAccount()
|
||||
// Tell the user they need to log in at least one account in order to play.
|
||||
auto reply = CustomMessageBox::selectable(m_parentWidget, tr("No Accounts"),
|
||||
tr("In order to play Minecraft, you must have at least one Microsoft "
|
||||
"account which owns Minecraft logged in."
|
||||
"account which owns Minecraft logged in. "
|
||||
"Would you like to open the account manager to add an account now?"),
|
||||
QMessageBox::Information, QMessageBox::Yes | QMessageBox::No)
|
||||
->exec();
|
||||
@ -106,7 +106,7 @@ void LaunchController::decideAccount()
|
||||
// Select the account to use. If the instance has a specific account set, that will be used. Otherwise, the default account will be used
|
||||
auto instanceAccountId = m_instance->settings()->get("InstanceAccountId").toString();
|
||||
auto instanceAccountIndex = accounts->findAccountByProfileId(instanceAccountId);
|
||||
if (instanceAccountIndex == -1) {
|
||||
if (instanceAccountIndex == -1 || instanceAccountId.isEmpty()) {
|
||||
m_accountToUse = accounts->defaultAccount();
|
||||
} else {
|
||||
m_accountToUse = accounts->at(instanceAccountIndex);
|
||||
|
@ -42,7 +42,11 @@
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QUrl>
|
||||
|
||||
#if defined(LAUNCHER_APPLICATION)
|
||||
#include <QtConcurrentRun>
|
||||
#endif
|
||||
|
||||
namespace MMCZip {
|
||||
// ours
|
||||
@ -132,6 +136,7 @@ bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files,
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(LAUNCHER_APPLICATION)
|
||||
// ours
|
||||
bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod*>& mods)
|
||||
{
|
||||
@ -217,6 +222,7 @@ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<M
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ours
|
||||
QString findFolderOfFileInZip(QuaZip* zip, const QString& what, const QStringList& ignore_paths, const QString& root)
|
||||
@ -422,6 +428,7 @@ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, Q
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(LAUNCHER_APPLICATION)
|
||||
void ExportToZipTask::executeTask()
|
||||
{
|
||||
setStatus("Adding files...");
|
||||
@ -500,5 +507,6 @@ bool ExportToZipTask::abort()
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace MMCZip
|
@ -48,7 +48,10 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#if defined(LAUNCHER_APPLICATION)
|
||||
#include "minecraft/mod/Mod.h"
|
||||
#endif
|
||||
#include "tasks/Task.h"
|
||||
|
||||
namespace MMCZip {
|
||||
@ -79,11 +82,12 @@ bool compressDirFiles(QuaZip* zip, QString dir, QFileInfoList files, bool follow
|
||||
*/
|
||||
bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files, bool followSymlinks = false);
|
||||
|
||||
#if defined(LAUNCHER_APPLICATION)
|
||||
/**
|
||||
* take a source jar, add mods to it, resulting in target jar
|
||||
*/
|
||||
bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod*>& mods);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Find a single file in archive by file name (not path)
|
||||
*
|
||||
@ -147,6 +151,7 @@ bool extractFile(QString fileCompressed, QString file, QString dir);
|
||||
*/
|
||||
bool collectFileListRecursively(const QString& rootDir, const QString& subDir, QFileInfoList* files, FilterFunction excludeFilter);
|
||||
|
||||
#if defined(LAUNCHER_APPLICATION)
|
||||
class ExportToZipTask : public Task {
|
||||
public:
|
||||
ExportToZipTask(QString outputPath, QDir dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false)
|
||||
@ -167,7 +172,7 @@ class ExportToZipTask : public Task {
|
||||
void setExcludeFiles(QStringList excludeFiles) { m_exclude_files = excludeFiles; }
|
||||
void addExtraFile(QString fileName, QByteArray data) { m_extra_files.insert(fileName, data); }
|
||||
|
||||
typedef std::optional<QString> ZipResult;
|
||||
using ZipResult = std::optional<QString>;
|
||||
|
||||
protected:
|
||||
virtual void executeTask() override;
|
||||
@ -189,4 +194,5 @@ class ExportToZipTask : public Task {
|
||||
QFuture<ZipResult> m_build_zip_future;
|
||||
QFutureWatcher<ZipResult> m_build_zip_watcher;
|
||||
};
|
||||
#endif
|
||||
} // namespace MMCZip
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <QPixmapCache>
|
||||
#include <QThread>
|
||||
#include <QTime>
|
||||
#include <limits>
|
||||
|
||||
#define GET_TYPE() \
|
||||
Qt::ConnectionType type; \
|
||||
@ -100,10 +101,14 @@ class PixmapCache final : public QObject {
|
||||
*/
|
||||
bool _markCacheMissByEviciton()
|
||||
{
|
||||
static constexpr uint maxInt = static_cast<uint>(std::numeric_limits<int>::max());
|
||||
static constexpr uint step = 10240;
|
||||
static constexpr int oneSecond = 1000;
|
||||
|
||||
auto now = QTime::currentTime();
|
||||
if (!m_last_cache_miss_by_eviciton.isNull()) {
|
||||
auto diff = m_last_cache_miss_by_eviciton.msecsTo(now);
|
||||
if (diff < 1000) { // less than a second ago
|
||||
if (diff < oneSecond) { // less than a second ago
|
||||
++m_consecutive_fast_evicitons;
|
||||
} else {
|
||||
m_consecutive_fast_evicitons = 0;
|
||||
@ -111,11 +116,17 @@ class PixmapCache final : public QObject {
|
||||
}
|
||||
m_last_cache_miss_by_eviciton = now;
|
||||
if (m_consecutive_fast_evicitons >= m_consecutive_fast_evicitons_threshold) {
|
||||
// double the cache size
|
||||
auto newSize = _cacheLimit() * 2;
|
||||
qDebug() << m_consecutive_fast_evicitons << "pixmap cache misses by eviction happened too fast, doubling cache size to"
|
||||
<< newSize;
|
||||
_setCacheLimit(newSize);
|
||||
// increase the cache size
|
||||
uint newSize = _cacheLimit() + step;
|
||||
if (newSize >= maxInt) { // increase it until you overflow :D
|
||||
newSize = maxInt;
|
||||
qDebug() << m_consecutive_fast_evicitons
|
||||
<< tr("pixmap cache misses by eviction happened too fast, doing nothing as the cache size reached it's limit");
|
||||
} else {
|
||||
qDebug() << m_consecutive_fast_evicitons
|
||||
<< tr("pixmap cache misses by eviction happened too fast, increasing cache size to") << static_cast<int>(newSize);
|
||||
}
|
||||
_setCacheLimit(static_cast<int>(newSize));
|
||||
m_consecutive_fast_evicitons = 0;
|
||||
return true;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
*/
|
||||
|
||||
#include "StringUtils.h"
|
||||
#include <qpair.h>
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QUuid>
|
||||
@ -149,7 +150,7 @@ QString StringUtils::truncateUrlHumanFriendly(QUrl& url, int max_len, bool hard_
|
||||
}
|
||||
|
||||
if ((url_compact.length() >= max_len) && hard_limit) {
|
||||
// still too long, truncate normaly
|
||||
// still too long, truncate normally
|
||||
url_compact = QString(str_url);
|
||||
auto to_remove = url_compact.length() - max_len + 3;
|
||||
url_compact.remove(url_compact.length() - to_remove - 1, to_remove);
|
||||
@ -182,3 +183,32 @@ QString StringUtils::getRandomAlphaNumeric()
|
||||
{
|
||||
return QUuid::createUuid().toString(QUuid::Id128);
|
||||
}
|
||||
|
||||
QPair<QString, QString> StringUtils::splitFirst(const QString& s, const QString& sep, Qt::CaseSensitivity cs)
|
||||
{
|
||||
QString left, right;
|
||||
auto index = s.indexOf(sep, 0, cs);
|
||||
left = s.mid(0, index);
|
||||
right = s.mid(index + sep.length());
|
||||
return qMakePair(left, right);
|
||||
}
|
||||
|
||||
QPair<QString, QString> StringUtils::splitFirst(const QString& s, QChar sep, Qt::CaseSensitivity cs)
|
||||
{
|
||||
QString left, right;
|
||||
auto index = s.indexOf(sep, 0, cs);
|
||||
left = s.mid(0, index);
|
||||
right = s.mid(left.length() + 1);
|
||||
return qMakePair(left, right);
|
||||
}
|
||||
|
||||
QPair<QString, QString> StringUtils::splitFirst(const QString& s, const QRegularExpression& re)
|
||||
{
|
||||
QString left, right;
|
||||
QRegularExpressionMatch match;
|
||||
auto index = s.indexOf(re, 0, &match);
|
||||
left = s.mid(0, index);
|
||||
auto end = match.hasMatch() ? left.length() + match.capturedLength() : left.length() + 1;
|
||||
right = s.mid(end);
|
||||
return qMakePair(left, right);
|
||||
}
|
||||
|
@ -36,8 +36,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <utility>
|
||||
|
||||
namespace StringUtils {
|
||||
|
||||
@ -70,12 +72,17 @@ int naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs)
|
||||
/**
|
||||
* @brief Truncate a url while keeping its readability py placing the `...` in the middle of the path
|
||||
* @param url Url to truncate
|
||||
* @param max_len max lenght of url in charaters
|
||||
* @param hard_limit if truncating the path can't get the url short enough, truncate it normaly.
|
||||
* @param max_len max length of url in characters
|
||||
* @param hard_limit if truncating the path can't get the url short enough, truncate it normally.
|
||||
*/
|
||||
QString truncateUrlHumanFriendly(QUrl& url, int max_len, bool hard_limit = false);
|
||||
|
||||
QString humanReadableFileSize(double bytes, bool use_si = false, int decimal_points = 1);
|
||||
|
||||
QString getRandomAlphaNumeric();
|
||||
|
||||
QPair<QString, QString> splitFirst(const QString& s, const QString& sep, Qt::CaseSensitivity cs = Qt::CaseSensitive);
|
||||
QPair<QString, QString> splitFirst(const QString& s, QChar sep, Qt::CaseSensitivity cs = Qt::CaseSensitive);
|
||||
QPair<QString, QString> splitFirst(const QString& s, const QRegularExpression& re);
|
||||
|
||||
} // namespace StringUtils
|
||||
|
@ -56,6 +56,7 @@ class Version {
|
||||
bool operator!=(const Version& other) const;
|
||||
|
||||
QString toString() const { return m_string; }
|
||||
bool isEmpty() const { return m_string.isEmpty(); }
|
||||
|
||||
friend QDebug operator<<(QDebug debug, const Version& v);
|
||||
|
||||
|
@ -10,7 +10,7 @@ class VersionProxyModel : public QAbstractProxyModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Column { Name, ParentVersion, Branch, Type, Architecture, Path, Time };
|
||||
typedef QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>> FilterMap;
|
||||
using FilterMap = QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>>;
|
||||
|
||||
public:
|
||||
VersionProxyModel(QObject* parent = 0);
|
||||
|
@ -93,6 +93,7 @@ FileLinkApp::FileLinkApp(int& argc, char** argv) : QCoreApplication(argc, argv),
|
||||
joinServer(serverToJoin);
|
||||
} else {
|
||||
qDebug() << "no server to join";
|
||||
m_status = Failed;
|
||||
exit();
|
||||
}
|
||||
}
|
||||
@ -108,6 +109,7 @@ void FileLinkApp::joinServer(QString server)
|
||||
connect(&socket, &QLocalSocket::readyRead, this, &FileLinkApp::readPathPairs);
|
||||
|
||||
connect(&socket, &QLocalSocket::errorOccurred, this, [&](QLocalSocket::LocalSocketError socketError) {
|
||||
m_status = Failed;
|
||||
switch (socketError) {
|
||||
case QLocalSocket::ServerNotFoundError:
|
||||
qDebug()
|
||||
@ -132,6 +134,7 @@ void FileLinkApp::joinServer(QString server)
|
||||
|
||||
connect(&socket, &QLocalSocket::disconnected, this, [&]() {
|
||||
qDebug() << "disconnected from server, should exit";
|
||||
m_status = Succeeded;
|
||||
exit();
|
||||
});
|
||||
|
||||
|
@ -41,8 +41,10 @@ class FileLinkApp : public QCoreApplication {
|
||||
// friends for the purpose of limiting access to deprecated stuff
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Status { Starting, Failed, Succeeded, Initialized };
|
||||
FileLinkApp(int& argc, char** argv);
|
||||
virtual ~FileLinkApp();
|
||||
Status status() const { return m_status; }
|
||||
|
||||
private:
|
||||
void joinServer(QString server);
|
||||
@ -50,6 +52,8 @@ class FileLinkApp : public QCoreApplication {
|
||||
void runLink();
|
||||
void sendResults();
|
||||
|
||||
Status m_status = Status::Starting;
|
||||
|
||||
bool m_useHardLinks = false;
|
||||
|
||||
QDateTime m_startTime;
|
||||
|
@ -26,5 +26,16 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
FileLinkApp ldh(argc, argv);
|
||||
|
||||
return ldh.exec();
|
||||
switch (ldh.status()) {
|
||||
case FileLinkApp::Starting:
|
||||
case FileLinkApp::Initialized: {
|
||||
return ldh.exec();
|
||||
}
|
||||
case FileLinkApp::Failed:
|
||||
return 1;
|
||||
case FileLinkApp::Succeeded:
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -22,8 +22,8 @@ struct JavaCheckResult {
|
||||
enum class Validity { Errored, ReturnedInvalidData, Valid } validity = Validity::Errored;
|
||||
};
|
||||
|
||||
typedef shared_qobject_ptr<QProcess> QProcessPtr;
|
||||
typedef shared_qobject_ptr<JavaChecker> JavaCheckerPtr;
|
||||
using QProcessPtr = shared_qobject_ptr<QProcess>;
|
||||
using JavaCheckerPtr = shared_qobject_ptr<JavaChecker>;
|
||||
class JavaChecker : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "tasks/Task.h"
|
||||
|
||||
class JavaCheckerJob;
|
||||
typedef shared_qobject_ptr<JavaCheckerJob> JavaCheckerJobPtr;
|
||||
using JavaCheckerJobPtr = shared_qobject_ptr<JavaCheckerJob>;
|
||||
|
||||
// FIXME: this just seems horribly redundant
|
||||
class JavaCheckerJob : public Task {
|
||||
|
@ -42,4 +42,4 @@ struct JavaInstall : public BaseVersion {
|
||||
bool recommended = false;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<JavaInstall> JavaInstallPtr;
|
||||
using JavaInstallPtr = std::shared_ptr<JavaInstall>;
|
||||
|
@ -34,6 +34,7 @@
|
||||
*/
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
@ -335,6 +336,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
||||
}
|
||||
}
|
||||
|
||||
candidates.append(getMinecraftJavaBundle());
|
||||
candidates = addJavasFromEnv(candidates);
|
||||
candidates.removeDuplicates();
|
||||
return candidates;
|
||||
@ -360,6 +362,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
||||
javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/bin/java");
|
||||
javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Commands/java");
|
||||
}
|
||||
javas.append(getMinecraftJavaBundle());
|
||||
javas = addJavasFromEnv(javas);
|
||||
javas.removeDuplicates();
|
||||
return javas;
|
||||
@ -411,6 +414,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
||||
// javas downloaded by sdkman
|
||||
scanJavaDirs(FS::PathCombine(home, ".sdkman/candidates/java"));
|
||||
|
||||
javas.append(getMinecraftJavaBundle());
|
||||
javas = addJavasFromEnv(javas);
|
||||
javas.removeDuplicates();
|
||||
return javas;
|
||||
@ -423,6 +427,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
||||
QList<QString> javas;
|
||||
javas.append(this->GetDefaultJava()->path);
|
||||
|
||||
javas.append(getMinecraftJavaBundle());
|
||||
return addJavasFromEnv(javas);
|
||||
}
|
||||
#endif
|
||||
@ -431,3 +436,50 @@ QString JavaUtils::getJavaCheckPath()
|
||||
{
|
||||
return APPLICATION->getJarPath("JavaCheck.jar");
|
||||
}
|
||||
|
||||
QStringList getMinecraftJavaBundle()
|
||||
{
|
||||
QString partialPath;
|
||||
QString executable = "java";
|
||||
QStringList processpaths;
|
||||
#if defined(Q_OS_OSX)
|
||||
partialPath = FS::PathCombine(QDir::homePath(), "Library/Application Support");
|
||||
#elif defined(Q_OS_WIN32)
|
||||
partialPath = QProcessEnvironment::systemEnvironment().value("LOCALAPPDATA", "");
|
||||
executable += "w.exe";
|
||||
|
||||
// add the microsoft store version of the launcher to the search. the current path is:
|
||||
// C:\Users\USERNAME\AppData\Local\Packages\Microsoft.4297127D64EC6_8wekyb3d8bbwe\LocalCache\Local\runtime
|
||||
auto minecraftMSStorePath =
|
||||
FS::PathCombine(QFileInfo(partialPath).absolutePath(), "Local", "Packages", "Microsoft.4297127D64EC6_8wekyb3d8bbwe");
|
||||
minecraftMSStorePath = FS::PathCombine(minecraftMSStorePath, "LocalCache", "Local", "runtime");
|
||||
processpaths << minecraftMSStorePath;
|
||||
#else
|
||||
partialPath = QDir::homePath();
|
||||
#endif
|
||||
auto minecraftDataPath = FS::PathCombine(partialPath, ".minecraft", "runtime");
|
||||
processpaths << minecraftDataPath;
|
||||
|
||||
QStringList javas;
|
||||
while (!processpaths.isEmpty()) {
|
||||
auto dirPath = processpaths.takeFirst();
|
||||
QDir dir(dirPath);
|
||||
if (!dir.exists())
|
||||
continue;
|
||||
auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
auto binFound = false;
|
||||
for (auto& entry : entries) {
|
||||
if (entry.baseName() == "bin") {
|
||||
javas.append(FS::PathCombine(entry.canonicalFilePath(), executable));
|
||||
binFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!binFound) {
|
||||
for (auto& entry : entries) {
|
||||
processpaths << entry.canonicalFilePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
return javas;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
QString stripVariableEntries(QString name, QString target, QString remove);
|
||||
QProcessEnvironment CleanEnviroment();
|
||||
QStringList getMinecraftJavaBundle();
|
||||
|
||||
class JavaUtils : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -45,10 +45,12 @@ QString JavaVersion::toString() const
|
||||
|
||||
bool JavaVersion::requiresPermGen()
|
||||
{
|
||||
if (m_parseable) {
|
||||
return m_major < 8;
|
||||
}
|
||||
return true;
|
||||
return !m_parseable || m_major < 8;
|
||||
}
|
||||
|
||||
bool JavaVersion::isModular()
|
||||
{
|
||||
return m_parseable && m_major >= 9;
|
||||
}
|
||||
|
||||
bool JavaVersion::operator<(const JavaVersion& rhs)
|
||||
|
@ -25,6 +25,8 @@ class JavaVersion {
|
||||
|
||||
bool requiresPermGen();
|
||||
|
||||
bool isModular();
|
||||
|
||||
QString toString() const;
|
||||
|
||||
int major() { return m_major; }
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
class Agent;
|
||||
|
||||
typedef std::shared_ptr<Agent> AgentPtr;
|
||||
using AgentPtr = std::shared_ptr<Agent>;
|
||||
|
||||
class Agent {
|
||||
public:
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "FileSystem.h"
|
||||
#include "net/ApiDownload.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
#include "net/Download.h"
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
|
@ -105,4 +105,4 @@ class Component : public QObject, public ProblemProvider {
|
||||
bool m_loaded = false;
|
||||
};
|
||||
|
||||
typedef shared_qobject_ptr<Component> ComponentPtr;
|
||||
using ComponentPtr = shared_qobject_ptr<Component>;
|
||||
|
@ -52,7 +52,7 @@
|
||||
class Library;
|
||||
class MinecraftInstance;
|
||||
|
||||
typedef std::shared_ptr<Library> LibraryPtr;
|
||||
using LibraryPtr = std::shared_ptr<Library>;
|
||||
|
||||
class Library {
|
||||
friend class OneSixVersionFormat;
|
||||
|
@ -184,6 +184,13 @@ void MinecraftInstance::loadSpecificSettings()
|
||||
m_settings->registerOverride(global_settings->getSetting("CloseAfterLaunch"), miscellaneousOverride);
|
||||
m_settings->registerOverride(global_settings->getSetting("QuitAfterGameStop"), miscellaneousOverride);
|
||||
|
||||
// Legacy-related options
|
||||
auto legacySettings = m_settings->registerSetting("OverrideLegacySettings", false);
|
||||
m_settings->registerOverride(global_settings->getSetting("OnlineFixes"), legacySettings);
|
||||
|
||||
auto envSetting = m_settings->registerSetting("OverrideEnv", false);
|
||||
m_settings->registerOverride(global_settings->getSetting("Env"), envSetting);
|
||||
|
||||
m_settings->set("InstanceType", "OneSix");
|
||||
}
|
||||
|
||||
@ -513,20 +520,28 @@ QStringList MinecraftInstance::javaArguments()
|
||||
|
||||
args << "-Duser.language=en";
|
||||
|
||||
if (javaVersion.isModular() && shouldApplyOnlineFixes())
|
||||
// allow reflective access to java.net - required by the skin fix
|
||||
args << "--add-opens"
|
||||
<< "java.base/java.net=ALL-UNNAMED";
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
QString MinecraftInstance::getLauncher()
|
||||
{
|
||||
auto profile = m_components->getProfile();
|
||||
|
||||
// use legacy launcher if the traits are set
|
||||
if (profile->getTraits().contains("legacyLaunch") || profile->getTraits().contains("alphaLaunch"))
|
||||
if (traits().contains("legacyLaunch") || traits().contains("alphaLaunch"))
|
||||
return "legacy";
|
||||
|
||||
return "standard";
|
||||
}
|
||||
|
||||
bool MinecraftInstance::shouldApplyOnlineFixes()
|
||||
{
|
||||
return traits().contains("legacyServices") && settings()->get("OnlineFixes").toBool();
|
||||
}
|
||||
|
||||
QMap<QString, QString> MinecraftInstance::getVariables()
|
||||
{
|
||||
QMap<QString, QString> out;
|
||||
@ -536,6 +551,7 @@ QMap<QString, QString> MinecraftInstance::getVariables()
|
||||
out.insert("INST_MC_DIR", QDir::toNativeSeparators(QDir(gameRoot()).absolutePath()));
|
||||
out.insert("INST_JAVA", settings()->get("JavaPath").toString());
|
||||
out.insert("INST_JAVA_ARGS", javaArguments().join(' '));
|
||||
out.insert("NO_COLOR", "1");
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -559,15 +575,20 @@ QProcessEnvironment MinecraftInstance::createLaunchEnvironment()
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
if (settings()->get("EnableMangoHud").toBool() && APPLICATION->capabilities() & Application::SupportsMangoHud) {
|
||||
auto preloadList = env.value("LD_PRELOAD").split(QLatin1String(":"));
|
||||
auto libPaths = env.value("LD_LIBRARY_PATH").split(QLatin1String(":"));
|
||||
QStringList preloadList;
|
||||
if (auto value = env.value("LD_PRELOAD"); !value.isEmpty())
|
||||
preloadList = value.split(QLatin1String(":"));
|
||||
QStringList libPaths;
|
||||
if (auto value = env.value("LD_LIBRARY_PATH"); !value.isEmpty())
|
||||
libPaths = value.split(QLatin1String(":"));
|
||||
|
||||
auto mangoHudLibString = MangoHud::getLibraryString();
|
||||
if (!mangoHudLibString.isEmpty()) {
|
||||
QFileInfo mangoHudLib(mangoHudLibString);
|
||||
|
||||
// dlsym variant is only needed for OpenGL and not included in the vulkan layer
|
||||
preloadList << "libMangoHud_dlsym.so" << mangoHudLib.fileName();
|
||||
preloadList << "libMangoHud_dlsym.so"
|
||||
<< "libMangoHud_opengl.so" << mangoHudLib.fileName();
|
||||
libPaths << mangoHudLib.absolutePath();
|
||||
}
|
||||
|
||||
@ -586,6 +607,23 @@ QProcessEnvironment MinecraftInstance::createLaunchEnvironment()
|
||||
}
|
||||
#endif
|
||||
|
||||
// custom env
|
||||
|
||||
auto insertEnv = [&env](QMap<QString, QVariant> envMap) {
|
||||
if (envMap.isEmpty())
|
||||
return;
|
||||
|
||||
for (auto iter = envMap.begin(); iter != envMap.end(); iter++)
|
||||
env.insert(iter.key(), iter.value().toString());
|
||||
};
|
||||
|
||||
bool overrideEnv = settings()->get("OverrideEnv").toBool();
|
||||
|
||||
if (!overrideEnv)
|
||||
insertEnv(APPLICATION->settings()->get("Env").toMap());
|
||||
else
|
||||
insertEnv(settings()->get("Env").toMap());
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
@ -698,7 +736,7 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS
|
||||
{
|
||||
QString windowParams;
|
||||
if (settings()->get("LaunchMaximized").toBool())
|
||||
windowParams = "max";
|
||||
windowParams = "maximized";
|
||||
else
|
||||
windowParams =
|
||||
QString("%1x%2").arg(settings()->get("MinecraftWinWidth").toInt()).arg(settings()->get("MinecraftWinHeight").toInt());
|
||||
@ -706,6 +744,19 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS
|
||||
launchScript += "windowParams " + windowParams + "\n";
|
||||
}
|
||||
|
||||
// launcher info
|
||||
{
|
||||
launchScript += "launcherBrand " + BuildConfig.LAUNCHER_NAME + "\n";
|
||||
launchScript += "launcherVersion " + BuildConfig.printableVersionString() + "\n";
|
||||
}
|
||||
|
||||
// instance info
|
||||
{
|
||||
launchScript += "instanceName " + name() + "\n";
|
||||
launchScript += "instanceIconKey " + name() + "\n";
|
||||
launchScript += "instanceIconPath icon.png\n"; // we already save a copy here
|
||||
}
|
||||
|
||||
// legacy auth
|
||||
if (session) {
|
||||
launchScript += "userName " + session->player_name + "\n";
|
||||
@ -716,6 +767,9 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS
|
||||
launchScript += "traits " + trait + "\n";
|
||||
}
|
||||
|
||||
if (shouldApplyOnlineFixes())
|
||||
launchScript += "onlineFixes true\n";
|
||||
|
||||
launchScript += "launcher " + getLauncher() + "\n";
|
||||
|
||||
// qDebug() << "Generated launch script:" << launchScript;
|
||||
|
@ -129,6 +129,7 @@ class MinecraftInstance : public BaseInstance {
|
||||
/// get arguments passed to java
|
||||
QStringList javaArguments();
|
||||
QString getLauncher();
|
||||
bool shouldApplyOnlineFixes();
|
||||
|
||||
/// get variables for launch command variable substitution/environment
|
||||
QMap<QString, QString> getVariables() override;
|
||||
@ -173,4 +174,4 @@ class MinecraftInstance : public BaseInstance {
|
||||
mutable std::shared_ptr<GameOptions> m_game_options;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<MinecraftInstance> MinecraftInstancePtr;
|
||||
using MinecraftInstancePtr = std::shared_ptr<MinecraftInstance>;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
struct MojangDownloadInfo {
|
||||
// types
|
||||
typedef std::shared_ptr<MojangDownloadInfo> Ptr;
|
||||
using Ptr = std::shared_ptr<MojangDownloadInfo>;
|
||||
|
||||
// data
|
||||
/// Local filesystem path. WARNING: not used, only here so we can pass through mojang files unmolested!
|
||||
@ -23,7 +23,7 @@ struct MojangLibraryDownloadInfo {
|
||||
MojangLibraryDownloadInfo() {}
|
||||
|
||||
// types
|
||||
typedef std::shared_ptr<MojangLibraryDownloadInfo> Ptr;
|
||||
using Ptr = std::shared_ptr<MojangLibraryDownloadInfo>;
|
||||
|
||||
// methods
|
||||
MojangDownloadInfo* getDownloadInfo(QString classifier)
|
||||
@ -42,7 +42,7 @@ struct MojangLibraryDownloadInfo {
|
||||
|
||||
struct MojangAssetIndexInfo : public MojangDownloadInfo {
|
||||
// types
|
||||
typedef std::shared_ptr<MojangAssetIndexInfo> Ptr;
|
||||
using Ptr = std::shared_ptr<MojangAssetIndexInfo>;
|
||||
|
||||
// methods
|
||||
MojangAssetIndexInfo() {}
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "VersionFile.h"
|
||||
|
||||
namespace ProfileUtils {
|
||||
typedef QStringList PatchOrder;
|
||||
using PatchOrder = QStringList;
|
||||
|
||||
/// Read and parse a OneSix format order file
|
||||
bool readOverrideOrders(QString path, PatchOrder& order);
|
||||
|
@ -43,4 +43,4 @@ struct AuthSession {
|
||||
bool demo = false;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<AuthSession> AuthSessionPtr;
|
||||
using AuthSessionPtr = std::shared_ptr<AuthSession>;
|
||||
|
@ -54,7 +54,7 @@ class Task;
|
||||
class AccountTask;
|
||||
class MinecraftAccount;
|
||||
|
||||
typedef shared_qobject_ptr<MinecraftAccount> MinecraftAccountPtr;
|
||||
using MinecraftAccountPtr = shared_qobject_ptr<MinecraftAccount>;
|
||||
Q_DECLARE_METATYPE(MinecraftAccountPtr)
|
||||
|
||||
/**
|
||||
|
@ -105,6 +105,17 @@ void LauncherPartLaunch::executeTask()
|
||||
auto instance = m_parent->instance();
|
||||
std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
|
||||
|
||||
QString legacyJarPath;
|
||||
if (minecraftInstance->getLauncher() == "legacy" || minecraftInstance->shouldApplyOnlineFixes()) {
|
||||
legacyJarPath = APPLICATION->getJarPath("NewLaunchLegacy.jar");
|
||||
if (legacyJarPath.isEmpty()) {
|
||||
const char* reason = QT_TR_NOOP("Legacy launcher library could not be found. Please check your installation.");
|
||||
emit logLine(tr(reason), MessageLevel::Fatal);
|
||||
emitFailed(tr(reason));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_launchScript = minecraftInstance->createLaunchScript(m_session, m_serverToJoin);
|
||||
QStringList args = minecraftInstance->javaArguments();
|
||||
QString allArgs = args.join(", ");
|
||||
@ -120,6 +131,9 @@ void LauncherPartLaunch::executeTask()
|
||||
auto classPath = minecraftInstance->getClassPath();
|
||||
classPath.prepend(jarPath);
|
||||
|
||||
if (!legacyJarPath.isEmpty())
|
||||
classPath.prepend(legacyJarPath);
|
||||
|
||||
auto natPath = minecraftInstance->getNativePath();
|
||||
#ifdef Q_OS_WIN
|
||||
if (!fitsInLocal8bit(natPath)) {
|
||||
|
@ -26,4 +26,4 @@ struct MinecraftServerTarget {
|
||||
static MinecraftServerTarget parse(const QString& fullAddress);
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<MinecraftServerTarget> MinecraftServerTargetPtr;
|
||||
using MinecraftServerTargetPtr = std::shared_ptr<MinecraftServerTarget>;
|
||||
|
@ -37,9 +37,9 @@
|
||||
#include "ModFolderModel.h"
|
||||
|
||||
#include <FileSystem.h>
|
||||
#include <qheaderview.h>
|
||||
#include <QDebug>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QHeaderView>
|
||||
#include <QIcon>
|
||||
#include <QMimeData>
|
||||
#include <QString>
|
||||
@ -65,8 +65,8 @@ ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool
|
||||
m_column_names = QStringList({ "Enable", "Image", "Name", "Version", "Last Modified", "Provider" });
|
||||
m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider") });
|
||||
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER };
|
||||
m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch,
|
||||
QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents };
|
||||
m_column_resize_modes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch,
|
||||
QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive };
|
||||
m_columnsHideable = { false, true, false, true, true, true };
|
||||
}
|
||||
|
||||
@ -131,6 +131,11 @@ QVariant ModFolderModel::data(const QModelIndex& index, int role) const
|
||||
}
|
||||
return {};
|
||||
}
|
||||
case Qt::SizeHintRole:
|
||||
if (column == ImageColumn) {
|
||||
return QSize(32, 32);
|
||||
}
|
||||
return {};
|
||||
case Qt::CheckStateRole:
|
||||
switch (column) {
|
||||
case ActiveColumn:
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
#include <QHeaderView>
|
||||
#include <QIcon>
|
||||
#include <QMenu>
|
||||
#include <QMimeData>
|
||||
@ -516,36 +517,22 @@ void ResourceFolderModel::setupHeaderAction(QAction* act, int column)
|
||||
act->setText(columnNames().at(column));
|
||||
}
|
||||
|
||||
void ResourceFolderModel::saveHiddenColumn(int column, bool hidden)
|
||||
void ResourceFolderModel::saveColumns(QTreeView* tree)
|
||||
{
|
||||
auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id());
|
||||
auto const setting_name = QString("UI/%1_Page/Columns").arg(id());
|
||||
auto setting = (m_instance->settings()->contains(setting_name)) ? m_instance->settings()->getSetting(setting_name)
|
||||
: m_instance->settings()->registerSetting(setting_name);
|
||||
|
||||
auto hiddenColumns = setting->get().toStringList();
|
||||
auto name = columnNames(false).at(column);
|
||||
auto index = hiddenColumns.indexOf(name);
|
||||
if (index >= 0 && !hidden) {
|
||||
hiddenColumns.removeAt(index);
|
||||
} else if (index < 0 && hidden) {
|
||||
hiddenColumns.append(name);
|
||||
}
|
||||
setting->set(hiddenColumns);
|
||||
setting->set(tree->header()->saveState());
|
||||
}
|
||||
|
||||
void ResourceFolderModel::loadHiddenColumns(QTreeView* tree)
|
||||
void ResourceFolderModel::loadColumns(QTreeView* tree)
|
||||
{
|
||||
auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id());
|
||||
auto const setting_name = QString("UI/%1_Page/Columns").arg(id());
|
||||
auto setting = (m_instance->settings()->contains(setting_name)) ? m_instance->settings()->getSetting(setting_name)
|
||||
: m_instance->settings()->registerSetting(setting_name);
|
||||
|
||||
auto hiddenColumns = setting->get().toStringList();
|
||||
auto col_names = columnNames(false);
|
||||
for (auto col_name : hiddenColumns) {
|
||||
auto index = col_names.indexOf(col_name);
|
||||
if (index >= 0)
|
||||
tree->setColumnHidden(index, true);
|
||||
}
|
||||
tree->header()->restoreState(setting->get().toByteArray());
|
||||
}
|
||||
|
||||
QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree)
|
||||
@ -570,7 +557,7 @@ QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree)
|
||||
if (m_column_resize_modes.at(c) == QHeaderView::ResizeToContents)
|
||||
tree->resizeColumnToContents(c);
|
||||
}
|
||||
saveHiddenColumn(col, !toggled);
|
||||
saveColumns(tree);
|
||||
});
|
||||
|
||||
menu->addAction(act);
|
||||
|
@ -117,8 +117,8 @@ class ResourceFolderModel : public QAbstractListModel {
|
||||
[[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void setupHeaderAction(QAction* act, int column);
|
||||
void saveHiddenColumn(int column, bool hidden);
|
||||
void loadHiddenColumns(QTreeView* tree);
|
||||
void saveColumns(QTreeView* tree);
|
||||
void loadColumns(QTreeView* tree);
|
||||
QMenu* createHeaderContextMenu(QTreeView* tree);
|
||||
|
||||
/** This creates a proxy model to filter / sort the model for a UI.
|
||||
@ -201,8 +201,7 @@ class ResourceFolderModel : public QAbstractListModel {
|
||||
QList<SortType> m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE };
|
||||
QStringList m_column_names = { "Enable", "Name", "Last Modified" };
|
||||
QStringList m_column_names_translated = { tr("Enable"), tr("Name"), tr("Last Modified") };
|
||||
QList<QHeaderView::ResizeMode> m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Stretch,
|
||||
QHeaderView::ResizeToContents };
|
||||
QList<QHeaderView::ResizeMode> m_column_resize_modes = { QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive };
|
||||
QList<bool> m_columnsHideable = { false, false, true };
|
||||
|
||||
QDir m_dir;
|
||||
|
@ -52,8 +52,8 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstanc
|
||||
m_column_names = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified" });
|
||||
m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified") });
|
||||
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE };
|
||||
m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents,
|
||||
QHeaderView::ResizeToContents };
|
||||
m_column_resize_modes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive,
|
||||
QHeaderView::Interactive };
|
||||
m_columnsHideable = { false, true, false, true, true };
|
||||
}
|
||||
|
||||
@ -117,6 +117,11 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const
|
||||
}
|
||||
return m_resources[row]->internal_id();
|
||||
}
|
||||
case Qt::SizeHintRole:
|
||||
if (column == ImageColumn) {
|
||||
return QSize(32, 32);
|
||||
}
|
||||
return {};
|
||||
case Qt::CheckStateRole:
|
||||
switch (column) {
|
||||
case ActiveColumn:
|
||||
|
@ -47,8 +47,7 @@ TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance*
|
||||
m_column_names = QStringList({ "Enable", "Image", "Name", "Last Modified" });
|
||||
m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified") });
|
||||
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE };
|
||||
m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch,
|
||||
QHeaderView::ResizeToContents };
|
||||
m_column_resize_modes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive };
|
||||
m_columnsHideable = { false, true, false, true };
|
||||
}
|
||||
|
||||
@ -104,6 +103,11 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const
|
||||
}
|
||||
return {};
|
||||
}
|
||||
case Qt::SizeHintRole:
|
||||
if (column == ImageColumn) {
|
||||
return QSize(32, 32);
|
||||
}
|
||||
return {};
|
||||
case Qt::CheckStateRole:
|
||||
if (column == ActiveColumn) {
|
||||
return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked;
|
||||
|
@ -688,6 +688,7 @@ bool loadIconFile(const Mod& mod)
|
||||
return png_invalid(); // icon invalid
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case ResourceType::ZIPFILE: {
|
||||
QuaZip zip(mod.fileinfo().filePath());
|
||||
@ -714,6 +715,7 @@ bool loadIconFile(const Mod& mod)
|
||||
} else {
|
||||
return png_invalid(); // could not set icon as current file.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case ResourceType::LITEMOD: {
|
||||
return false; // can lightmods even have icons?
|
||||
|
@ -232,10 +232,9 @@ bool processPackPNG(const ResourcePack& pack)
|
||||
} else {
|
||||
return png_invalid(); // pack.png does not exists or is not a valid file.
|
||||
}
|
||||
return false; // not processed correctly; https://github.com/PrismLauncher/PrismLauncher/issues/1740
|
||||
}
|
||||
case ResourceType::ZIPFILE: {
|
||||
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
|
||||
|
||||
QuaZip zip(pack.fileinfo().filePath());
|
||||
if (!zip.open(QuaZip::mdUnzip))
|
||||
return false; // can't open zip file
|
||||
@ -259,6 +258,7 @@ bool processPackPNG(const ResourcePack& pack)
|
||||
} else {
|
||||
return png_invalid(); // could not set pack.mcmeta as current file.
|
||||
}
|
||||
return false; // not processed correctly; https://github.com/PrismLauncher/PrismLauncher/issues/1740
|
||||
}
|
||||
default:
|
||||
qWarning() << "Invalid type for resource pack parse task!";
|
||||
|
@ -186,10 +186,9 @@ bool processPackPNG(const TexturePack& pack)
|
||||
} else {
|
||||
return png_invalid(); // pack.png does not exists or is not a valid file.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case ResourceType::ZIPFILE: {
|
||||
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
|
||||
|
||||
QuaZip zip(pack.fileinfo().filePath());
|
||||
if (!zip.open(QuaZip::mdUnzip))
|
||||
return false; // can't open zip file
|
||||
@ -215,6 +214,7 @@ bool processPackPNG(const TexturePack& pack)
|
||||
zip.close();
|
||||
return png_invalid(); // could not set pack.mcmeta as current file.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
qWarning() << "Invalid type for resource pack parse task!";
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <QtNetwork/QtNetwork>
|
||||
#include "tasks/Task.h"
|
||||
|
||||
typedef shared_qobject_ptr<class SkinDelete> SkinDeletePtr;
|
||||
using SkinDeletePtr = shared_qobject_ptr<class SkinDelete>;
|
||||
|
||||
class SkinDelete : public Task {
|
||||
Q_OBJECT
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <memory>
|
||||
#include "tasks/Task.h"
|
||||
|
||||
typedef shared_qobject_ptr<class SkinUpload> SkinUploadPtr;
|
||||
using SkinUploadPtr = shared_qobject_ptr<class SkinUpload>;
|
||||
|
||||
class SkinUpload : public Task {
|
||||
Q_OBJECT
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "ATLPackInstallTask.h"
|
||||
|
||||
#include <QtConcurrent>
|
||||
#include <algorithm>
|
||||
|
||||
#include <quazip/quazip.h>
|
||||
|
||||
@ -50,6 +51,7 @@
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/OneSixVersionFormat.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "modplatform/atlauncher/ATLPackManifest.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
#include "settings/INISettingsObject.h"
|
||||
|
||||
@ -57,6 +59,7 @@
|
||||
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "ui/dialogs/BlockedModsDialog.h"
|
||||
|
||||
namespace ATLauncher {
|
||||
|
||||
@ -717,6 +720,8 @@ void PackInstallTask::downloadMods()
|
||||
|
||||
jarmods.clear();
|
||||
jobPtr.reset(new NetJob(tr("Mod download"), APPLICATION->network()));
|
||||
|
||||
QList<VersionMod> blocked_mods;
|
||||
for (const auto& mod : m_version.mods) {
|
||||
// skip non-client mods
|
||||
if (!mod.client)
|
||||
@ -731,9 +736,10 @@ void PackInstallTask::downloadMods()
|
||||
case DownloadType::Server:
|
||||
url = BuildConfig.ATL_DOWNLOAD_SERVER_URL + mod.url;
|
||||
break;
|
||||
case DownloadType::Browser:
|
||||
emitFailed(tr("Unsupported download type: %1").arg(mod.download_raw));
|
||||
return;
|
||||
case DownloadType::Browser: {
|
||||
blocked_mods.append(mod);
|
||||
continue;
|
||||
}
|
||||
case DownloadType::Direct:
|
||||
url = mod.url;
|
||||
break;
|
||||
@ -805,24 +811,86 @@ void PackInstallTask::downloadMods()
|
||||
modsToCopy[entry->getFullPath()] = path;
|
||||
}
|
||||
}
|
||||
if (!blocked_mods.isEmpty()) {
|
||||
QList<BlockedMod> mods;
|
||||
|
||||
for (auto mod : blocked_mods) {
|
||||
BlockedMod blocked_mod;
|
||||
blocked_mod.name = mod.file;
|
||||
blocked_mod.websiteUrl = mod.url;
|
||||
blocked_mod.hash = mod.md5;
|
||||
blocked_mod.matched = false;
|
||||
blocked_mod.localPath = "";
|
||||
|
||||
mods.append(blocked_mod);
|
||||
}
|
||||
|
||||
qWarning() << "Blocked mods found, displaying mod list";
|
||||
|
||||
BlockedModsDialog message_dialog(nullptr, tr("Blocked mods found"),
|
||||
tr("The following files are not available for download in third party launchers.<br/>"
|
||||
"You will need to manually download them and add them to the instance."),
|
||||
mods, "md5");
|
||||
|
||||
message_dialog.setModal(true);
|
||||
|
||||
if (message_dialog.exec()) {
|
||||
qDebug() << "Post dialog blocked mods list: " << mods;
|
||||
for (auto blocked : mods) {
|
||||
if (!blocked.matched) {
|
||||
qDebug() << blocked.name << "was not matched to a local file, skipping copy";
|
||||
continue;
|
||||
}
|
||||
auto modIter = std::find_if(blocked_mods.begin(), blocked_mods.end(),
|
||||
[blocked](const VersionMod& mod) { return mod.url == blocked.websiteUrl; });
|
||||
if (modIter == blocked_mods.end())
|
||||
continue;
|
||||
auto mod = *modIter;
|
||||
if (mod.type == ModType::Extract || mod.type == ModType::TexturePackExtract || mod.type == ModType::ResourcePackExtract) {
|
||||
modsToExtract.insert(blocked.localPath, mod);
|
||||
} else if (mod.type == ModType::Decomp) {
|
||||
modsToDecomp.insert(blocked.localPath, mod);
|
||||
} else {
|
||||
auto relpath = getDirForModType(mod.type, mod.type_raw);
|
||||
if (relpath == Q_NULLPTR)
|
||||
continue;
|
||||
|
||||
auto path = FS::PathCombine(m_stagingPath, "minecraft", relpath, mod.file);
|
||||
|
||||
if (mod.type == ModType::Forge) {
|
||||
auto ver = getComponentVersion("net.minecraftforge", mod.version);
|
||||
if (ver) {
|
||||
componentsToInstall.insert("net.minecraftforge", ver);
|
||||
continue;
|
||||
}
|
||||
|
||||
qDebug() << "Jarmod: " + path;
|
||||
jarmods.push_back(path);
|
||||
}
|
||||
|
||||
if (mod.type == ModType::Jar) {
|
||||
qDebug() << "Jarmod: " + path;
|
||||
jarmods.push_back(path);
|
||||
}
|
||||
|
||||
modsToCopy[blocked.localPath] = path;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
emitFailed(tr("Unknown download type: %1").arg("browser"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
connect(jobPtr.get(), &NetJob::succeeded, this, &PackInstallTask::onModsDownloaded);
|
||||
connect(jobPtr.get(), &NetJob::failed, [&](QString reason) {
|
||||
abortable = false;
|
||||
jobPtr.reset();
|
||||
emitFailed(reason);
|
||||
});
|
||||
connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) {
|
||||
connect(jobPtr.get(), &NetJob::progress, [this](qint64 current, qint64 total) {
|
||||
setDetails(tr("%1 out of %2 complete").arg(current).arg(total));
|
||||
abortable = true;
|
||||
setProgress(current, total);
|
||||
});
|
||||
connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress);
|
||||
connect(jobPtr.get(), &NetJob::aborted, [&] {
|
||||
abortable = false;
|
||||
jobPtr.reset();
|
||||
emitAborted();
|
||||
});
|
||||
connect(jobPtr.get(), &NetJob::aborted, &PackInstallTask::emitAborted);
|
||||
connect(jobPtr.get(), &NetJob::failed, &PackInstallTask::emitFailed);
|
||||
|
||||
jobPtr->start();
|
||||
}
|
||||
@ -843,7 +911,7 @@ void PackInstallTask::onModsDownloaded()
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), this, &PackInstallTask::extractMods, modsToExtract, modsToDecomp, modsToCopy);
|
||||
#endif
|
||||
connect(&m_modExtractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &PackInstallTask::onModsExtracted);
|
||||
connect(&m_modExtractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, [&]() { emitAborted(); });
|
||||
connect(&m_modExtractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &PackInstallTask::emitAborted);
|
||||
m_modExtractFutureWatcher.setFuture(m_modExtractFuture);
|
||||
} else {
|
||||
install();
|
||||
|
@ -208,17 +208,15 @@ Task::Ptr FlameAPI::getFile(const QString& addonId, const QString& fileId, std::
|
||||
return netJob;
|
||||
}
|
||||
|
||||
// https://docs.curseforge.com/?python#tocS_ModsSearchSortField
|
||||
static QList<ResourceAPI::SortingMethod> s_sorts = { { 1, "Featured", QObject::tr("Sort by Featured") },
|
||||
{ 2, "Popularity", QObject::tr("Sort by Popularity") },
|
||||
{ 3, "LastUpdated", QObject::tr("Sort by Last Updated") },
|
||||
{ 4, "Name", QObject::tr("Sort by Name") },
|
||||
{ 5, "Author", QObject::tr("Sort by Author") },
|
||||
{ 6, "TotalDownloads", QObject::tr("Sort by Downloads") },
|
||||
{ 7, "Category", QObject::tr("Sort by Category") },
|
||||
{ 8, "GameVersion", QObject::tr("Sort by Game Version") } };
|
||||
|
||||
QList<ResourceAPI::SortingMethod> FlameAPI::getSortingMethods() const
|
||||
{
|
||||
return s_sorts;
|
||||
// https://docs.curseforge.com/?python#tocS_ModsSearchSortField
|
||||
return { { 1, "Featured", QObject::tr("Sort by Featured") },
|
||||
{ 2, "Popularity", QObject::tr("Sort by Popularity") },
|
||||
{ 3, "LastUpdated", QObject::tr("Sort by Last Updated") },
|
||||
{ 4, "Name", QObject::tr("Sort by Name") },
|
||||
{ 5, "Author", QObject::tr("Sort by Author") },
|
||||
{ 6, "TotalDownloads", QObject::tr("Sort by Downloads") },
|
||||
{ 7, "Category", QObject::tr("Sort by Category") },
|
||||
{ 8, "GameVersion", QObject::tr("Sort by Game Version") } };
|
||||
}
|
||||
|
@ -568,7 +568,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
|
||||
m_mod_id_resolver.reset();
|
||||
connect(m_files_job.get(), &NetJob::succeeded, this, [&]() {
|
||||
m_files_job.reset();
|
||||
validateZIPResouces();
|
||||
validateZIPResources();
|
||||
});
|
||||
connect(m_files_job.get(), &NetJob::failed, [&](QString reason) {
|
||||
m_files_job.reset();
|
||||
@ -617,7 +617,7 @@ void FlameCreationTask::copyBlockedMods(QList<BlockedMod> const& blocked_mods)
|
||||
setAbortable(true);
|
||||
}
|
||||
|
||||
void FlameCreationTask::validateZIPResouces()
|
||||
void FlameCreationTask::validateZIPResources()
|
||||
{
|
||||
qDebug() << "Validating whether resources stored as .zip are in the right place";
|
||||
for (auto [fileName, targetFolder] : m_ZIP_resources) {
|
||||
@ -670,8 +670,8 @@ void FlameCreationTask::validateZIPResouces()
|
||||
validatePath(fileName, targetFolder, "datapacks");
|
||||
break;
|
||||
case PackedResourceType::ShaderPack:
|
||||
// in theroy flame API can't do this but who knows, that *may* change ?
|
||||
// better to handle it if it *does* occure in the future
|
||||
// in theory flame API can't do this but who knows, that *may* change ?
|
||||
// better to handle it if it *does* occur in the future
|
||||
validatePath(fileName, targetFolder, "shaderpacks");
|
||||
break;
|
||||
case PackedResourceType::WorldSave:
|
||||
|
@ -74,7 +74,7 @@ class FlameCreationTask final : public InstanceCreationTask {
|
||||
void idResolverSucceeded(QEventLoop&);
|
||||
void setupDownloadJob(QEventLoop&);
|
||||
void copyBlockedMods(QList<BlockedMod> const& blocked_mods);
|
||||
void validateZIPResouces();
|
||||
void validateZIPResources();
|
||||
QString getVersionForLoader(QString uid, QString loaderType, QString version, QString mcVersion);
|
||||
|
||||
private:
|
||||
|
@ -45,7 +45,7 @@ struct Modpack {
|
||||
QIcon icon;
|
||||
};
|
||||
|
||||
typedef QList<Modpack> ModpackList;
|
||||
using ModpackList = QList<Modpack>;
|
||||
|
||||
Modpack parseDirectory(QString path);
|
||||
|
||||
|
@ -31,7 +31,7 @@ struct Modpack {
|
||||
QString packCode;
|
||||
};
|
||||
|
||||
typedef QList<Modpack> ModpackList;
|
||||
using ModpackList = QList<Modpack>;
|
||||
|
||||
} // namespace LegacyFTB
|
||||
|
||||
|
@ -111,14 +111,12 @@ Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, std::shared_ptr<QByteAr
|
||||
return netJob;
|
||||
}
|
||||
|
||||
// https://docs.modrinth.com/api-spec/#tag/projects/operation/searchProjects
|
||||
static QList<ResourceAPI::SortingMethod> s_sorts = { { 1, "relevance", QObject::tr("Sort by Relevance") },
|
||||
{ 2, "downloads", QObject::tr("Sort by Downloads") },
|
||||
{ 3, "follows", QObject::tr("Sort by Follows") },
|
||||
{ 4, "newest", QObject::tr("Sort by Last Updated") },
|
||||
{ 5, "updated", QObject::tr("Sort by Newest") } };
|
||||
|
||||
QList<ResourceAPI::SortingMethod> ModrinthAPI::getSortingMethods() const
|
||||
{
|
||||
return s_sorts;
|
||||
// https://docs.modrinth.com/api-spec/#tag/projects/operation/searchProjects
|
||||
return { { 1, "relevance", QObject::tr("Sort by Relevance") },
|
||||
{ 2, "downloads", QObject::tr("Sort by Downloads") },
|
||||
{ 3, "follows", QObject::tr("Sort by Follows") },
|
||||
{ 4, "newest", QObject::tr("Sort by Newest") },
|
||||
{ 5, "updated", QObject::tr("Sort by Last Updated") } };
|
||||
}
|
||||
|
@ -36,11 +36,16 @@
|
||||
*/
|
||||
|
||||
#include "NetJob.h"
|
||||
#if defined(LAUNCHER_APPLICATION)
|
||||
#include "Application.h"
|
||||
#endif
|
||||
|
||||
NetJob::NetJob(QString job_name, shared_qobject_ptr<QNetworkAccessManager> network)
|
||||
: ConcurrentTask(nullptr, job_name, APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()), m_network(network)
|
||||
{}
|
||||
NetJob::NetJob(QString job_name, shared_qobject_ptr<QNetworkAccessManager> network) : ConcurrentTask(nullptr, job_name), m_network(network)
|
||||
{
|
||||
#if defined(LAUNCHER_APPLICATION)
|
||||
setMaxConcurrent(APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt());
|
||||
#endif
|
||||
}
|
||||
|
||||
auto NetJob::addNetAction(NetAction::Ptr action) -> bool
|
||||
{
|
||||
|
@ -46,6 +46,7 @@
|
||||
#if defined(LAUNCHER_APPLICATION)
|
||||
#include "Application.h"
|
||||
#endif
|
||||
#include "BuildConfig.h"
|
||||
|
||||
#include "net/NetAction.h"
|
||||
|
||||
@ -111,6 +112,8 @@ void NetRequest::executeTask()
|
||||
m_last_progress_bytes = 0;
|
||||
|
||||
QNetworkReply* rep = getReply(request);
|
||||
if (rep == nullptr) // it failed
|
||||
return;
|
||||
m_reply.reset(rep);
|
||||
connect(rep, &QNetworkReply::downloadProgress, this, &NetRequest::downloadProgress);
|
||||
connect(rep, &QNetworkReply::finished, this, &NetRequest::downloadFinished);
|
||||
|
@ -87,7 +87,7 @@ class NetRequest : public NetAction {
|
||||
std::unique_ptr<Sink> m_sink;
|
||||
Options m_options;
|
||||
|
||||
typedef const QLoggingCategory& (*logCatFunc)();
|
||||
using logCatFunc = const QLoggingCategory& (*)();
|
||||
logCatFunc logCat = taskUploadLogC;
|
||||
|
||||
std::chrono::steady_clock m_clock;
|
||||
|
39
launcher/net/StaticHeaderProxy.h
Normal file
@ -0,0 +1,39 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "net/HeaderProxy.h"
|
||||
|
||||
namespace Net {
|
||||
|
||||
class StaticHeaderProxy : public HeaderProxy {
|
||||
public:
|
||||
StaticHeaderProxy(QList<HeaderPair> hdrs = {}) : HeaderProxy(), m_hdrs(hdrs){};
|
||||
virtual ~StaticHeaderProxy() = default;
|
||||
|
||||
public:
|
||||
virtual QList<HeaderPair> headers(const QNetworkRequest&) const override { return m_hdrs; };
|
||||
void setHeaders(QList<HeaderPair> hdrs) { m_hdrs = hdrs; };
|
||||
|
||||
private:
|
||||
QList<HeaderPair> m_hdrs;
|
||||
};
|
||||
|
||||
} // namespace Net
|
@ -51,4 +51,4 @@ class NewsEntry : public QObject {
|
||||
QString link;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<NewsEntry> NewsEntryPtr;
|
||||
using NewsEntryPtr = std::shared_ptr<NewsEntry>;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
class IPathMatcher {
|
||||
public:
|
||||
typedef std::shared_ptr<IPathMatcher> Ptr;
|
||||
using Ptr = std::shared_ptr<IPathMatcher>;
|
||||
|
||||
public:
|
||||
virtual ~IPathMatcher() {}
|
||||
|
@ -9,6 +9,7 @@
|
||||
<file>scalable/copy.svg</file>
|
||||
<file>scalable/coremods.svg</file>
|
||||
<file>scalable/custom-commands.svg</file>
|
||||
<file>scalable/environment-variables.svg</file>
|
||||
<file>scalable/discord.svg</file>
|
||||
<file>scalable/externaltools.svg</file>
|
||||
<file>scalable/help.svg</file>
|
||||
|
@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs id="defs3051">
|
||||
<style type="text/css" id="current-color-scheme">
|
||||
.ColorScheme-Text {
|
||||
color:#eff0f1;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path style="fill:currentColor;fill-opacity:1;stroke:none"
|
||||
d="M 6 2 C 4.895478 2 4 2.8954778 4 4 L 4 6 L 4 7 C 4 7.2761493 3.7761423 7.5 3.5 7.5 L 3 7.5 L 3 8.5 L 3.5 8.5 C 3.7761423 8.5 4 8.7238507 4 9 L 4 10 L 4 11 L 4 12 C 4 13.104597 4.8954307 14 6 14 L 7 14 L 7 13 L 6 13 C 5.4477157 13 5 12.552299 5 12 L 5 11 L 5 10 L 5 9 C 5 8.617501 4.8607153 8.2649743 4.625 8 C 4.8607153 7.7350257 5 7.382499 5 7 L 5 6 L 5 5.71875 L 5 4 C 5 3.4477014 5.4477765 3 6 3 L 7 3 L 7 2 L 6 2 z M 9 2 L 9 3 L 10 3 C 10.552224 3 11 3.4477014 11 4 L 11 5.71875 L 11 6 L 11 7 C 11 7.382499 11.139285 7.7350257 11.375 8 C 11.139285 8.2649743 11 8.617501 11 9 L 11 10 L 11 11 L 11 12 C 11 12.552299 10.552284 13 10 13 L 9 13 L 9 14 L 10 14 C 11.104569 14 12 13.104597 12 12 L 12 11 L 12 10 L 12 9 C 12 8.7238507 12.223858 8.5 12.5 8.5 L 13 8.5 L 13 7.5 L 12.5 7.5 C 12.223858 7.5 12 7.2761493 12 7 L 12 6 L 12 4 C 12 2.8954778 11.104522 2 10 2 L 9 2 z "
|
||||
class="ColorScheme-Text"
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -9,6 +9,7 @@
|
||||
<file>scalable/copy.svg</file>
|
||||
<file>scalable/coremods.svg</file>
|
||||
<file>scalable/custom-commands.svg</file>
|
||||
<file>scalable/environment-variables.svg</file>
|
||||
<file>scalable/discord.svg</file>
|
||||
<file>scalable/externaltools.svg</file>
|
||||
<file>scalable/help.svg</file>
|
||||
|
@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs id="defs3051">
|
||||
<style type="text/css" id="current-color-scheme">
|
||||
.ColorScheme-Text {
|
||||
color:#232629;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path style="fill:currentColor;fill-opacity:1;stroke:none"
|
||||
d="M 6 2 C 4.895478 2 4 2.8954778 4 4 L 4 6 L 4 7 C 4 7.2761493 3.7761423 7.5 3.5 7.5 L 3 7.5 L 3 8.5 L 3.5 8.5 C 3.7761423 8.5 4 8.7238507 4 9 L 4 10 L 4 11 L 4 12 C 4 13.104597 4.8954307 14 6 14 L 7 14 L 7 13 L 6 13 C 5.4477157 13 5 12.552299 5 12 L 5 11 L 5 10 L 5 9 C 5 8.617501 4.8607153 8.2649743 4.625 8 C 4.8607153 7.7350257 5 7.382499 5 7 L 5 6 L 5 5.71875 L 5 4 C 5 3.4477014 5.4477765 3 6 3 L 7 3 L 7 2 L 6 2 z M 9 2 L 9 3 L 10 3 C 10.552224 3 11 3.4477014 11 4 L 11 5.71875 L 11 6 L 11 7 C 11 7.382499 11.139285 7.7350257 11.375 8 C 11.139285 8.2649743 11 8.617501 11 9 L 11 10 L 11 11 L 11 12 C 11 12.552299 10.552284 13 10 13 L 9 13 L 9 14 L 10 14 C 11.104569 14 12 13.104597 12 12 L 12 11 L 12 10 L 12 9 C 12 8.7238507 12.223858 8.5 12.5 8.5 L 13 8.5 L 13 7.5 L 12.5 7.5 C 12.223858 7.5 12 7.2761493 12 7 L 12 6 L 12 4 C 12 2.8954778 11.104522 2 10 2 L 9 2 z "
|
||||
class="ColorScheme-Text"
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -11,6 +11,7 @@
|
||||
<file>scalable/copy.svg</file>
|
||||
<file>scalable/coremods.svg</file>
|
||||
<file>scalable/custom-commands.svg</file>
|
||||
<file>scalable/environment-variables.svg</file>
|
||||
<file>scalable/discord.svg</file>
|
||||
<file>scalable/externaltools.svg</file>
|
||||
<file>scalable/help.svg</file>
|
||||
|
@ -1,86 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
fill="#757575"
|
||||
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>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#757575"><g><rect fill="none" height="24" width="24"/></g><g><path d="M20,4H4C2.89,4,2,4.9,2,6v12c0,1.1,0.89,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.11,4,20,4z M20,18H4V8h16V18z M18,17h-6v-2 h6V17z M7.5,17l-1.41-1.41L8.67,13l-2.59-2.59L7.5,9l4,4L7.5,17z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 391 B |
86
launcher/resources/flat/scalable/environment-variables.svg
Normal file
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
fill="#757575"
|
||||
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>
|
After Width: | Height: | Size: 2.6 KiB |
@ -11,6 +11,7 @@
|
||||
<file>scalable/copy.svg</file>
|
||||
<file>scalable/coremods.svg</file>
|
||||
<file>scalable/custom-commands.svg</file>
|
||||
<file>scalable/environment-variables.svg</file>
|
||||
<file>scalable/discord.svg</file>
|
||||
<file>scalable/externaltools.svg</file>
|
||||
<file>scalable/help.svg</file>
|
||||
|
@ -1,86 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
fill="#eeeeee"
|
||||
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>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#eeeeee"><g><rect fill="none" height="24" width="24"/></g><g><path d="M20,4H4C2.89,4,2,4.9,2,6v12c0,1.1,0.89,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.11,4,20,4z M20,18H4V8h16V18z M18,17h-6v-2 h6V17z M7.5,17l-1.41-1.41L8.67,13l-2.59-2.59L7.5,9l4,4L7.5,17z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 391 B |
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
fill="#eeeeee"
|
||||
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>
|
After Width: | Height: | Size: 2.6 KiB |
@ -73,8 +73,8 @@
|
||||
<file>64x64/screenshots.png</file>
|
||||
<file>scalable/screenshots.svg</file>
|
||||
|
||||
<!-- Custom commands. -->
|
||||
<file>scalable/custom-commands.svg</file>
|
||||
<file>scalable/environment-variables.svg</file>
|
||||
|
||||
<!-- The cat button. Freeware, http://findicons.com/icon/73096/black_cat -->
|
||||
<file>16x16/cat.png</file>
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 113 KiB |
346
launcher/resources/multimc/scalable/environment-variables.svg
Normal file
@ -0,0 +1,346 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="128"
|
||||
height="128"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.47pre3 r22311"
|
||||
version="1.0"
|
||||
sodipodi:docname="code-context.svgz"
|
||||
inkscape:output_extension="org.inkscape.output.svgz.inkscape"
|
||||
inkscape:export-filename="/home/pinheiro/pics/oxygen-icons/scalable/actions/small/48x48/context.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5440">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5442" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5444" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5342">
|
||||
<stop
|
||||
style="stop-color:#232221;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5344" />
|
||||
<stop
|
||||
id="stop5394"
|
||||
offset="0.10646833"
|
||||
style="stop-color:#555350;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#918d88;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop5346" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3857"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop3859"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3861"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5342"
|
||||
id="linearGradient5348"
|
||||
x1="80.151077"
|
||||
y1="-120.00011"
|
||||
x2="80.151077"
|
||||
y2="-15.919633"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.85712143,0,0,0.85712149,15.99961,-9.1458159)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3857"
|
||||
id="linearGradient5378"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.85712141,0,0,-0.85442216,15.99961,9.407114)"
|
||||
x1="76"
|
||||
y1="-4"
|
||||
x2="76"
|
||||
y2="-124" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3857"
|
||||
id="radialGradient5386"
|
||||
cx="64"
|
||||
cy="136"
|
||||
fx="64"
|
||||
fy="136"
|
||||
r="48"
|
||||
gradientTransform="matrix(1.3086619,0,0,0.65227042,-19.755964,19.661784)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter5416"
|
||||
x="-0.21917803"
|
||||
width="1.4383561"
|
||||
y="-0.21917814"
|
||||
height="1.4383563">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="1.4611876"
|
||||
id="feGaussianBlur5418" />
|
||||
</filter>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath5420">
|
||||
<path
|
||||
style="fill:url(#radialGradient5424);fill-opacity:1;stroke:none"
|
||||
d="m 108,8 c -52,0 -36,4 0,4 3.57143,0 8,2.700959 8,8 0,24 4,24 4,0 0,-5.923499 -4.70207,-12 -12,-12 z"
|
||||
id="path5422"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</clipPath>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3857"
|
||||
id="radialGradient5424"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.70743936,0.70677405,-0.99807448,0.99901401,48.73805,-79.148369)"
|
||||
cx="112.00771"
|
||||
cy="15.99981"
|
||||
fx="112.00771"
|
||||
fy="15.99981"
|
||||
r="8.0077057" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3857"
|
||||
id="radialGradient5426"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.70727305,0.70694048,-1.9971123,1.9980518,64.741093,-95.151426)"
|
||||
cx="112.00771"
|
||||
cy="15.99981"
|
||||
fx="112.00771"
|
||||
fy="15.99981"
|
||||
r="8.0077057" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3857"
|
||||
id="radialGradient5430"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.70727305,0.70694048,-1.9971123,1.9980518,64.741093,-95.151426)"
|
||||
cx="112.00771"
|
||||
cy="15.99981"
|
||||
fx="112.00771"
|
||||
fy="15.99981"
|
||||
r="8.0077057" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3857"
|
||||
id="radialGradient5436"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.70727305,0.70694048,-1.9971123,1.9980518,64.741093,-95.151426)"
|
||||
cx="112.00771"
|
||||
cy="15.99981"
|
||||
fx="112.00771"
|
||||
fy="15.99981"
|
||||
r="8.0077057" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3857"
|
||||
id="radialGradient5438"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.70727305,0.70694048,-1.9971123,1.9980518,64.741093,-95.151426)"
|
||||
cx="112.00771"
|
||||
cy="15.99981"
|
||||
fx="112.00771"
|
||||
fy="15.99981"
|
||||
r="8.0077057" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5440"
|
||||
id="linearGradient5451"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="71.937897"
|
||||
y1="31.666744"
|
||||
x2="71.937897"
|
||||
y2="184.00002"
|
||||
gradientTransform="matrix(0.49730883,0,0,0.49574271,32.172236,26.323555)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3857"
|
||||
id="linearGradient5453"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.85712141,0,0,-0.85442216,15.99961,9.25759)"
|
||||
x1="76"
|
||||
y1="-8"
|
||||
x2="76"
|
||||
y2="-72.117546" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3857"
|
||||
id="radialGradient5480"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.70727305,0.70694048,-1.9971123,1.9980518,64.741093,-95.151426)"
|
||||
cx="112.00771"
|
||||
cy="15.99981"
|
||||
fx="112.00771"
|
||||
fy="15.99981"
|
||||
r="8.0077057" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3857"
|
||||
id="radialGradient5482"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.70727305,0.70694048,-1.9971123,1.9980518,64.741093,-95.151426)"
|
||||
cx="112.00771"
|
||||
cy="15.99981"
|
||||
fx="112.00771"
|
||||
fy="15.99981"
|
||||
r="8.0077057" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
gridtolerance="10000"
|
||||
guidetolerance="10"
|
||||
objecttolerance="10"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.4029514"
|
||||
inkscape:cx="135.41032"
|
||||
inkscape:cy="66.337315"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
width="128px"
|
||||
height="128px"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1040"
|
||||
inkscape:window-height="728"
|
||||
inkscape:window-x="374"
|
||||
inkscape:window-y="333"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:window-maximized="0">
|
||||
<inkscape:grid
|
||||
id="GridFromPre046Settings"
|
||||
type="xygrid"
|
||||
originx="0px"
|
||||
originy="0px"
|
||||
spacingx="2.6666px"
|
||||
spacingy="2.6666px"
|
||||
color="#0000ff"
|
||||
empcolor="#0000ff"
|
||||
opacity="0.2"
|
||||
empopacity="0.4"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:url(#linearGradient5348);fill-opacity:1;stroke:none"
|
||||
id="rect3888"
|
||||
width="95.997589"
|
||||
height="95.997597"
|
||||
x="15.999609"
|
||||
y="-112.0004"
|
||||
rx="10.285457"
|
||||
ry="10.285458"
|
||||
transform="scale(1,-1)" />
|
||||
<path
|
||||
style="opacity:0.60465118;fill:url(#linearGradient5453);fill-opacity:1;stroke:none"
|
||||
d="m 25.485068,18.710656 c -3.798763,0 -6.856972,3.048578 -6.856972,6.835377 l 0.8,37.219744 c 6.539821,0.759062 16.86475,1.174831 23.9994,1.174831 25.561145,0 52.250262,-5.22011 65.841214,-13.190143 l 0,-25.104432 c 0,-3.786799 -3.05819,-6.835377 -6.85697,-6.835377 l -76.926672,-0.1 z"
|
||||
id="rect5352"
|
||||
sodipodi:nodetypes="cccscccc" />
|
||||
<path
|
||||
style="font-size:113.80991364px;fill:url(#linearGradient5451);fill-opacity:1"
|
||||
d="m 56.043058,38.22138 c -4.502355,0.02208 -8.022848,0.601203 -9.573194,1.921002 -1.562598,1.327923 -2.331149,4.004842 -2.331134,8.024838 l 0,6.537605 c -1.5e-5,2.710357 -0.456344,4.708001 -1.460845,5.763007 -0.985927,1.036861 -2.157584,1.549216 -4.817681,1.549196 l -1.7095,0 0,3.965943 1.7095,0 c 2.641495,1.6e-5 3.81315,0.463195 4.817681,1.518211 1.004501,1.055044 1.46083,2.861382 1.460845,5.608091 l 0,2.556172 c -1.5e-5,4.020026 0.768536,10.660189 2.331134,12.006269 1.550346,1.319827 5.070839,2.077935 9.573194,2.106906 l 0,-3.965941 c -2.581373,-0.01061 -5.752521,-0.464158 -6.54272,-1.254849 -0.799914,-0.800372 -1.19667,-6.451506 -1.196649,-9.016319 l 0,-2.788555 C 48.303668,69.915298 47.928575,67.94064 47.091497,66.649126 46.254384,65.357638 45.51975,64.49115 43.454931,64 c 2.046218,-0.454739 2.768369,-1.342112 3.605484,-2.633634 0.855681,-1.291479 1.243253,-3.464838 1.243274,-6.32072 l 0,-6.769983 c -2.1e-5,-2.564784 0.396735,-4.249978 1.196649,-5.050381 0.790199,-0.790653 3.961347,-1.030684 6.54272,-1.037961 l 0,-3.965941 z m 15.913882,0 0,3.965941 c 2.581375,0.0072 5.752523,0.247308 6.542722,1.037961 0.799912,0.800403 1.19667,2.485597 1.196648,5.050381 l 0,6.769983 c 2.2e-5,2.855882 0.387593,5.029241 1.243273,6.32072 0.837117,1.291522 1.55927,2.178895 3.605488,2.633634 -2.064821,0.49115 -2.799455,1.357638 -3.636568,2.649126 -0.837078,1.291514 -1.212171,3.266172 -1.212193,6.10383 l 0,2.788555 c 2.2e-5,2.564813 -0.396736,8.215947 -1.196648,9.016319 -0.790199,0.790691 -3.961347,1.244092 -6.542722,1.254849 l 0,3.965941 c 4.502355,-0.02897 8.02285,-0.787079 9.573197,-2.106906 1.562597,-1.34608 2.33115,-7.986243 2.331135,-12.006269 l 0,-2.556172 c 1.5e-5,-2.746709 0.456342,-4.553047 1.460846,-5.608091 1.004528,-1.055016 2.176183,-1.518195 4.817678,-1.518211 l 1.7095,0 0,-3.965943 -1.7095,0 c -2.660094,2e-5 -3.831749,-0.512335 -4.817678,-1.549196 -1.004504,-1.055006 -1.460831,-3.05265 -1.460846,-5.763007 l 0,-6.537605 c 1.5e-5,-4.019996 -0.768538,-6.696915 -2.331135,-8.024838 C 79.97979,38.822583 76.459295,38.243453 71.95694,38.22138 z"
|
||||
id="path3006"
|
||||
sodipodi:nodetypes="csccsccccscccccsccsccccsccccsccccsccscccccsccccsccsc" />
|
||||
<path
|
||||
style="fill:url(#linearGradient5378);fill-opacity:1;stroke:none"
|
||||
d="m 107.87589,25.774638 c 0.72539,1.084602 1.12497,2.38464 1.12497,3.791498 l 0,20.986745 c -13.590951,7.970031 -40.28007,13.190143 -65.841216,13.190143 -7.038772,0 -13.841689,-0.408385 -20.303062,-1.148132 l 0,0.320409 c 6.539821,0.759061 13.436264,1.17483 20.570914,1.17483 25.561145,0 52.250262,-5.22011 65.841214,-13.19014 l 0,-20.986745 c 0,-1.559831 -0.517,-2.990759 -1.39282,-4.138608 z"
|
||||
id="path5369"
|
||||
sodipodi:nodetypes="cccsccsccc" />
|
||||
<path
|
||||
id="path5380"
|
||||
d="m 25.485068,109.37056 c -3.798763,0 -6.856972,-3.04858 -6.856972,-6.83539 l 0,-33.002043 c 6.539821,-0.759061 13.436266,-1.174829 20.570912,-1.174829 25.561149,0 56.57875,-25.058477 70.169702,-17.088444 l 0,51.265316 c 0,3.78681 -3.05819,6.83539 -6.85697,6.83539 l -77.026672,0 z"
|
||||
style="opacity:0.4;fill:url(#radialGradient5386);fill-opacity:1;stroke:none"
|
||||
sodipodi:nodetypes="cccscccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="path5414"
|
||||
d="m 108,8 -4,8 c 3.30365,-0.176594 7.9579,2.481149 8,8 l 8,-4 C 120.007,14.388483 115.55603,8.131068 108,8 z"
|
||||
style="fill:url(#radialGradient5426);fill-opacity:1;stroke:none;filter:url(#filter5416)"
|
||||
clip-path="url(#clipPath5420)"
|
||||
transform="matrix(0.85712141,0,0,0.85442216,9.142639,9.25759)" />
|
||||
<path
|
||||
clip-path="url(#clipPath5420)"
|
||||
style="fill:url(#radialGradient5430);fill-opacity:1;stroke:none;filter:url(#filter5416)"
|
||||
d="m 108,8 -4,8 c 3.30365,-0.176594 7.9579,2.481149 8,8 l 8,-4 C 120.007,14.388483 115.55603,8.131068 108,8 z"
|
||||
id="path5428"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
transform="matrix(-0.85712141,0,0,0.85442216,118.85417,9.25759)" />
|
||||
<path
|
||||
clip-path="url(#clipPath5420)"
|
||||
style="opacity:0.52558139;fill:url(#radialGradient5436);fill-opacity:1;stroke:none;filter:url(#filter5416)"
|
||||
d="m 108,8 -4,8 c 3.30365,-0.176594 7.9579,2.481149 8,8 l 8,-4 C 120.007,14.388483 115.55603,8.131068 108,8 z"
|
||||
id="path5432"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
transform="matrix(0.85712141,0,0,-0.85442216,9.142639,118.83578)" />
|
||||
<path
|
||||
transform="matrix(-0.85712141,0,0,-0.85442216,118.85417,118.83578)"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="path5434"
|
||||
d="m 108,8 -4,8 c 3.30365,-0.176594 7.9579,2.481149 8,8 l 8,-4 C 120.007,14.388483 115.55603,8.131068 108,8 z"
|
||||
style="opacity:0.52558139;fill:url(#radialGradient5438);fill-opacity:1;stroke:none;filter:url(#filter5416)"
|
||||
clip-path="url(#clipPath5420)" />
|
||||
<path
|
||||
clip-path="url(#clipPath5420)"
|
||||
style="fill:url(#radialGradient5482);fill-opacity:1;stroke:none;filter:url(#filter5416)"
|
||||
d="m 108,8 -4,8 c 3.30365,-0.176594 7.9579,2.481149 8,8 l 8,-4 C 120.007,14.388483 115.55603,8.131068 108,8 z"
|
||||
id="path5455"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
transform="matrix(0.85712141,0,0,0.85442216,9.142639,9.25759)" />
|
||||
<path
|
||||
transform="matrix(-0.85712141,0,0,0.85442216,118.85417,9.25759)"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="path5457"
|
||||
d="m 108,8 -4,8 c 3.30365,-0.176594 7.9579,2.481149 8,8 l 8,-4 C 120.007,14.388483 115.55603,8.131068 108,8 z"
|
||||
style="fill:url(#radialGradient5480);fill-opacity:1;stroke:none;filter:url(#filter5416)"
|
||||
clip-path="url(#clipPath5420)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 14 KiB |
@ -10,6 +10,7 @@
|
||||
<file>scalable/copy.svg</file>
|
||||
<file>scalable/coremods.svg</file>
|
||||
<file>scalable/custom-commands.svg</file>
|
||||
<file>scalable/environment-variables.svg</file>
|
||||
<file>scalable/externaltools.svg</file>
|
||||
<file>scalable/help.svg</file>
|
||||
<file>scalable/instance-settings.svg</file>
|
||||
|
345
launcher/resources/pe_blue/scalable/environment-variables.svg
Normal file
@ -0,0 +1,345 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
id="svg2"
|
||||
height="32"
|
||||
width="32"
|
||||
version="1.1"
|
||||
sodipodi:docname="environment-variables.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
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/">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#505050"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
id="namedview52"
|
||||
showgrid="false"
|
||||
inkscape:zoom="7.375"
|
||||
inkscape:cx="21.559322"
|
||||
inkscape:cy="-2.9830509"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#505050">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid858" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient3931">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
id="stop3933" />
|
||||
<stop
|
||||
offset="0.69999987"
|
||||
style="stop-color:#ffffff;stop-opacity:0.10396039"
|
||||
id="stop3939" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0.14356436"
|
||||
id="stop3935" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3900">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#f6f6f6;stop-opacity:1"
|
||||
id="stop3902" />
|
||||
<stop
|
||||
offset="0.75714284"
|
||||
style="stop-color:#494949;stop-opacity:1"
|
||||
id="stop3904" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#2c2c2c;stop-opacity:1"
|
||||
id="stop3906" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3808">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#333333;stop-opacity:1"
|
||||
id="stop3810" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#c8c8c8;stop-opacity:1"
|
||||
id="stop3812" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3030">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1"
|
||||
id="stop3032" />
|
||||
<stop
|
||||
offset="0.75714284"
|
||||
style="stop-color:#333333;stop-opacity:1"
|
||||
id="stop3038" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#4d4d4d;stop-opacity:1"
|
||||
id="stop3034" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
gradientTransform="matrix(0.67596238,0.94191445,-0.76796117,0.55112488,7.7178628,-19.890271)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3030"
|
||||
id="radialGradient3036"
|
||||
fy="14.242621"
|
||||
fx="29.381905"
|
||||
r="16.375"
|
||||
cy="14.242621"
|
||||
cx="29.381905" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.5,0,0,1,-16,4)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3808"
|
||||
id="linearGradient3824"
|
||||
y2="1033.8622"
|
||||
x2="34"
|
||||
y1="1033.8622"
|
||||
x1="30" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(0.82142857,0,0,1.500001,6.7142857,-522.68214)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3808"
|
||||
id="linearGradient3834"
|
||||
y2="1039.3622"
|
||||
x2="32"
|
||||
y1="1043.3622"
|
||||
x1="32" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(6.479993,1.9525666,-10.415476,2.1794781,10657.845,-1282.8793)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3844"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(2.5191507,2.9862959,-4.0491019,3.333339,4186.8847,-2518.44)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3852"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(-2.5191507,2.9863064,4.0491022,3.3333507,-4122.8849,-2518.4524)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3857"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(-0.69414478,2.3073251,-1.6952184,-0.67174747,96.941544,960.82172)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3937"
|
||||
fy="21.976955"
|
||||
fx="31.946348"
|
||||
r="19.25"
|
||||
cy="21.976955"
|
||||
cx="31.946348" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fill="#3366cc"
|
||||
d="M 26,32 H 6 C 2.7,32 0,29.3 0,26 V 6 C 0,2.7 2.7,0 6,0 h 20 c 3.3,0 6,2.7 6,6 v 20 c 0,3.3 -2.7,6 -6,6 z"
|
||||
id="path2" />
|
||||
<path
|
||||
fill="#daeeff"
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M 28,6 C 28,4.9 27.1,4 26,4 H 6 C 4.9,4 4,4.9 4,6 v 20 c 0,1.1 0.9,2 2,2 h 20 c 1.1,0 2,-0.9 2,-2 z"
|
||||
id="path4" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g869"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g871"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g873"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g875"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g877"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g879"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g881"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g883"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g885"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g887"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g889"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g891"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g893"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g895"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g897"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
id="g856"
|
||||
style="fill:#c1272d;fill-opacity:1"
|
||||
transform="matrix(0.0361121,0,0,0.0361121,6.5218379,6.0218363)">
|
||||
<g
|
||||
id="g854"
|
||||
style="fill:#c1272d;fill-opacity:1">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path850"
|
||||
d="m -14.4505,276.30781 c 0,-6.995 2.705,-13.403 7.846,-18.556 l 156.788,-156.782 c 5.128,-5.140997 11.554,-7.851997 18.568,-7.851997 7.026,0 13.452,2.717 18.556,7.845997 l 16.83,16.83 c 5.129,5.135 7.84,11.549 7.84,18.538 0,7.026 -2.717,13.452 -7.846,18.556 l -121.415001,121.42 121.427001,121.433 c 5.129,5.135 7.84,11.555 7.84,18.55 0,7.02 -2.717,13.439 -7.846,18.544 l -16.775,16.774 c -5.116,5.165 -11.555,7.895 -18.611,7.895 -7.044,0 -13.47,-2.723 -18.556,-7.846 l -156.813,-156.8 c -5.128,-5.14 -7.833,-11.549 -7.833,-18.55 z"
|
||||
style="fill:#c1272d;fill-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path322"
|
||||
d="m 539.38069,276.30781 c 0,-6.995 -2.705,-13.403 -7.846,-18.556 l -156.788,-156.782 c -5.128,-5.140997 -11.554,-7.851997 -18.568,-7.851997 -7.026,0 -13.452,2.717 -18.556,7.845997 l -16.83,16.83 c -5.129,5.135 -7.84,11.549 -7.84,18.538 0,7.026 2.717,13.452 7.846,18.556 l 121.415,121.42 -121.427,121.433 c -5.129,5.135 -7.84,11.555 -7.84,18.55 0,7.02 2.717,13.439 7.846,18.544 l 16.775,16.774 c 5.116,5.165 11.555,7.895 18.611,7.895 7.044,0 13.47,-2.723 18.556,-7.846 l 156.813,-156.8 c 5.128,-5.14 7.833,-11.549 7.833,-18.55 z"
|
||||
style="fill:#c1272d;fill-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g858"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g860"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g862"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g864"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g866"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g868"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g870"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g872"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g874"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g876"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g878"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g880"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g882"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g884"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g886"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g12">
|
||||
<path
|
||||
id="path6"
|
||||
d="m 6,28 h 20 c 1.1,0 2,-0.9 2,-2 V 9 6 C 28,4.9 27.1,4 26,4 H 6 C 4.9,4 4,4.9 4,6 v 3 17 c 0,1.1 0.9,2 2,2 z"
|
||||
fill="none" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
@ -10,6 +10,7 @@
|
||||
<file>scalable/copy.svg</file>
|
||||
<file>scalable/coremods.svg</file>
|
||||
<file>scalable/custom-commands.svg</file>
|
||||
<file>scalable/environment-variables.svg</file>
|
||||
<file>scalable/externaltools.svg</file>
|
||||
<file>scalable/help.svg</file>
|
||||
<file>scalable/instance-settings.svg</file>
|
||||
|
347
launcher/resources/pe_colored/scalable/environment-variables.svg
Normal file
@ -0,0 +1,347 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
id="svg2"
|
||||
height="32"
|
||||
width="32"
|
||||
version="1.1"
|
||||
sodipodi:docname="environment-variables.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
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/">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#505050"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
id="namedview52"
|
||||
showgrid="false"
|
||||
inkscape:zoom="10.429825"
|
||||
inkscape:cx="3.4995793"
|
||||
inkscape:cy="11.793103"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#505050">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid858" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient3931">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
id="stop3933" />
|
||||
<stop
|
||||
offset="0.69999987"
|
||||
style="stop-color:#ffffff;stop-opacity:0.10396039"
|
||||
id="stop3939" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0.14356436"
|
||||
id="stop3935" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3900">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#f6f6f6;stop-opacity:1"
|
||||
id="stop3902" />
|
||||
<stop
|
||||
offset="0.75714284"
|
||||
style="stop-color:#494949;stop-opacity:1"
|
||||
id="stop3904" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#2c2c2c;stop-opacity:1"
|
||||
id="stop3906" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3808">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#333333;stop-opacity:1"
|
||||
id="stop3810" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#c8c8c8;stop-opacity:1"
|
||||
id="stop3812" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3030">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1"
|
||||
id="stop3032" />
|
||||
<stop
|
||||
offset="0.75714284"
|
||||
style="stop-color:#333333;stop-opacity:1"
|
||||
id="stop3038" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#4d4d4d;stop-opacity:1"
|
||||
id="stop3034" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
gradientTransform="matrix(0.67596238,0.94191445,-0.76796117,0.55112488,7.7178628,-19.890271)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3030"
|
||||
id="radialGradient3036"
|
||||
fy="14.242621"
|
||||
fx="29.381905"
|
||||
r="16.375"
|
||||
cy="14.242621"
|
||||
cx="29.381905" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.5,0,0,1,-16,4)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3808"
|
||||
id="linearGradient3824"
|
||||
y2="1033.8622"
|
||||
x2="34"
|
||||
y1="1033.8622"
|
||||
x1="30" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(0.82142857,0,0,1.500001,6.7142857,-522.68214)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3808"
|
||||
id="linearGradient3834"
|
||||
y2="1039.3622"
|
||||
x2="32"
|
||||
y1="1043.3622"
|
||||
x1="32" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(6.479993,1.9525666,-10.415476,2.1794781,10657.845,-1282.8793)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3844"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(2.5191507,2.9862959,-4.0491019,3.333339,4186.8847,-2518.44)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3852"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(-2.5191507,2.9863064,4.0491022,3.3333507,-4122.8849,-2518.4524)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3857"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(-0.69414478,2.3073251,-1.6952184,-0.67174747,96.941544,960.82172)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3937"
|
||||
fy="21.976955"
|
||||
fx="31.946348"
|
||||
r="19.25"
|
||||
cy="21.976955"
|
||||
cx="31.946348" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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>
|
||||
<path
|
||||
id="path2"
|
||||
d="M 28,6 C 28,4.9 27.1,4 26,4 H 6 C 4.9,4 4,4.9 4,6 v 20 c 0,1.1 0.9,2 2,2 h 20 c 1.1,0 2,-0.9 2,-2 z"
|
||||
fill="#f2f2f2"
|
||||
clip-rule="evenodd"
|
||||
fill-rule="evenodd" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g869"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g871"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g873"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g875"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g877"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g879"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g881"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g883"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g885"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g887"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g889"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g891"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g893"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g895"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g897"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
id="g856"
|
||||
style="fill:#c1272d;fill-opacity:1"
|
||||
transform="matrix(0.0361121,0,0,0.0361121,6.5218379,6.0218363)">
|
||||
<g
|
||||
id="g854"
|
||||
style="fill:#c1272d;fill-opacity:1">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path850"
|
||||
d="m -14.4505,276.30781 c 0,-6.995 2.705,-13.403 7.846,-18.556 l 156.788,-156.782 c 5.128,-5.140997 11.554,-7.851997 18.568,-7.851997 7.026,0 13.452,2.717 18.556,7.845997 l 16.83,16.83 c 5.129,5.135 7.84,11.549 7.84,18.538 0,7.026 -2.717,13.452 -7.846,18.556 l -121.415001,121.42 121.427001,121.433 c 5.129,5.135 7.84,11.555 7.84,18.55 0,7.02 -2.717,13.439 -7.846,18.544 l -16.775,16.774 c -5.116,5.165 -11.555,7.895 -18.611,7.895 -7.044,0 -13.47,-2.723 -18.556,-7.846 l -156.813,-156.8 c -5.128,-5.14 -7.833,-11.549 -7.833,-18.55 z"
|
||||
style="fill:#c1272d;fill-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path322"
|
||||
d="m 539.38069,276.30781 c 0,-6.995 -2.705,-13.403 -7.846,-18.556 l -156.788,-156.782 c -5.128,-5.140997 -11.554,-7.851997 -18.568,-7.851997 -7.026,0 -13.452,2.717 -18.556,7.845997 l -16.83,16.83 c -5.129,5.135 -7.84,11.549 -7.84,18.538 0,7.026 2.717,13.452 7.846,18.556 l 121.415,121.42 -121.427,121.433 c -5.129,5.135 -7.84,11.555 -7.84,18.55 0,7.02 2.717,13.439 7.846,18.544 l 16.775,16.774 c 5.116,5.165 11.555,7.895 18.611,7.895 7.044,0 13.47,-2.723 18.556,-7.846 l 156.813,-156.8 c 5.128,-5.14 7.833,-11.549 7.833,-18.55 z"
|
||||
style="fill:#c1272d;fill-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g858"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g860"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g862"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g864"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g866"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g868"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g870"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g872"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g874"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g876"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g878"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g880"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g882"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g884"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g886"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g12">
|
||||
<path
|
||||
id="path6"
|
||||
d="m 6,28 h 20 c 1.1,0 2,-0.9 2,-2 V 9 6 C 28,4.9 27.1,4 26,4 H 6 C 4.9,4 4,4.9 4,6 v 3 17 c 0,1.1 0.9,2 2,2 z"
|
||||
fill="none" />
|
||||
<path
|
||||
id="path8"
|
||||
d="M 26,0 H 6 C 2.7,0 0,2.7 0,6 V 9 H 4 V 6 C 4,4.9 4.9,4 6,4 h 20 c 1.1,0 2,0.9 2,2 v 3 h 4 V 6 C 32,2.7 29.3,0 26,0 Z"
|
||||
fill="#39b54a" />
|
||||
<path
|
||||
id="path10"
|
||||
d="m 28,26 c 0,1.1 -0.9,2 -2,2 H 6 C 4.9,28 4,27.1 4,26 V 9 H 0 v 17 c 0,3.3 2.7,6 6,6 h 20 c 3.3,0 6,-2.7 6,-6 V 9 h -4 z"
|
||||
fill="#8c6239" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
@ -10,6 +10,7 @@
|
||||
<file>scalable/copy.svg</file>
|
||||
<file>scalable/coremods.svg</file>
|
||||
<file>scalable/custom-commands.svg</file>
|
||||
<file>scalable/environment-variables.svg</file>
|
||||
<file>scalable/externaltools.svg</file>
|
||||
<file>scalable/help.svg</file>
|
||||
<file>scalable/instance-settings.svg</file>
|
||||
|
345
launcher/resources/pe_dark/scalable/environment-variables.svg
Normal file
@ -0,0 +1,345 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
id="svg2"
|
||||
height="32"
|
||||
width="32"
|
||||
version="1.1"
|
||||
sodipodi:docname="environment-variables.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
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/">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#505050"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1720"
|
||||
inkscape:window-height="749"
|
||||
id="namedview52"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.75"
|
||||
inkscape:cx="20.305085"
|
||||
inkscape:cy="19.79661"
|
||||
inkscape:window-x="153"
|
||||
inkscape:window-y="287"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#505050">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid858" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient3931">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
id="stop3933" />
|
||||
<stop
|
||||
offset="0.69999987"
|
||||
style="stop-color:#ffffff;stop-opacity:0.10396039"
|
||||
id="stop3939" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0.14356436"
|
||||
id="stop3935" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3900">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#f6f6f6;stop-opacity:1"
|
||||
id="stop3902" />
|
||||
<stop
|
||||
offset="0.75714284"
|
||||
style="stop-color:#494949;stop-opacity:1"
|
||||
id="stop3904" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#2c2c2c;stop-opacity:1"
|
||||
id="stop3906" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3808">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#333333;stop-opacity:1"
|
||||
id="stop3810" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#c8c8c8;stop-opacity:1"
|
||||
id="stop3812" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3030">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1"
|
||||
id="stop3032" />
|
||||
<stop
|
||||
offset="0.75714284"
|
||||
style="stop-color:#333333;stop-opacity:1"
|
||||
id="stop3038" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#4d4d4d;stop-opacity:1"
|
||||
id="stop3034" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
gradientTransform="matrix(0.67596238,0.94191445,-0.76796117,0.55112488,7.7178628,-19.890271)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3030"
|
||||
id="radialGradient3036"
|
||||
fy="14.242621"
|
||||
fx="29.381905"
|
||||
r="16.375"
|
||||
cy="14.242621"
|
||||
cx="29.381905" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.5,0,0,1,-16,4)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3808"
|
||||
id="linearGradient3824"
|
||||
y2="1033.8622"
|
||||
x2="34"
|
||||
y1="1033.8622"
|
||||
x1="30" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(0.82142857,0,0,1.500001,6.7142857,-522.68214)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3808"
|
||||
id="linearGradient3834"
|
||||
y2="1039.3622"
|
||||
x2="32"
|
||||
y1="1043.3622"
|
||||
x1="32" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(6.479993,1.9525666,-10.415476,2.1794781,10657.845,-1282.8793)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3844"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(2.5191507,2.9862959,-4.0491019,3.333339,4186.8847,-2518.44)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3852"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(-2.5191507,2.9863064,4.0491022,3.3333507,-4122.8849,-2518.4524)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3857"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(-0.69414478,2.3073251,-1.6952184,-0.67174747,96.941544,960.82172)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3937"
|
||||
fy="21.976955"
|
||||
fx="31.946348"
|
||||
r="19.25"
|
||||
cy="21.976955"
|
||||
cx="31.946348" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M 26,32 H 6 C 2.7,32 0,29.3 0,26 V 6 C 0,2.7 2.7,0 6,0 h 20 c 3.3,0 6,2.7 6,6 v 20 c 0,3.3 -2.7,6 -6,6 z"
|
||||
id="path2"
|
||||
style="fill-opacity:1;fill:#010101" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fill="#f2f2f2"
|
||||
d="M 28,6 C 28,4.9 27.1,4 26,4 H 6 C 4.9,4 4,4.9 4,6 v 20 c 0,1.1 0.9,2 2,2 h 20 c 1.1,0 2,-0.9 2,-2 z"
|
||||
id="path4" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g869"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g871"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g873"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g875"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g877"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g879"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g881"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g883"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g885"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g887"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g889"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g891"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g893"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g895"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g897"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
id="g856"
|
||||
style="fill:#666666;fill-opacity:1"
|
||||
transform="matrix(0.0361121,0,0,0.0361121,6.5218379,6.0218363)">
|
||||
<g
|
||||
id="g854"
|
||||
style="fill:#666666;fill-opacity:1">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path850"
|
||||
d="m -14.4505,276.30781 c 0,-6.995 2.705,-13.403 7.846,-18.556 l 156.788,-156.782 c 5.128,-5.140997 11.554,-7.851997 18.568,-7.851997 7.026,0 13.452,2.717 18.556,7.845997 l 16.83,16.83 c 5.129,5.135 7.84,11.549 7.84,18.538 0,7.026 -2.717,13.452 -7.846,18.556 l -121.415001,121.42 121.427001,121.433 c 5.129,5.135 7.84,11.555 7.84,18.55 0,7.02 -2.717,13.439 -7.846,18.544 l -16.775,16.774 c -5.116,5.165 -11.555,7.895 -18.611,7.895 -7.044,0 -13.47,-2.723 -18.556,-7.846 l -156.813,-156.8 c -5.128,-5.14 -7.833,-11.549 -7.833,-18.55 z"
|
||||
style="fill:#666666;fill-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path322"
|
||||
d="m 539.38069,276.30781 c 0,-6.995 -2.705,-13.403 -7.846,-18.556 l -156.788,-156.782 c -5.128,-5.140997 -11.554,-7.851997 -18.568,-7.851997 -7.026,0 -13.452,2.717 -18.556,7.845997 l -16.83,16.83 c -5.129,5.135 -7.84,11.549 -7.84,18.538 0,7.026 2.717,13.452 7.846,18.556 l 121.415,121.42 -121.427,121.433 c -5.129,5.135 -7.84,11.555 -7.84,18.55 0,7.02 2.717,13.439 7.846,18.544 l 16.775,16.774 c 5.116,5.165 11.555,7.895 18.611,7.895 7.044,0 13.47,-2.723 18.556,-7.846 l 156.813,-156.8 c 5.128,-5.14 7.833,-11.549 7.833,-18.55 z"
|
||||
style="fill:#666666;fill-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g858"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g860"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g862"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g864"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g866"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g868"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g870"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g872"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g874"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g876"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g878"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g880"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g882"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g884"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g886"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g12">
|
||||
<path
|
||||
id="path6"
|
||||
d="m 6,28 h 20 c 1.1,0 2,-0.9 2,-2 V 9 6 C 28,4.9 27.1,4 26,4 H 6 C 4.9,4 4,4.9 4,6 v 3 17 c 0,1.1 0.9,2 2,2 z"
|
||||
fill="none" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
@ -10,6 +10,7 @@
|
||||
<file>scalable/copy.svg</file>
|
||||
<file>scalable/coremods.svg</file>
|
||||
<file>scalable/custom-commands.svg</file>
|
||||
<file>scalable/environment-variables.svg</file>
|
||||
<file>scalable/externaltools.svg</file>
|
||||
<file>scalable/help.svg</file>
|
||||
<file>scalable/instance-settings.svg</file>
|
||||
|
345
launcher/resources/pe_light/scalable/environment-variables.svg
Normal file
@ -0,0 +1,345 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
id="svg2"
|
||||
height="32"
|
||||
width="32"
|
||||
version="1.1"
|
||||
sodipodi:docname="environment-variables.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
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/">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#505050"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
id="namedview52"
|
||||
showgrid="false"
|
||||
inkscape:zoom="11.313709"
|
||||
inkscape:cx="5.5242717"
|
||||
inkscape:cy="12.28598"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#505050">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid858" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient3931">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
id="stop3933" />
|
||||
<stop
|
||||
offset="0.69999987"
|
||||
style="stop-color:#ffffff;stop-opacity:0.10396039"
|
||||
id="stop3939" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0.14356436"
|
||||
id="stop3935" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3900">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#f6f6f6;stop-opacity:1"
|
||||
id="stop3902" />
|
||||
<stop
|
||||
offset="0.75714284"
|
||||
style="stop-color:#494949;stop-opacity:1"
|
||||
id="stop3904" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#2c2c2c;stop-opacity:1"
|
||||
id="stop3906" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3808">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#333333;stop-opacity:1"
|
||||
id="stop3810" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#c8c8c8;stop-opacity:1"
|
||||
id="stop3812" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3030">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1"
|
||||
id="stop3032" />
|
||||
<stop
|
||||
offset="0.75714284"
|
||||
style="stop-color:#333333;stop-opacity:1"
|
||||
id="stop3038" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#4d4d4d;stop-opacity:1"
|
||||
id="stop3034" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
gradientTransform="matrix(0.67596238,0.94191445,-0.76796117,0.55112488,7.7178628,-19.890271)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3030"
|
||||
id="radialGradient3036"
|
||||
fy="14.242621"
|
||||
fx="29.381905"
|
||||
r="16.375"
|
||||
cy="14.242621"
|
||||
cx="29.381905" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.5,0,0,1,-16,4)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3808"
|
||||
id="linearGradient3824"
|
||||
y2="1033.8622"
|
||||
x2="34"
|
||||
y1="1033.8622"
|
||||
x1="30" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(0.82142857,0,0,1.500001,6.7142857,-522.68214)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3808"
|
||||
id="linearGradient3834"
|
||||
y2="1039.3622"
|
||||
x2="32"
|
||||
y1="1043.3622"
|
||||
x1="32" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(6.479993,1.9525666,-10.415476,2.1794781,10657.845,-1282.8793)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3844"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(2.5191507,2.9862959,-4.0491019,3.333339,4186.8847,-2518.44)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3852"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(-2.5191507,2.9863064,4.0491022,3.3333507,-4122.8849,-2518.4524)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3857"
|
||||
fy="1039.813"
|
||||
fx="30.724609"
|
||||
r="3"
|
||||
cy="1039.813"
|
||||
cx="30.724609" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(-0.69414478,2.3073251,-1.6952184,-0.67174747,96.941544,960.82172)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3900"
|
||||
id="radialGradient3937"
|
||||
fy="21.976955"
|
||||
fx="31.946348"
|
||||
r="19.25"
|
||||
cy="21.976955"
|
||||
cx="31.946348" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M 26,32 H 6 C 2.7,32 0,29.3 0,26 V 6 C 0,2.7 2.7,0 6,0 h 20 c 3.3,0 6,2.7 6,6 v 20 c 0,3.3 -2.7,6 -6,6 z"
|
||||
id="path2"
|
||||
style="fill-opacity:1;fill:#f2f2f2" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g869"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g871"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g873"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g875"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g877"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g879"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g881"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g883"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g885"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g887"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g889"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g891"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g893"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g895"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<g
|
||||
style="fill:#008000"
|
||||
id="g897"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499946,5.2499965)" />
|
||||
<path
|
||||
id="path2-3"
|
||||
d="M 28,6 C 28,4.9 27.1,4 26,4 H 6 C 4.9,4 4,4.9 4,6 v 20.000001 c 0,1.1 0.9,2 2,2 h 20 c 1.1,0 2,-0.9 2,-2 z"
|
||||
fill="#4d4d4d"
|
||||
clip-rule="evenodd"
|
||||
fill-rule="evenodd" />
|
||||
<g
|
||||
id="g856"
|
||||
style="fill:#ffffff;fill-opacity:1"
|
||||
transform="matrix(0.0361121,0,0,0.0361121,6.5218379,6.0218363)">
|
||||
<g
|
||||
id="g854"
|
||||
style="fill:#ffffff;fill-opacity:1">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path850"
|
||||
d="m -14.4505,276.30781 c 0,-6.995 2.705,-13.403 7.846,-18.556 l 156.788,-156.782 c 5.128,-5.140997 11.554,-7.851997 18.568,-7.851997 7.026,0 13.452,2.717 18.556,7.845997 l 16.83,16.83 c 5.129,5.135 7.84,11.549 7.84,18.538 0,7.026 -2.717,13.452 -7.846,18.556 l -121.415001,121.42 121.427001,121.433 c 5.129,5.135 7.84,11.555 7.84,18.55 0,7.02 -2.717,13.439 -7.846,18.544 l -16.775,16.774 c -5.116,5.165 -11.555,7.895 -18.611,7.895 -7.044,0 -13.47,-2.723 -18.556,-7.846 l -156.813,-156.8 c -5.128,-5.14 -7.833,-11.549 -7.833,-18.55 z"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path322"
|
||||
d="m 539.38069,276.30781 c 0,-6.995 -2.705,-13.403 -7.846,-18.556 l -156.788,-156.782 c -5.128,-5.140997 -11.554,-7.851997 -18.568,-7.851997 -7.026,0 -13.452,2.717 -18.556,7.845997 l -16.83,16.83 c -5.129,5.135 -7.84,11.549 -7.84,18.538 0,7.026 2.717,13.452 7.846,18.556 l 121.415,121.42 -121.427,121.433 c -5.129,5.135 -7.84,11.555 -7.84,18.55 0,7.02 2.717,13.439 7.846,18.544 l 16.775,16.774 c 5.116,5.165 11.555,7.895 18.611,7.895 7.044,0 13.47,-2.723 18.556,-7.846 l 156.813,-156.8 c 5.128,-5.14 7.833,-11.549 7.833,-18.55 z"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g858"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g860"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g862"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g864"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g866"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g868"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g870"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g872"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g874"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g876"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g878"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g880"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g882"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g884"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g886"
|
||||
style="fill:#00ff00"
|
||||
transform="matrix(0.04286288,0,0,0.04286288,4.7499948,4.2499932)" />
|
||||
<g
|
||||
id="g12">
|
||||
<path
|
||||
id="path6"
|
||||
d="m 6,28 h 20 c 1.1,0 2,-0.9 2,-2 V 9 6 C 28,4.9 27.1,4 26,4 H 6 C 4.9,4 4,4.9 4,6 v 3 17 c 0,1.1 0.9,2 2,2 z"
|
||||
fill="none" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
@ -39,87 +39,76 @@
|
||||
#include <QDebug>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QList>
|
||||
#include <QNetworkRequest>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
#include <memory>
|
||||
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "net/StaticHeaderProxy.h"
|
||||
|
||||
ImgurAlbumCreation::ImgurAlbumCreation(QList<ScreenShot::Ptr> screenshots) : NetAction(), m_screenshots(screenshots)
|
||||
Net::NetRequest::Ptr ImgurAlbumCreation::make(std::shared_ptr<ImgurAlbumCreation::Result> output, QList<ScreenShot::Ptr> screenshots)
|
||||
{
|
||||
m_url = BuildConfig.IMGUR_BASE_URL + "album.json";
|
||||
m_state = State::Inactive;
|
||||
auto up = makeShared<ImgurAlbumCreation>();
|
||||
up->m_url = BuildConfig.IMGUR_BASE_URL + "album.json";
|
||||
up->m_sink.reset(new Sink(output));
|
||||
up->m_screenshots = screenshots;
|
||||
return up;
|
||||
}
|
||||
|
||||
void ImgurAlbumCreation::executeTask()
|
||||
QNetworkReply* ImgurAlbumCreation::getReply(QNetworkRequest& request)
|
||||
{
|
||||
m_state = State::Running;
|
||||
QNetworkRequest request(m_url);
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgentUncached().toUtf8());
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
request.setRawHeader("Authorization", QString("Client-ID %1").arg(BuildConfig.IMGUR_CLIENT_ID).toStdString().c_str());
|
||||
request.setRawHeader("Accept", "application/json");
|
||||
|
||||
QStringList hashes;
|
||||
for (auto shot : m_screenshots) {
|
||||
hashes.append(shot->m_imgurDeleteHash);
|
||||
}
|
||||
|
||||
const QByteArray data = "deletehashes=" + hashes.join(',').toUtf8() + "&title=Minecraft%20Screenshots&privacy=hidden";
|
||||
return m_network->post(request, data);
|
||||
};
|
||||
|
||||
QNetworkReply* rep = APPLICATION->network()->post(request, data);
|
||||
|
||||
m_reply.reset(rep);
|
||||
connect(rep, &QNetworkReply::uploadProgress, this, &ImgurAlbumCreation::downloadProgress);
|
||||
connect(rep, &QNetworkReply::finished, this, &ImgurAlbumCreation::downloadFinished);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15
|
||||
connect(rep, &QNetworkReply::errorOccurred, this, &ImgurAlbumCreation::downloadError);
|
||||
#else
|
||||
connect(rep, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &ImgurAlbumCreation::downloadError);
|
||||
#endif
|
||||
connect(rep, &QNetworkReply::sslErrors, this, &ImgurAlbumCreation::sslErrors);
|
||||
void ImgurAlbumCreation::init()
|
||||
{
|
||||
qDebug() << "Setting up imgur upload";
|
||||
auto api_headers = new Net::StaticHeaderProxy(
|
||||
QList<Net::HeaderPair>{ { "Content-Type", "application/x-www-form-urlencoded" },
|
||||
{ "Authorization", QString("Client-ID %1").arg(BuildConfig.IMGUR_CLIENT_ID).toStdString().c_str() },
|
||||
{ "Accept", "application/json" } });
|
||||
addHeaderProxy(api_headers);
|
||||
}
|
||||
|
||||
void ImgurAlbumCreation::downloadError([[maybe_unused]] QNetworkReply::NetworkError error)
|
||||
auto ImgurAlbumCreation::Sink::init(QNetworkRequest& request) -> Task::State
|
||||
{
|
||||
qDebug() << m_reply->errorString();
|
||||
m_state = State::Failed;
|
||||
m_output.clear();
|
||||
return Task::State::Running;
|
||||
};
|
||||
|
||||
auto ImgurAlbumCreation::Sink::write(QByteArray& data) -> Task::State
|
||||
{
|
||||
m_output.append(data);
|
||||
return Task::State::Running;
|
||||
}
|
||||
|
||||
void ImgurAlbumCreation::downloadFinished()
|
||||
auto ImgurAlbumCreation::Sink::abort() -> Task::State
|
||||
{
|
||||
if (m_state != State::Failed) {
|
||||
QByteArray data = m_reply->readAll();
|
||||
m_reply.reset();
|
||||
QJsonParseError jsonError;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||
if (jsonError.error != QJsonParseError::NoError) {
|
||||
qDebug() << jsonError.errorString();
|
||||
emitFailed();
|
||||
return;
|
||||
}
|
||||
auto object = doc.object();
|
||||
if (!object.value("success").toBool()) {
|
||||
qDebug() << doc.toJson();
|
||||
emitFailed();
|
||||
return;
|
||||
}
|
||||
m_deleteHash = object.value("data").toObject().value("deletehash").toString();
|
||||
m_id = object.value("data").toObject().value("id").toString();
|
||||
m_state = State::Succeeded;
|
||||
emit succeeded();
|
||||
return;
|
||||
} else {
|
||||
qDebug() << m_reply->readAll();
|
||||
m_reply.reset();
|
||||
emitFailed();
|
||||
return;
|
||||
m_output.clear();
|
||||
return Task::State::Failed;
|
||||
}
|
||||
|
||||
auto ImgurAlbumCreation::Sink::finalize(QNetworkReply&) -> Task::State
|
||||
{
|
||||
QJsonParseError jsonError;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(m_output, &jsonError);
|
||||
if (jsonError.error != QJsonParseError::NoError) {
|
||||
qDebug() << jsonError.errorString();
|
||||
return Task::State::Failed;
|
||||
}
|
||||
}
|
||||
|
||||
void ImgurAlbumCreation::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
setProgress(bytesReceived, bytesTotal);
|
||||
emit progress(bytesReceived, bytesTotal);
|
||||
auto object = doc.object();
|
||||
if (!object.value("success").toBool()) {
|
||||
qDebug() << doc.toJson();
|
||||
return Task::State::Failed;
|
||||
}
|
||||
m_result->deleteHash = object.value("data").toObject().value("deletehash").toString();
|
||||
m_result->id = object.value("data").toObject().value("id").toString();
|
||||
return Task::State::Succeeded;
|
||||
}
|
@ -36,34 +36,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "Screenshot.h"
|
||||
#include "net/NetAction.h"
|
||||
#include "net/NetRequest.h"
|
||||
|
||||
typedef shared_qobject_ptr<class ImgurAlbumCreation> ImgurAlbumCreationPtr;
|
||||
class ImgurAlbumCreation : public NetAction {
|
||||
class ImgurAlbumCreation : public Net::NetRequest {
|
||||
public:
|
||||
explicit ImgurAlbumCreation(QList<ScreenShot::Ptr> screenshots);
|
||||
static ImgurAlbumCreationPtr make(QList<ScreenShot::Ptr> screenshots)
|
||||
{
|
||||
return ImgurAlbumCreationPtr(new ImgurAlbumCreation(screenshots));
|
||||
}
|
||||
virtual ~ImgurAlbumCreation() = default;
|
||||
|
||||
QString deleteHash() const { return m_deleteHash; }
|
||||
QString id() const { return m_id; }
|
||||
struct Result {
|
||||
QString deleteHash;
|
||||
QString id;
|
||||
};
|
||||
|
||||
void init() override{};
|
||||
class Sink : public Net::Sink {
|
||||
public:
|
||||
Sink(std::shared_ptr<Result> res) : m_result(res){};
|
||||
virtual ~Sink() = default;
|
||||
|
||||
protected slots:
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
|
||||
void downloadError(QNetworkReply::NetworkError error) override;
|
||||
void downloadFinished() override;
|
||||
void downloadReadyRead() override {}
|
||||
public:
|
||||
auto init(QNetworkRequest& request) -> Task::State override;
|
||||
auto write(QByteArray& data) -> Task::State override;
|
||||
auto abort() -> Task::State override;
|
||||
auto finalize(QNetworkReply& reply) -> Task::State override;
|
||||
auto hasLocalData() -> bool override { return false; }
|
||||
|
||||
public slots:
|
||||
void executeTask() override;
|
||||
private:
|
||||
std::shared_ptr<Result> m_result;
|
||||
QByteArray m_output;
|
||||
};
|
||||
|
||||
static NetRequest::Ptr make(std::shared_ptr<Result> output, QList<ScreenShot::Ptr> screenshots);
|
||||
QNetworkReply* getReply(QNetworkRequest& request) override;
|
||||
|
||||
void init() override;
|
||||
|
||||
private:
|
||||
QList<ScreenShot::Ptr> m_screenshots;
|
||||
|
||||
QString m_deleteHash;
|
||||
QString m_id;
|
||||
};
|
||||
|
@ -35,8 +35,8 @@
|
||||
*/
|
||||
|
||||
#include "ImgurUpload.h"
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "net/StaticHeaderProxy.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
@ -47,104 +47,84 @@
|
||||
#include <QNetworkRequest>
|
||||
#include <QUrl>
|
||||
|
||||
ImgurUpload::ImgurUpload(ScreenShot::Ptr shot) : NetAction(), m_shot(shot)
|
||||
void ImgurUpload::init()
|
||||
{
|
||||
m_url = BuildConfig.IMGUR_BASE_URL + "upload.json";
|
||||
m_state = State::Inactive;
|
||||
qDebug() << "Setting up imgur upload";
|
||||
auto api_headers = new Net::StaticHeaderProxy(
|
||||
QList<Net::HeaderPair>{ { "Authorization", QString("Client-ID %1").arg(BuildConfig.IMGUR_CLIENT_ID).toStdString().c_str() },
|
||||
{ "Accept", "application/json" } });
|
||||
addHeaderProxy(api_headers);
|
||||
}
|
||||
|
||||
void ImgurUpload::executeTask()
|
||||
QNetworkReply* ImgurUpload::getReply(QNetworkRequest& request)
|
||||
{
|
||||
finished = false;
|
||||
m_state = Task::State::Running;
|
||||
QNetworkRequest request(m_url);
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgentUncached().toUtf8());
|
||||
request.setRawHeader("Authorization", QString("Client-ID %1").arg(BuildConfig.IMGUR_CLIENT_ID).toStdString().c_str());
|
||||
request.setRawHeader("Accept", "application/json");
|
||||
auto file = new QFile(m_fileInfo.absoluteFilePath());
|
||||
|
||||
QFile f(m_shot->m_file.absoluteFilePath());
|
||||
if (!f.open(QFile::ReadOnly)) {
|
||||
if (!file->open(QFile::ReadOnly)) {
|
||||
emitFailed();
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QHttpMultiPart* multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
file->setParent(multipart);
|
||||
QHttpPart filePart;
|
||||
filePart.setBody(f.readAll().toBase64());
|
||||
filePart.setBodyDevice(file);
|
||||
filePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
|
||||
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"image\"");
|
||||
multipart->append(filePart);
|
||||
QHttpPart typePart;
|
||||
typePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"type\"");
|
||||
typePart.setBody("base64");
|
||||
typePart.setBody("file");
|
||||
multipart->append(typePart);
|
||||
QHttpPart namePart;
|
||||
namePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"name\"");
|
||||
namePart.setBody(m_shot->m_file.baseName().toUtf8());
|
||||
namePart.setBody(m_fileInfo.baseName().toUtf8());
|
||||
multipart->append(namePart);
|
||||
|
||||
QNetworkReply* rep = m_network->post(request, multipart);
|
||||
return m_network->post(request, multipart);
|
||||
};
|
||||
|
||||
m_reply.reset(rep);
|
||||
connect(rep, &QNetworkReply::uploadProgress, this, &ImgurUpload::downloadProgress);
|
||||
connect(rep, &QNetworkReply::finished, this, &ImgurUpload::downloadFinished);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15
|
||||
connect(rep, &QNetworkReply::errorOccurred, this, &ImgurUpload::downloadError);
|
||||
#else
|
||||
connect(rep, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &ImgurUpload::downloadError);
|
||||
#endif
|
||||
connect(rep, &QNetworkReply::sslErrors, this, &ImgurUpload::sslErrors);
|
||||
auto ImgurUpload::Sink::init(QNetworkRequest& request) -> Task::State
|
||||
{
|
||||
m_output.clear();
|
||||
return Task::State::Running;
|
||||
};
|
||||
|
||||
auto ImgurUpload::Sink::write(QByteArray& data) -> Task::State
|
||||
{
|
||||
m_output.append(data);
|
||||
return Task::State::Running;
|
||||
}
|
||||
|
||||
void ImgurUpload::downloadError([[maybe_unused]] QNetworkReply::NetworkError error)
|
||||
auto ImgurUpload::Sink::abort() -> Task::State
|
||||
{
|
||||
qCritical() << "ImgurUpload failed with error" << m_reply->errorString() << "Server reply:\n" << m_reply->readAll();
|
||||
if (finished) {
|
||||
qCritical() << "Double finished ImgurUpload!";
|
||||
return;
|
||||
}
|
||||
m_state = Task::State::Failed;
|
||||
finished = true;
|
||||
m_reply.reset();
|
||||
emitFailed();
|
||||
m_output.clear();
|
||||
return Task::State::Failed;
|
||||
}
|
||||
|
||||
void ImgurUpload::downloadFinished()
|
||||
auto ImgurUpload::Sink::finalize(QNetworkReply&) -> Task::State
|
||||
{
|
||||
if (finished) {
|
||||
qCritical() << "Double finished ImgurUpload!";
|
||||
return;
|
||||
}
|
||||
QByteArray data = m_reply->readAll();
|
||||
m_reply.reset();
|
||||
QJsonParseError jsonError;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||
QJsonDocument doc = QJsonDocument::fromJson(m_output, &jsonError);
|
||||
if (jsonError.error != QJsonParseError::NoError) {
|
||||
qDebug() << "imgur server did not reply with JSON" << jsonError.errorString();
|
||||
finished = true;
|
||||
m_reply.reset();
|
||||
emitFailed();
|
||||
return;
|
||||
return Task::State::Failed;
|
||||
}
|
||||
auto object = doc.object();
|
||||
if (!object.value("success").toBool()) {
|
||||
qDebug() << "Screenshot upload not successful:" << doc.toJson();
|
||||
finished = true;
|
||||
m_reply.reset();
|
||||
emitFailed();
|
||||
return;
|
||||
return Task::State::Failed;
|
||||
}
|
||||
m_shot->m_imgurId = object.value("data").toObject().value("id").toString();
|
||||
m_shot->m_url = object.value("data").toObject().value("link").toString();
|
||||
m_shot->m_imgurDeleteHash = object.value("data").toObject().value("deletehash").toString();
|
||||
m_state = Task::State::Succeeded;
|
||||
finished = true;
|
||||
emit succeeded();
|
||||
return;
|
||||
return Task::State::Succeeded;
|
||||
}
|
||||
|
||||
void ImgurUpload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
Net::NetRequest::Ptr ImgurUpload::make(ScreenShot::Ptr m_shot)
|
||||
{
|
||||
setProgress(bytesReceived, bytesTotal);
|
||||
emit progress(bytesReceived, bytesTotal);
|
||||
auto up = makeShared<ImgurUpload>(m_shot->m_file);
|
||||
up->m_url = std::move(BuildConfig.IMGUR_BASE_URL + "upload.json");
|
||||
up->m_sink.reset(new Sink(m_shot));
|
||||
return up;
|
||||
}
|
||||
|
@ -35,27 +35,36 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QFileInfo>
|
||||
#include "Screenshot.h"
|
||||
#include "net/NetAction.h"
|
||||
#include "net/NetRequest.h"
|
||||
|
||||
class ImgurUpload : public NetAction {
|
||||
class ImgurUpload : public Net::NetRequest {
|
||||
public:
|
||||
using Ptr = shared_qobject_ptr<ImgurUpload>;
|
||||
class Sink : public Net::Sink {
|
||||
public:
|
||||
Sink(ScreenShot::Ptr shot) : m_shot(shot){};
|
||||
virtual ~Sink() = default;
|
||||
|
||||
explicit ImgurUpload(ScreenShot::Ptr shot);
|
||||
static Ptr make(ScreenShot::Ptr shot) { return Ptr(new ImgurUpload(shot)); }
|
||||
void init() override{};
|
||||
public:
|
||||
auto init(QNetworkRequest& request) -> Task::State override;
|
||||
auto write(QByteArray& data) -> Task::State override;
|
||||
auto abort() -> Task::State override;
|
||||
auto finalize(QNetworkReply& reply) -> Task::State override;
|
||||
auto hasLocalData() -> bool override { return false; }
|
||||
|
||||
protected slots:
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
|
||||
void downloadError(QNetworkReply::NetworkError error) override;
|
||||
void downloadFinished() override;
|
||||
void downloadReadyRead() override {}
|
||||
private:
|
||||
ScreenShot::Ptr m_shot;
|
||||
QByteArray m_output;
|
||||
};
|
||||
ImgurUpload(QFileInfo info) : m_fileInfo(info) {}
|
||||
virtual ~ImgurUpload() = default;
|
||||
|
||||
public slots:
|
||||
void executeTask() override;
|
||||
static NetRequest::Ptr make(ScreenShot::Ptr m_shot);
|
||||
|
||||
void init() override;
|
||||
|
||||
private:
|
||||
ScreenShot::Ptr m_shot;
|
||||
bool finished = true;
|
||||
virtual QNetworkReply* getReply(QNetworkRequest&) override;
|
||||
const QFileInfo m_fileInfo;
|
||||
};
|
||||
|
@ -26,8 +26,8 @@
|
||||
class Setting;
|
||||
class SettingsObject;
|
||||
|
||||
typedef std::shared_ptr<SettingsObject> SettingsObjectPtr;
|
||||
typedef std::weak_ptr<SettingsObject> SettingsObjectWeakPtr;
|
||||
using SettingsObjectPtr = std::shared_ptr<SettingsObject>;
|
||||
using SettingsObjectWeakPtr = std::weak_ptr<SettingsObject>;
|
||||
|
||||
/*!
|
||||
* \brief The SettingsObject handles communicating settings between the application and a
|
||||
|
@ -77,7 +77,7 @@ struct TaskStepProgress {
|
||||
|
||||
Q_DECLARE_METATYPE(TaskStepProgress)
|
||||
|
||||
typedef QList<std::shared_ptr<TaskStepProgress>> TaskStepProgressList;
|
||||
using TaskStepProgressList = QList<std::shared_ptr<TaskStepProgress>>;
|
||||
|
||||
class Task : public QObject, public QRunnable {
|
||||
Q_OBJECT
|
||||
|