Compare commits
38 Commits
release-6.
...
5.1
Author | SHA1 | Date | |
---|---|---|---|
d8044ababe | |||
32b526b729 | |||
7f6515dbe4 | |||
a39390b8b4 | |||
63a3dd1919 | |||
7a5a4de6ea | |||
664d4e701e | |||
a4ba8d8288 | |||
392bf7a97b | |||
34687049b1 | |||
9337ec6706 | |||
5bcb6962c4 | |||
0617b43190 | |||
ed28234cfb | |||
9c4455ca03 | |||
9ec7837275 | |||
549b5a6488 | |||
2652f37453 | |||
0eaff22145 | |||
2f5393b9d0 | |||
e28480a8e4 | |||
fcef6321fc | |||
35e792c5de | |||
c08b632b51 | |||
cac800bfd8 | |||
2eb8173951 | |||
75abf2c124 | |||
d40a18d6c5 | |||
a74fdc588c | |||
25b0ec6eff | |||
04e8982d33 | |||
58bd449db8 | |||
c984e9b5d6 | |||
ddd319369a | |||
de3c336213 | |||
6e94e9bff1 | |||
93b8d9e454 | |||
6d46081864 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1 +1 @@
|
|||||||
open_collective: prismlauncher
|
open_collective: polymc
|
||||||
|
12
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
12
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -8,9 +8,9 @@ body:
|
|||||||
If you need help with running Minecraft, please visit us on our Discord before making a bug report.
|
If you need help with running Minecraft, please visit us on our Discord before making a bug report.
|
||||||
|
|
||||||
Before submitting a bug report, please make sure you have read this *entire* form, and that:
|
Before submitting a bug report, please make sure you have read this *entire* form, and that:
|
||||||
* You have read the [Prism Launcher wiki](https://prismlauncher.org/wiki/) and it has not answered your question.
|
* You have read the [PolyMC wiki](https://polymc.org/wiki/) and it has not answered your question.
|
||||||
* Your bug is not caused by Minecraft or any mods you have installed.
|
* Your bug is not caused by Minecraft or any mods you have installed.
|
||||||
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/PrismLauncher/PrismLauncher/issues)
|
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/PolyMC/PolyMC/issues)
|
||||||
|
|
||||||
**Do not forget to give your issue a descriptive title.** "Bug in the instance screen" makes it hard to distinguish issues at a glance.
|
**Do not forget to give your issue a descriptive title.** "Bug in the instance screen" makes it hard to distinguish issues at a glance.
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
@ -25,15 +25,15 @@ body:
|
|||||||
- Other
|
- Other
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Version of Prism Launcher
|
label: Version of PolyMC
|
||||||
description: The version of Prism Launcher used in the bug report.
|
description: The version of PolyMC used in the bug report.
|
||||||
placeholder: Prism Launcher 5.0
|
placeholder: PolyMC 1.4.1
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Version of Qt
|
label: Version of Qt
|
||||||
description: The version of Qt used in the bug report. You can find it in Help -> About Prism Launcher -> About Qt.
|
description: The version of Qt used in the bug report. You can find it in Help -> About PolyMC -> About Qt.
|
||||||
placeholder: Qt 6.3.0
|
placeholder: Qt 6.3.0
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,5 +1,5 @@
|
|||||||
blank_issues_enabled: true
|
blank_issues_enabled: true
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Prism Launcher Matrix Support Room
|
- name: PolyMC Matrix Support Room
|
||||||
url: https://matrix.to/#/#prism-support:matrix.org
|
url: https://matrix.to/#/#support:polymc.org
|
||||||
about: Please ask for support here before opening an issue.
|
about: Please ask for support here before opening an issue.
|
||||||
|
4
.github/ISSUE_TEMPLATE/rfc.yml
vendored
4
.github/ISSUE_TEMPLATE/rfc.yml
vendored
@ -6,7 +6,7 @@ body:
|
|||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
### Use this form to suggest a larger change for Prism Launcher.
|
### Use this form to suggest a larger change for PolyMC.
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Goal
|
label: Goal
|
||||||
@ -18,7 +18,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Motivation
|
label: Motivation
|
||||||
description: |
|
description: |
|
||||||
Introduce the topic. If this is a not-well-known section of Prism Launcher, a detailed explanation of the background is recommended.
|
Introduce the topic. If this is a not-well-known section of PolyMC, a detailed explanation of the background is recommended.
|
||||||
Some example points of discussion:
|
Some example points of discussion:
|
||||||
- What specific problems are you facing right now that you're trying to address?
|
- What specific problems are you facing right now that you're trying to address?
|
||||||
- Are there any previous discussions? Link to them and summarize them (don't force your readers to read them though!).
|
- Are there any previous discussions? Link to them and summarize them (don't force your readers to read them though!).
|
||||||
|
8
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
8
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
@ -5,25 +5,25 @@ body:
|
|||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
### Use this form to suggest a feature for Prism Launcher.
|
### Use this form to suggest a feature for PolyMC.
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: Role
|
label: Role
|
||||||
description: In what way do you use Prism Launcher that needs this feature?
|
description: In what way do you use PolyMC that needs this feature?
|
||||||
placeholder: I play modded Minecraft.
|
placeholder: I play modded Minecraft.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: Suggestion
|
label: Suggestion
|
||||||
description: What do you want Prism Launcher to do?
|
description: What do you want PolyMC to do?
|
||||||
placeholder: I want the cat button to meow.
|
placeholder: I want the cat button to meow.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: Benefit
|
label: Benefit
|
||||||
description: Why do you need Prism Launcher to do this?
|
description: Why do you need PolyMC to do this?
|
||||||
placeholder: so that I can always hear a cat when I need to.
|
placeholder: so that I can always hear a cat when I need to.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
9
.github/pull_request_template.md
vendored
9
.github/pull_request_template.md
vendored
@ -1,9 +0,0 @@
|
|||||||
<!--
|
|
||||||
Hey there! Thanks for your contribution.
|
|
||||||
|
|
||||||
Please make sure that your commits are signed off first.
|
|
||||||
If you don't know how that works, check out our contribution guidelines: https://github.com/PrismLauncher/PrismLauncher/blob/develop/CONTRIBUTING.md#signing-your-work
|
|
||||||
If you already created your commits, you can run `git rebase --signoff develop` to retroactively sign-off all your commits and `git push --force` to override what you have pushed already.
|
|
||||||
|
|
||||||
Note that signing and signing-off are two different things!
|
|
||||||
-->
|
|
277
.github/workflows/build.yml
vendored
277
.github/workflows/build.yml
vendored
@ -7,17 +7,10 @@ on:
|
|||||||
description: Type of build (Debug, Release, RelWithDebInfo, MinSizeRel)
|
description: Type of build (Debug, Release, RelWithDebInfo, MinSizeRel)
|
||||||
type: string
|
type: string
|
||||||
default: Debug
|
default: Debug
|
||||||
is_qt_cached:
|
|
||||||
description: Enable Qt caching or not
|
|
||||||
type: string
|
|
||||||
default: true
|
|
||||||
secrets:
|
secrets:
|
||||||
SPARKLE_ED25519_KEY:
|
SPARKLE_ED25519_KEY:
|
||||||
description: Private key for signing Sparkle updates
|
description: Private key for signing Sparkle updates
|
||||||
required: false
|
required: false
|
||||||
CACHIX_AUTH_TOKEN:
|
|
||||||
description: Private token for authenticating against Cachix cache
|
|
||||||
required: false
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@ -32,60 +25,26 @@ jobs:
|
|||||||
- os: ubuntu-20.04
|
- os: ubuntu-20.04
|
||||||
qt_ver: 6
|
qt_ver: 6
|
||||||
qt_host: linux
|
qt_host: linux
|
||||||
qt_arch: ''
|
|
||||||
qt_version: '6.2.4'
|
qt_version: '6.2.4'
|
||||||
qt_modules: 'qt5compat qtimageformats'
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
qt_tools: ''
|
|
||||||
|
|
||||||
- os: windows-2022
|
- os: windows-2022
|
||||||
name: "Windows-MinGW-w64"
|
name: "Windows-Legacy"
|
||||||
msystem: clang64
|
msystem: clang32
|
||||||
|
|
||||||
- os: windows-2022
|
|
||||||
name: "Windows-MSVC-Legacy"
|
|
||||||
msystem: ''
|
|
||||||
architecture: 'win32'
|
|
||||||
vcvars_arch: 'amd64_x86'
|
|
||||||
qt_ver: 5
|
qt_ver: 5
|
||||||
qt_host: windows
|
|
||||||
qt_arch: 'win32_msvc2019'
|
|
||||||
qt_version: '5.15.2'
|
|
||||||
qt_modules: ''
|
|
||||||
qt_tools: 'tools_openssl_x86'
|
|
||||||
|
|
||||||
- os: windows-2022
|
- os: windows-2022
|
||||||
name: "Windows-MSVC"
|
name: "Windows"
|
||||||
msystem: ''
|
msystem: clang64
|
||||||
architecture: 'x64'
|
|
||||||
vcvars_arch: 'amd64'
|
|
||||||
qt_ver: 6
|
qt_ver: 6
|
||||||
qt_host: windows
|
|
||||||
qt_arch: ''
|
|
||||||
qt_version: '6.4.2'
|
|
||||||
qt_modules: 'qt5compat qtimageformats'
|
|
||||||
qt_tools: ''
|
|
||||||
|
|
||||||
- os: windows-2022
|
|
||||||
name: "Windows-MSVC-arm64"
|
|
||||||
msystem: ''
|
|
||||||
architecture: 'arm64'
|
|
||||||
vcvars_arch: 'amd64_arm64'
|
|
||||||
qt_ver: 6
|
|
||||||
qt_host: windows
|
|
||||||
qt_arch: 'win64_msvc2019_arm64'
|
|
||||||
qt_version: '6.4.2'
|
|
||||||
qt_modules: 'qt5compat qtimageformats'
|
|
||||||
qt_tools: ''
|
|
||||||
|
|
||||||
- os: macos-12
|
- os: macos-12
|
||||||
name: macOS
|
name: macOS
|
||||||
macosx_deployment_target: 10.15
|
macosx_deployment_target: 10.15
|
||||||
qt_ver: 6
|
qt_ver: 6
|
||||||
qt_host: mac
|
qt_host: mac
|
||||||
qt_arch: ''
|
|
||||||
qt_version: '6.3.0'
|
qt_version: '6.3.0'
|
||||||
qt_modules: 'qt5compat qtimageformats'
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
qt_tools: ''
|
|
||||||
|
|
||||||
- os: macos-12
|
- os: macos-12
|
||||||
name: macOS-Legacy
|
name: macOS-Legacy
|
||||||
@ -94,7 +53,6 @@ jobs:
|
|||||||
qt_host: mac
|
qt_host: mac
|
||||||
qt_version: '5.15.2'
|
qt_version: '5.15.2'
|
||||||
qt_modules: ''
|
qt_modules: ''
|
||||||
qt_tools: ''
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
@ -105,7 +63,6 @@ jobs:
|
|||||||
INSTALL_APPIMAGE_DIR: "install-appdir"
|
INSTALL_APPIMAGE_DIR: "install-appdir"
|
||||||
BUILD_DIR: "build"
|
BUILD_DIR: "build"
|
||||||
CCACHE_VAR: ""
|
CCACHE_VAR: ""
|
||||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
##
|
##
|
||||||
@ -116,8 +73,16 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: 'true'
|
submodules: 'true'
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver == 6
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
config-file: ./.github/codeql/codeql-config.yml
|
||||||
|
queries: security-and-quality
|
||||||
|
languages: cpp, java
|
||||||
|
|
||||||
- name: 'Setup MSYS2'
|
- name: 'Setup MSYS2'
|
||||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
if: runner.os == 'Windows'
|
||||||
uses: msys2/setup-msys2@v2
|
uses: msys2/setup-msys2@v2
|
||||||
with:
|
with:
|
||||||
msystem: ${{ matrix.msystem }}
|
msystem: ${{ matrix.msystem }}
|
||||||
@ -130,26 +95,21 @@ jobs:
|
|||||||
cmake:p
|
cmake:p
|
||||||
extra-cmake-modules:p
|
extra-cmake-modules:p
|
||||||
ninja:p
|
ninja:p
|
||||||
qt6-base:p
|
qt${{ matrix.qt_ver }}-base:p
|
||||||
qt6-svg:p
|
qt${{ matrix.qt_ver }}-svg:p
|
||||||
qt6-imageformats:p
|
qt${{ matrix.qt_ver }}-imageformats:p
|
||||||
quazip-qt6:p
|
quazip-qt${{ matrix.qt_ver }}:p
|
||||||
ccache:p
|
ccache:p
|
||||||
qt6-5compat:p
|
${{ matrix.qt_ver == 6 && 'qt6-5compat:p' || '' }}
|
||||||
|
|
||||||
- name: Force newer ccache
|
|
||||||
if: runner.os == 'Windows' && matrix.msystem == '' && inputs.build_type == 'Debug'
|
|
||||||
run: |
|
|
||||||
choco install ccache --version 4.7.1
|
|
||||||
|
|
||||||
- name: Setup ccache
|
- name: Setup ccache
|
||||||
if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug'
|
if: runner.os != 'Windows' && inputs.build_type == 'Debug'
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.5
|
uses: hendrikmuhs/ccache-action@v1.2.3
|
||||||
with:
|
with:
|
||||||
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }}
|
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}
|
||||||
|
|
||||||
- name: Setup ccache (Windows MinGW-w64)
|
- name: Setup ccache (Windows)
|
||||||
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
|
if: runner.os == 'Windows' && inputs.build_type == 'Debug'
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
run: |
|
run: |
|
||||||
ccache --set-config=cache_dir='${{ github.workspace }}\.ccache'
|
ccache --set-config=cache_dir='${{ github.workspace }}\.ccache'
|
||||||
@ -164,14 +124,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "CCACHE_VAR=ccache" >> $GITHUB_ENV
|
echo "CCACHE_VAR=ccache" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Retrieve ccache cache (Windows MinGW-w64)
|
- name: Retrieve ccache cache (Windows)
|
||||||
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
|
if: runner.os == 'Windows' && inputs.build_type == 'Debug'
|
||||||
uses: actions/cache@v3.0.11
|
uses: actions/cache@v3.0.11
|
||||||
with:
|
with:
|
||||||
path: '${{ github.workspace }}\.ccache'
|
path: '${{ github.workspace }}\.ccache'
|
||||||
key: ${{ matrix.os }}-mingw-w64
|
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ matrix.os }}-mingw-w64
|
${{ matrix.os }}-qt${{ matrix.qt_ver }}
|
||||||
|
|
||||||
- name: Set short version
|
- name: Set short version
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -196,39 +156,16 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
|
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
|
||||||
|
|
||||||
- name: Install host Qt (Windows MSVC arm64)
|
- name: Install Qt (macOS and AppImage)
|
||||||
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
|
if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS'
|
||||||
uses: jurplel/install-qt-action@v3
|
|
||||||
with:
|
|
||||||
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
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
version: ${{ matrix.qt_version }}
|
version: ${{ matrix.qt_version }}
|
||||||
host: ${{ matrix.qt_host }}
|
host: ${{ matrix.qt_host }}
|
||||||
target: 'desktop'
|
target: 'desktop'
|
||||||
arch: ${{ matrix.qt_arch }}
|
|
||||||
modules: ${{ matrix.qt_modules }}
|
modules: ${{ matrix.qt_modules }}
|
||||||
tools: ${{ matrix.qt_tools }}
|
cache: true
|
||||||
cache: ${{ inputs.is_qt_cached }}
|
cache-key-prefix: ${{ matrix.qt_host }}-${{ matrix.qt_version }}-"${{ matrix.qt_modules }}"-qt_cache
|
||||||
|
|
||||||
- name: Install MSVC (Windows MSVC)
|
|
||||||
if: runner.os == 'Windows' && matrix.msystem == ''
|
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
|
||||||
with:
|
|
||||||
vsversion: 2022
|
|
||||||
arch: ${{ matrix.vcvars_arch }}
|
|
||||||
|
|
||||||
- name: Prepare AppImage (Linux)
|
- name: Prepare AppImage (Linux)
|
||||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||||
@ -239,11 +176,6 @@ jobs:
|
|||||||
|
|
||||||
${{ github.workspace }}/.github/scripts/prepare_JREs.sh
|
${{ github.workspace }}/.github/scripts/prepare_JREs.sh
|
||||||
|
|
||||||
- name: Add QT_HOST_PATH var (Windows MSVC arm64)
|
|
||||||
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
|
|
||||||
run: |
|
|
||||||
echo "QT_HOST_PATH=${{ github.workspace }}\HostQt\Qt\${{ matrix.qt_version }}\msvc2019_64" >> $env:GITHUB_ENV
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# CONFIGURE
|
# CONFIGURE
|
||||||
##
|
##
|
||||||
@ -258,26 +190,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja
|
||||||
|
|
||||||
- name: Configure CMake (Windows MinGW-w64)
|
- name: Configure CMake (Windows)
|
||||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
if: runner.os == 'Windows'
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=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=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -G Ninja
|
||||||
|
|
||||||
- name: Configure CMake (Windows MSVC)
|
|
||||||
if: runner.os == 'Windows' && matrix.msystem == ''
|
|
||||||
run: |
|
|
||||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON
|
|
||||||
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix)
|
|
||||||
if ("${{ env.CCACHE_VAR }}")
|
|
||||||
{
|
|
||||||
Copy-Item C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/ccache.exe -Destination C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/cl.exe
|
|
||||||
echo "CLToolExe=cl.exe" >> $env:GITHUB_ENV
|
|
||||||
echo "CLToolPath=C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/" >> $env:GITHUB_ENV
|
|
||||||
echo "TrackFileAccess=false" >> $env:GITHUB_ENV
|
|
||||||
}
|
|
||||||
# Needed for ccache, but also speeds up compile
|
|
||||||
echo "UseMultiToolTask=true" >> $env:GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Configure CMake (Linux)
|
- name: Configure CMake (Linux)
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
@ -293,17 +210,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cmake --build ${{ env.BUILD_DIR }}
|
cmake --build ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
- name: Build (Windows MinGW-w64)
|
- name: Build (Windows)
|
||||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
if: runner.os == 'Windows'
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
run: |
|
run: |
|
||||||
cmake --build ${{ env.BUILD_DIR }}
|
cmake --build ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
- name: Build (Windows MSVC)
|
|
||||||
if: runner.os == 'Windows' && matrix.msystem == ''
|
|
||||||
run: |
|
|
||||||
cmake --build ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }}
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# TEST
|
# TEST
|
||||||
##
|
##
|
||||||
@ -311,18 +223,21 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
if: runner.os != 'Windows'
|
if: runner.os != 'Windows'
|
||||||
run: |
|
run: |
|
||||||
ctest -E "^example64|example$" --test-dir build --output-on-failure
|
ctest --test-dir build --output-on-failure
|
||||||
|
|
||||||
- name: Test (Windows MinGW-w64)
|
- name: Test (Windows)
|
||||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
if: runner.os == 'Windows'
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
run: |
|
run: |
|
||||||
ctest -E "^example64|example$" --test-dir build --output-on-failure
|
ctest --test-dir build --output-on-failure
|
||||||
|
|
||||||
- name: Test (Windows MSVC)
|
##
|
||||||
if: runner.os == 'Windows' && matrix.msystem == '' && matrix.architecture != 'arm64'
|
# CODE SCAN
|
||||||
run: |
|
##
|
||||||
ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }}
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver == 6
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
|
||||||
##
|
##
|
||||||
# PACKAGE BUILDS
|
# PACKAGE BUILDS
|
||||||
@ -358,37 +273,24 @@ jobs:
|
|||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Package (Windows MinGW-w64)
|
- name: Package (Windows)
|
||||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
if: runner.os == 'Windows'
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
run: |
|
run: |
|
||||||
cmake --install ${{ env.BUILD_DIR }}
|
cmake --install ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
- name: Package (Windows MSVC)
|
|
||||||
if: runner.os == 'Windows' && matrix.msystem == ''
|
|
||||||
run: |
|
|
||||||
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }}
|
|
||||||
|
|
||||||
cd ${{ env.INSTALL_DIR }}
|
cd ${{ env.INSTALL_DIR }}
|
||||||
if ("${{ matrix.qt_ver }}" -eq "5")
|
if [ "${{ matrix.qt_ver }}" == "5" ]; then
|
||||||
{
|
cp /clang32/bin/libcrypto-1_1.dll /clang32/bin/libssl-1_1.dll ./
|
||||||
Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll
|
fi
|
||||||
Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Package (Windows MinGW-w64, portable)
|
- name: Package (Windows, portable)
|
||||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
if: runner.os == 'Windows'
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
run: |
|
run: |
|
||||||
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
||||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||||
|
|
||||||
- name: Package (Windows MSVC, portable)
|
|
||||||
if: runner.os == 'Windows' && matrix.msystem == ''
|
|
||||||
run: |
|
|
||||||
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
|
||||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
|
||||||
|
|
||||||
- name: Package (Windows, installer)
|
- name: Package (Windows, installer)
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
run: |
|
run: |
|
||||||
@ -509,76 +411,5 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||||
path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||||
snap:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
if: inputs.build_type == 'Debug'
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: 'true'
|
|
||||||
- name: Set short version
|
|
||||||
shell: bash
|
|
||||||
if: inputs.build_type == 'Debug'
|
|
||||||
run: |
|
|
||||||
ver_short=`git rev-parse --short HEAD`
|
|
||||||
echo "VERSION=$ver_short" >> $GITHUB_ENV
|
|
||||||
- name: Package Snap (Linux)
|
|
||||||
id: snapcraft
|
|
||||||
if: inputs.build_type == 'Debug'
|
|
||||||
uses: snapcore/action-build@v1
|
|
||||||
- name: Upload Snap (Linux)
|
|
||||||
if: inputs.build_type == 'Debug'
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: prismlauncher_${{ env.VERSION }}_amd64.snap
|
|
||||||
path: ${{ steps.snapcraft.outputs.snap }}
|
|
||||||
|
|
||||||
flatpak:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: bilelmoussaoui/flatpak-github-actions:kde-5.15-22.08
|
|
||||||
options: --privileged
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
if: inputs.build_type == 'Debug'
|
|
||||||
with:
|
|
||||||
submodules: 'true'
|
|
||||||
- name: Build Flatpak (Linux)
|
|
||||||
if: inputs.build_type == 'Debug'
|
|
||||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v4
|
|
||||||
with:
|
|
||||||
bundle: "Prism Launcher.flatpak"
|
|
||||||
manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml
|
|
||||||
cache-key: flatpak-${{ github.sha }}-x86_64
|
|
||||||
|
|
||||||
nix:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
package:
|
|
||||||
- prismlauncher
|
|
||||||
- prismlauncher-qt5
|
|
||||||
steps:
|
|
||||||
- name: Clone repository
|
|
||||||
if: inputs.build_type == 'Debug'
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: 'true'
|
|
||||||
- name: Install nix
|
|
||||||
if: inputs.build_type == 'Debug'
|
|
||||||
uses: cachix/install-nix-action@v18
|
|
||||||
with:
|
|
||||||
install_url: https://nixos.org/nix/install
|
|
||||||
extra_nix_config: |
|
|
||||||
auto-optimise-store = true
|
|
||||||
experimental-features = nix-command flakes
|
|
||||||
- uses: cachix/cachix-action@v12
|
|
||||||
if: inputs.build_type == 'Debug'
|
|
||||||
with:
|
|
||||||
name: prismlauncher
|
|
||||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
|
||||||
- name: Build
|
|
||||||
if: inputs.build_type == 'Debug'
|
|
||||||
run: nix build .#${{ matrix.package }} --print-build-logs
|
|
||||||
|
35
.github/workflows/codeql.yml
vendored
35
.github/workflows/codeql.yml
vendored
@ -1,35 +0,0 @@
|
|||||||
name: "CodeQL Code Scanning"
|
|
||||||
|
|
||||||
on: [ push, pull_request, workflow_dispatch ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
CodeQL:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: 'true'
|
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v2
|
|
||||||
with:
|
|
||||||
config-file: ./.github/codeql/codeql-config.yml
|
|
||||||
queries: security-and-quality
|
|
||||||
languages: cpp, java
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
run:
|
|
||||||
sudo apt-get -y update
|
|
||||||
|
|
||||||
sudo apt-get -y install ninja-build extra-cmake-modules scdoc qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
|
|
||||||
|
|
||||||
- name: Configure and Build
|
|
||||||
run: |
|
|
||||||
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DLauncher_QT_VERSION_MAJOR=5 -G Ninja
|
|
||||||
|
|
||||||
cmake --build build
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v2
|
|
6
.github/workflows/trigger_builds.yml
vendored
6
.github/workflows/trigger_builds.yml
vendored
@ -3,11 +3,12 @@ name: Build Application
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches-ignore:
|
branches-ignore:
|
||||||
- 'renovate/**'
|
- 'stable'
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
- '**/LICENSE'
|
- '**/LICENSE'
|
||||||
- 'flake.lock'
|
- 'flake.lock'
|
||||||
|
- '**.nix'
|
||||||
- 'packages/**'
|
- 'packages/**'
|
||||||
- '.github/ISSUE_TEMPLATE/**'
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
- '.markdownlint**'
|
- '.markdownlint**'
|
||||||
@ -16,6 +17,7 @@ on:
|
|||||||
- '**.md'
|
- '**.md'
|
||||||
- '**/LICENSE'
|
- '**/LICENSE'
|
||||||
- 'flake.lock'
|
- 'flake.lock'
|
||||||
|
- '**.nix'
|
||||||
- 'packages/**'
|
- 'packages/**'
|
||||||
- '.github/ISSUE_TEMPLATE/**'
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
- '.markdownlint**'
|
- '.markdownlint**'
|
||||||
@ -28,7 +30,5 @@ jobs:
|
|||||||
uses: ./.github/workflows/build.yml
|
uses: ./.github/workflows/build.yml
|
||||||
with:
|
with:
|
||||||
build_type: Debug
|
build_type: Debug
|
||||||
is_qt_cached: true
|
|
||||||
secrets:
|
secrets:
|
||||||
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
|
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
|
||||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
|
36
.github/workflows/trigger_release.yml
vendored
36
.github/workflows/trigger_release.yml
vendored
@ -12,7 +12,6 @@ jobs:
|
|||||||
uses: ./.github/workflows/build.yml
|
uses: ./.github/workflows/build.yml
|
||||||
with:
|
with:
|
||||||
build_type: Release
|
build_type: Release
|
||||||
is_qt_cached: false
|
|
||||||
secrets:
|
secrets:
|
||||||
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
|
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
|
||||||
|
|
||||||
@ -46,26 +45,13 @@ jobs:
|
|||||||
|
|
||||||
tar -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
|
tar -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
|
||||||
|
|
||||||
for d in PrismLauncher-Windows-MSVC*; do
|
for d in PrismLauncher-Windows-*; do
|
||||||
cd "${d}" || continue
|
cd "${d}" || continue
|
||||||
LEGACY="$(echo -n ${d} | grep -o Legacy || true)"
|
LEGACY="$(echo -n ${d} | grep -o Legacy || true)"
|
||||||
ARM64="$(echo -n ${d} | grep -o arm64 || true)"
|
|
||||||
INST="$(echo -n ${d} | grep -o Setup || true)"
|
INST="$(echo -n ${d} | grep -o Setup || true)"
|
||||||
PORT="$(echo -n ${d} | grep -o Portable || true)"
|
PORT="$(echo -n ${d} | grep -o Portable || true)"
|
||||||
NAME="PrismLauncher-Windows-MSVC"
|
NAME="PrismLauncher-Windows"
|
||||||
test -z "${LEGACY}" || NAME="${NAME}-Legacy"
|
test -z "${LEGACY}" || NAME="${NAME}-Legacy"
|
||||||
test -z "${ARM64}" || NAME="${NAME}-arm64"
|
|
||||||
test -z "${PORT}" || NAME="${NAME}-Portable"
|
|
||||||
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
|
|
||||||
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
|
|
||||||
cd ..
|
|
||||||
done
|
|
||||||
|
|
||||||
for d in PrismLauncher-Windows-MinGW-w64*; do
|
|
||||||
cd "${d}" || continue
|
|
||||||
INST="$(echo -n ${d} | grep -o Setup || true)"
|
|
||||||
PORT="$(echo -n ${d} | grep -o Portable || true)"
|
|
||||||
NAME="PrismLauncher-Windows-MinGW-w64"
|
|
||||||
test -z "${PORT}" || NAME="${NAME}-Portable"
|
test -z "${PORT}" || NAME="${NAME}-Portable"
|
||||||
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
|
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
|
||||||
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
|
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
|
||||||
@ -86,20 +72,14 @@ jobs:
|
|||||||
PrismLauncher-Linux-${{ env.VERSION }}.tar.gz
|
PrismLauncher-Linux-${{ env.VERSION }}.tar.gz
|
||||||
PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz
|
PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||||
PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage
|
PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage
|
||||||
|
PrismLauncher-Windows-Legacy-${{ env.VERSION }}.zip
|
||||||
PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
|
PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
|
||||||
PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||||
PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip
|
PrismLauncher-Windows-Legacy-Portable-${{ env.VERSION }}.zip
|
||||||
PrismLauncher-Windows-MinGW-w64-Portable-${{ env.VERSION }}.zip
|
PrismLauncher-Windows-Legacy-Setup-${{ env.VERSION }}.exe
|
||||||
PrismLauncher-Windows-MinGW-w64-Setup-${{ env.VERSION }}.exe
|
PrismLauncher-Windows-${{ env.VERSION }}.zip
|
||||||
PrismLauncher-Windows-MSVC-Legacy-${{ env.VERSION }}.zip
|
PrismLauncher-Windows-Portable-${{ env.VERSION }}.zip
|
||||||
PrismLauncher-Windows-MSVC-Legacy-Portable-${{ env.VERSION }}.zip
|
PrismLauncher-Windows-Setup-${{ env.VERSION }}.exe
|
||||||
PrismLauncher-Windows-MSVC-Legacy-Setup-${{ env.VERSION }}.exe
|
|
||||||
PrismLauncher-Windows-MSVC-arm64-${{ env.VERSION }}.zip
|
|
||||||
PrismLauncher-Windows-MSVC-arm64-Portable-${{ env.VERSION }}.zip
|
|
||||||
PrismLauncher-Windows-MSVC-arm64-Setup-${{ env.VERSION }}.exe
|
|
||||||
PrismLauncher-Windows-MSVC-${{ env.VERSION }}.zip
|
|
||||||
PrismLauncher-Windows-MSVC-Portable-${{ env.VERSION }}.zip
|
|
||||||
PrismLauncher-Windows-MSVC-Setup-${{ env.VERSION }}.exe
|
|
||||||
PrismLauncher-macOS-${{ env.VERSION }}.tar.gz
|
PrismLauncher-macOS-${{ env.VERSION }}.tar.gz
|
||||||
PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz
|
PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz
|
||||||
PrismLauncher-${{ env.VERSION }}.tar.gz
|
PrismLauncher-${{ env.VERSION }}.tar.gz
|
||||||
|
2
.github/workflows/winget.yml
vendored
2
.github/workflows/winget.yml
vendored
@ -11,5 +11,5 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
identifier: PrismLauncher.PrismLauncher
|
identifier: PrismLauncher.PrismLauncher
|
||||||
version: ${{ github.event.release.tag_name }}
|
version: ${{ github.event.release.tag_name }}
|
||||||
installers-regex: 'PrismLauncher-Windows-MSVC(:?-arm64|-Legacy)?-Setup-.+\.exe$'
|
installers-regex: 'PrismLauncher-Windows-Setup-.+\.exe$'
|
||||||
token: ${{ secrets.WINGET_TOKEN }}
|
token: ${{ secrets.WINGET_TOKEN }}
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -47,6 +47,3 @@ result/
|
|||||||
# Flatpak
|
# Flatpak
|
||||||
.flatpak-builder
|
.flatpak-builder
|
||||||
flatbuild
|
flatbuild
|
||||||
|
|
||||||
# Snap
|
|
||||||
*.snap
|
|
||||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -10,9 +10,3 @@
|
|||||||
[submodule "libraries/libnbtplusplus"]
|
[submodule "libraries/libnbtplusplus"]
|
||||||
path = libraries/libnbtplusplus
|
path = libraries/libnbtplusplus
|
||||||
url = https://github.com/PrismLauncher/libnbtplusplus.git
|
url = https://github.com/PrismLauncher/libnbtplusplus.git
|
||||||
[submodule "libraries/zlib"]
|
|
||||||
path = libraries/zlib
|
|
||||||
url = https://github.com/madler/zlib.git
|
|
||||||
[submodule "libraries/extra-cmake-modules"]
|
|
||||||
path = libraries/extra-cmake-modules
|
|
||||||
url = https://github.com/KDE/extra-cmake-modules
|
|
||||||
|
163
CMakeLists.txt
163
CMakeLists.txt
@ -1,5 +1,10 @@
|
|||||||
cmake_minimum_required(VERSION 3.15) # minimum version required by QuaZip
|
cmake_minimum_required(VERSION 3.15) # minimum version required by QuaZip
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
|
||||||
|
cmake_policy(SET CMP0020 OLD)
|
||||||
|
endif()
|
||||||
|
|
||||||
project(Launcher)
|
project(Launcher)
|
||||||
|
|
||||||
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
|
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
|
||||||
@ -27,61 +32,13 @@ set(CMAKE_C_STANDARD_REQUIRED true)
|
|||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
include(GenerateExportHeader)
|
include(GenerateExportHeader)
|
||||||
if(MSVC)
|
set(CMAKE_CXX_FLAGS "-Wall -pedantic -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}")
|
||||||
# /GS Adds buffer security checks, default on but incuded anyway to mirror gcc's fstack-protector flag
|
|
||||||
# /permissive- specify standards-conforming compiler behavior, also enabled by Qt6, default on with std:c++20
|
|
||||||
# Use /W4 as /Wall includes unnesserey warnings such as added padding to structs
|
|
||||||
set(CMAKE_CXX_FLAGS "/GS /permissive- /W4 ${CMAKE_CXX_FLAGS}")
|
|
||||||
|
|
||||||
# LINK accepts /SUBSYSTEM whics sets if we are a WINDOWS (gui) or a CONSOLE programs
|
|
||||||
# This implicitly selects an entrypoint specific to the subsystem selected
|
|
||||||
# qtmain/QtEntryPointLib provides the correct entrypoint (wWinMain) for gui programs
|
|
||||||
# Additinaly LINK autodetects we use a GUI so we can omit /SUBSYSTEM
|
|
||||||
# This allows tests to still use have console without using seperate linker flags
|
|
||||||
# /LTCG allows for linking wholy optimizated programs
|
|
||||||
# /MANIFEST:NO disables generating a manifest file, we instead provide our own
|
|
||||||
# /STACK sets the stack reserve size, ATL's pack list needs 3-4 MiB as of November 2022, provide 8 MiB
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "/LTCG /MANIFEST:NO /STACK:8388608 ${CMAKE_EXE_LINKER_FLAGS}")
|
|
||||||
|
|
||||||
# /GL enables whole program optimizations
|
|
||||||
# /Gw helps reduce binary size
|
|
||||||
# /Gy allows the compiler to package individual functions
|
|
||||||
# /guard:cf enables control flow guard
|
|
||||||
foreach(lang C CXX)
|
|
||||||
set("CMAKE_${lang}_FLAGS_RELEASE" "/GL /Gw /Gy /guard:cf")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# See https://github.com/ccache/ccache/issues/1040
|
|
||||||
# Note, CMake 3.25 replaces this with CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
|
|
||||||
# See https://cmake.org/cmake/help/v3.25/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.html
|
|
||||||
foreach(config DEBUG RELWITHDEBINFO)
|
|
||||||
foreach(lang C CXX)
|
|
||||||
set(flags_var "CMAKE_${lang}_FLAGS_${config}")
|
|
||||||
string(REGEX REPLACE "/Z[Ii]" "/Z7" ${flags_var} "${${flags_var}}")
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDLL")
|
|
||||||
set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release "")
|
|
||||||
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release "")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "-Wall -pedantic -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}")
|
|
||||||
|
|
||||||
# ATL's pack list needs more than the default 1 Mib stack on windows
|
|
||||||
if(WIN32)
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--stack,8388608 ${CMAKE_EXE_LINKER_FLAGS}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Fix build with Qt 5.13
|
# Fix build with Qt 5.13
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_DISABLE_DEPRECATED_BEFORE=0x050C00")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_DISABLE_DEPRECATED_BEFORE=0x050C00")
|
||||||
|
|
||||||
# Fix aarch64 build for toml++
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0")
|
|
||||||
|
|
||||||
# set CXXFLAGS for build targets
|
# set CXXFLAGS for build targets
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}")
|
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||||
|
|
||||||
@ -91,18 +48,11 @@ if(ENABLE_LTO)
|
|||||||
include(CheckIPOSupported)
|
include(CheckIPOSupported)
|
||||||
check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error)
|
check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error)
|
||||||
|
|
||||||
if(ipo_supported)
|
if(ipo_supported AND (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel"))
|
||||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
|
message(STATUS "IPO / LTO enabled")
|
||||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE)
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
if(CMAKE_BUILD_TYPE)
|
elseif(ipo_supported)
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
|
message(STATUS "Not enabling IPO / LTO on debug builds")
|
||||||
message(STATUS "IPO / LTO enabled")
|
|
||||||
else()
|
|
||||||
message(STATUS "Not enabling IPO / LTO on debug builds")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(STATUS "IPO / LTO will only be enabled for release builds")
|
|
||||||
endif()
|
|
||||||
else()
|
else()
|
||||||
message(STATUS "IPO / LTO not supported: <${ipo_error}>")
|
message(STATUS "IPO / LTO not supported: <${ipo_error}>")
|
||||||
endif()
|
endif()
|
||||||
@ -110,20 +60,8 @@ endif()
|
|||||||
|
|
||||||
option(BUILD_TESTING "Build the testing tree." ON)
|
option(BUILD_TESTING "Build the testing tree." ON)
|
||||||
|
|
||||||
find_package(ECM QUIET NO_MODULE)
|
find_package(ECM REQUIRED NO_MODULE)
|
||||||
if(NOT ECM_FOUND)
|
set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}")
|
||||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/CMakeLists.txt")
|
|
||||||
message(STATUS "Using bundled ECM")
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/modules;${CMAKE_MODULE_PATH}")
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR
|
|
||||||
" Could not find ECM\n \n"
|
|
||||||
" Either install ECM using the system package manager or clone submodules\n"
|
|
||||||
" Submodules can be cloned with 'git submodule update --init --recursive'")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}")
|
|
||||||
endif()
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
include(ECMAddTests)
|
include(ECMAddTests)
|
||||||
if(BUILD_TESTING)
|
if(BUILD_TESTING)
|
||||||
@ -138,8 +76,8 @@ set(Launcher_NEWS_OPEN_URL "https://prismlauncher.org/news" CACHE STRING "URL th
|
|||||||
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
|
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
|
||||||
|
|
||||||
######## Set version numbers ########
|
######## Set version numbers ########
|
||||||
set(Launcher_VERSION_MAJOR 6)
|
set(Launcher_VERSION_MAJOR 5)
|
||||||
set(Launcher_VERSION_MINOR 3)
|
set(Launcher_VERSION_MINOR 1)
|
||||||
|
|
||||||
set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}")
|
set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}")
|
||||||
set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.0.0")
|
set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.0.0")
|
||||||
@ -208,16 +146,6 @@ set(Launcher_BUILD_TIMESTAMP "${TODAY}")
|
|||||||
|
|
||||||
################################ 3rd Party Libs ################################
|
################################ 3rd Party Libs ################################
|
||||||
|
|
||||||
# Successive configurations of cmake without cleaning the build dir will cause zlib fallback to fail due to cached values
|
|
||||||
# Record when fallback triggered and skip this find_package
|
|
||||||
if(NOT Launcher_FORCE_BUNDLED_LIBS AND NOT FORCE_BUNDLED_ZLIB)
|
|
||||||
find_package(ZLIB QUIET)
|
|
||||||
endif()
|
|
||||||
if(NOT ZLIB_FOUND)
|
|
||||||
set(FORCE_BUNDLED_ZLIB TRUE CACHE BOOL "")
|
|
||||||
mark_as_advanced(FORCE_BUNDLED_ZLIB)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Find the required Qt parts
|
# Find the required Qt parts
|
||||||
include(QtVersionlessBackport)
|
include(QtVersionlessBackport)
|
||||||
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
||||||
@ -236,7 +164,7 @@ if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -D_UNICODE")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -D_UNICODE")
|
||||||
elseif(Launcher_QT_VERSION_MAJOR EQUAL 6)
|
elseif(Launcher_QT_VERSION_MAJOR EQUAL 6)
|
||||||
set(QT_VERSION_MAJOR 6)
|
set(QT_VERSION_MAJOR 6)
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Core CoreTools Widgets Concurrent Network Test Xml Core5Compat)
|
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml Core5Compat)
|
||||||
list(APPEND Launcher_QT_LIBS Qt6::Core5Compat)
|
list(APPEND Launcher_QT_LIBS Qt6::Core5Compat)
|
||||||
|
|
||||||
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
||||||
@ -250,16 +178,12 @@ else()
|
|||||||
message(FATAL_ERROR "Qt version ${Launcher_QT_VERSION_MAJOR} is not supported")
|
message(FATAL_ERROR "Qt version ${Launcher_QT_VERSION_MAJOR} is not supported")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
include(ECMQueryQt)
|
||||||
include(ECMQueryQt)
|
ecm_query_qt(QT_PLUGINS_DIR QT_INSTALL_PLUGINS)
|
||||||
ecm_query_qt(QT_PLUGINS_DIR QT_INSTALL_PLUGINS)
|
ecm_query_qt(QT_LIBS_DIR QT_INSTALL_LIBS)
|
||||||
ecm_query_qt(QT_LIBS_DIR QT_INSTALL_LIBS)
|
ecm_query_qt(QT_LIBEXECS_DIR QT_INSTALL_LIBEXECS)
|
||||||
ecm_query_qt(QT_LIBEXECS_DIR QT_INSTALL_LIBEXECS)
|
ecm_query_qt(QT_DATA_DIR QT_HOST_DATA)
|
||||||
else()
|
set(QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs)
|
||||||
set(QT_PLUGINS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_PLUGINS})
|
|
||||||
set(QT_LIBS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_LIBS})
|
|
||||||
set(QT_LIBEXECS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_LIBEXECS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# NOTE: Qt 6 already sets this by default
|
# NOTE: Qt 6 already sets this by default
|
||||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
if (Qt5_POSITION_INDEPENDENT_CODE)
|
||||||
@ -274,8 +198,6 @@ if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
|||||||
find_package(ghc_filesystem QUIET)
|
find_package(ghc_filesystem QUIET)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(ECMQtDeclareLoggingCategory)
|
|
||||||
|
|
||||||
####################################### Program Info #######################################
|
####################################### Program Info #######################################
|
||||||
|
|
||||||
set(Launcher_APP_BINARY_NAME "prismlauncher" CACHE STRING "Name of the Launcher binary")
|
set(Launcher_APP_BINARY_NAME "prismlauncher" CACHE STRING "Name of the Launcher binary")
|
||||||
@ -325,11 +247,13 @@ if(UNIX AND APPLE)
|
|||||||
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
|
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
|
||||||
|
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
include(KDEInstallDirs)
|
|
||||||
|
|
||||||
set(BINARY_DEST_DIR "bin")
|
set(BINARY_DEST_DIR "bin")
|
||||||
set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}")
|
set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}")
|
||||||
set(JARS_DEST_DIR "share/${Launcher_APP_BINARY_NAME}")
|
set(JARS_DEST_DIR "share/${Launcher_APP_BINARY_NAME}")
|
||||||
|
set(LAUNCHER_DESKTOP_DEST_DIR "share/applications" CACHE STRING "Path to the desktop file directory")
|
||||||
|
set(LAUNCHER_METAINFO_DEST_DIR "share/metainfo" CACHE STRING "Path to the metainfo directory")
|
||||||
|
set(LAUNCHER_ICON_DEST_DIR "share/icons/hicolor/scalable/apps" CACHE STRING "Path to the scalable icon directory")
|
||||||
|
set(LAUNCHER_MAN_DEST_DIR "share/man/man6" CACHE STRING "Path to the man page directory")
|
||||||
|
|
||||||
# install as bundle with no dependencies included
|
# install as bundle with no dependencies included
|
||||||
set(INSTALL_BUNDLE "nodeps")
|
set(INSTALL_BUNDLE "nodeps")
|
||||||
@ -337,13 +261,12 @@ elseif(UNIX)
|
|||||||
# Set RPATH
|
# Set RPATH
|
||||||
SET(Launcher_BINARY_RPATH "$ORIGIN/")
|
SET(Launcher_BINARY_RPATH "$ORIGIN/")
|
||||||
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${KDE_INSTALL_APPDIR})
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${LAUNCHER_DESKTOP_DEST_DIR})
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${KDE_INSTALL_METAINFODIR})
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${LAUNCHER_METAINFO_DEST_DIR})
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps")
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION ${LAUNCHER_ICON_DEST_DIR})
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_mrpack_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR})
|
|
||||||
|
|
||||||
if(Launcher_ManPage)
|
if(Launcher_ManPage)
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION "${KDE_INSTALL_MANDIR}/man6")
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION ${LAUNCHER_MAN_DEST_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Install basic runner script if component "portable" is selected
|
# Install basic runner script if component "portable" is selected
|
||||||
@ -383,32 +306,6 @@ add_subdirectory(libraries/systeminfo) # system information library
|
|||||||
add_subdirectory(libraries/hoedown) # markdown parser
|
add_subdirectory(libraries/hoedown) # markdown parser
|
||||||
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
||||||
add_subdirectory(libraries/javacheck) # java compatibility checker
|
add_subdirectory(libraries/javacheck) # java compatibility checker
|
||||||
if(FORCE_BUNDLED_ZLIB)
|
|
||||||
message(STATUS "Using bundled zlib")
|
|
||||||
|
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) # Suppress cmake warnings and allow INTERPROCEDURAL_OPTIMIZATION for zlib
|
|
||||||
set(SKIP_INSTALL_ALL ON)
|
|
||||||
add_subdirectory(libraries/zlib EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
# On OS where unistd.h exists, zlib's generated header defines `Z_HAVE_UNISTD_H`, while the included header does not.
|
|
||||||
# We cannot safely undo the rename on those systems, and they generally have packages for zlib anyway.
|
|
||||||
check_include_file(unistd.h NEED_GENERATED_ZCONF)
|
|
||||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h.included" AND NOT NEED_GENERATED_ZCONF)
|
|
||||||
# zlib's cmake script renames a file, dirtying the submodule, see https://github.com/madler/zlib/issues/162
|
|
||||||
message(STATUS "Undoing Rename")
|
|
||||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h")
|
|
||||||
file(RENAME "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h.included" "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/libraries/zlib" "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib" CACHE STRING "" FORCE)
|
|
||||||
set_target_properties(zlibstatic PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIR}")
|
|
||||||
add_library(ZLIB::ZLIB ALIAS zlibstatic)
|
|
||||||
set(ZLIB_LIBRARY ZLIB::ZLIB CACHE STRING "zlib library name")
|
|
||||||
|
|
||||||
find_package(ZLIB REQUIRED)
|
|
||||||
else()
|
|
||||||
message(STATUS "Using system zlib")
|
|
||||||
endif()
|
|
||||||
if (FORCE_BUNDLED_QUAZIP)
|
if (FORCE_BUNDLED_QUAZIP)
|
||||||
message(STATUS "Using bundled QuaZip")
|
message(STATUS "Using bundled QuaZip")
|
||||||
set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts.
|
set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts.
|
||||||
|
44
COPYING.md
44
COPYING.md
@ -1,7 +1,7 @@
|
|||||||
## Prism Launcher
|
## Prism Launcher
|
||||||
|
|
||||||
Prism Launcher - Minecraft Launcher
|
Prism Launcher - Minecraft Launcher
|
||||||
Copyright (C) 2022-2023 Prism Launcher Contributors
|
Copyright (C) 2022 Prism Launcher Contributors
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -398,45 +398,3 @@
|
|||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
## Breeze icons
|
|
||||||
|
|
||||||
Copyright (C) 2014 Uri Herrera <uri_herrera@nitrux.in> and others
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 3 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
## Oxygen Icons
|
|
||||||
|
|
||||||
The Oxygen Icon Theme
|
|
||||||
Copyright (C) 2007 Nuno Pinheiro <nuno@oxygen-icons.org>
|
|
||||||
Copyright (C) 2007 David Vignoni <david@icon-king.com>
|
|
||||||
Copyright (C) 2007 David Miller <miller@oxygen-icons.org>
|
|
||||||
Copyright (C) 2007 Johann Ollivier Lapeyre <johann@oxygen-icons.org>
|
|
||||||
Copyright (C) 2007 Kenneth Wimer <kwwii@bootsplash.org>
|
|
||||||
Copyright (C) 2007 Riccardo Iaconelli <riccardo@oxygen-icons.org>
|
|
||||||
|
|
||||||
and others
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 3 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
91
README.md
91
README.md
@ -1,102 +1,29 @@
|
|||||||
<p align="left">
|
<p align="center">
|
||||||
<picture>
|
<img src="./program_info/org.prismlauncher.PrismLauncher.logo.svg#gh-light-mode-only" alt="Prism Launcher logo" width="50%"/>
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="/program_info/org.prismlauncher.PrismLauncher.logo-darkmode.svg">
|
<img src="./program_info/org.prismlauncher.PrismLauncher.logo-darkmode.svg#gh-dark-mode-only" alt="Prism Launcher logo" width="50%"/>
|
||||||
<source media="(prefers-color-scheme: light)" srcset="/program_info/org.prismlauncher.PrismLauncher.logo.svg">
|
|
||||||
<img alt="Prism Launcher" src="/program_info/org.prismlauncher.PrismLauncher.logo.svg" width="50%">
|
|
||||||
</picture>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
Prism Launcher is a custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.
|
Prism Launcher is a custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.
|
||||||
|
|
||||||
This is a **fork** of the MultiMC Launcher and is not endorsed by MultiMC.
|
We are working on a website and other media, for more info we have a [Discord server](https://discord.gg/prismlauncher).
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
<a href="https://repology.org/project/prismlauncher/versions">
|
- All downloads and instructions for Prism Launcher will soon be available.
|
||||||
<img src="https://repology.org/badge/vertical-allrepos/prismlauncher.svg" alt="Packaging status" align="right">
|
- Last build status can be found [here](https://github.com/PrismLauncher/PrismLauncher/actions).
|
||||||
</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).
|
|
||||||
|
|
||||||
### Development Builds
|
### 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.
|
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.
|
||||||
|
|
||||||
Prebuilt Development builds are provided for **Linux**, **Windows** and **macOS**.
|
Portable builds are provided for AppImage on Linux, Windows, and macOS.
|
||||||
|
|
||||||
For **Arch**, **Debian**, **Fedora**, **OpenSUSE (Tumbleweed)** and **Gentoo**, respectively, you can use these packages for the latest development versions:
|
## Help & Support
|
||||||
|
|
||||||
[](https://aur.archlinux.org/packages/prismlauncher-git/) [](https://aur.archlinux.org/packages/prismlauncher-qt5-git/) [](https://mpr.makedeb.org/packages/prismlauncher-git) [](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [](https://build.opensuse.org/project/show/home:getchoo) [](https://packages.gentoo.org/packages/games-action/prismlauncher)
|
|
||||||
|
|
||||||
## Community & Support
|
[](https://discord.gg/hX4g537UNE)
|
||||||
|
|
||||||
Feel free to create a GitHub issue if you find a bug or want to suggest a new feature. We have multiple community spaces where other community members can help you.
|
|
||||||
|
|
||||||
#### Join our Discord server:
|
|
||||||
[](https://discord.gg/prismlauncher)
|
|
||||||
|
|
||||||
#### Join our Matrix space:
|
|
||||||
[](https://matrix.to/#/#prismlauncher:matrix.org)
|
|
||||||
|
|
||||||
#### Join our Subreddit:
|
|
||||||
[](https://www.reddit.com/r/PrismLauncher/)
|
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
If you want to build Prism Launcher yourself, check the [Build Instructions](https://prismlauncher.org/wiki/development/build-instructions/).
|
|
||||||
|
|
||||||
## Translations
|
|
||||||
|
|
||||||
The translation effort for PrismLauncher is hosted on [Weblate](https://hosted.weblate.org/projects/prismlauncher/launcher/) and information about translating Prism Launcher is available at <https://github.com/PrismLauncher/Translations>
|
|
||||||
|
|
||||||
## Forking/Redistributing/Custom builds policy
|
|
||||||
|
|
||||||
We don't care what you do with your fork/custom build as long as you follow the terms of the [license](LICENSE) (this is a legal responsibility), and if you made code changes rather than just packaging a custom build, please do the following as a basic courtesy:
|
|
||||||
|
|
||||||
- Make it clear that your fork is not PrismLauncher and is not endorsed by or affiliated with the PrismLauncher project (<https://prismlauncher.org>).
|
|
||||||
- Go through [CMakeLists.txt](CMakeLists.txt) and change PrismLauncher's API keys to your own or set them to empty strings (`""`) to disable them (this way the program will still compile but the functionality requiring those keys will be disabled).
|
|
||||||
|
|
||||||
If you have any questions or want any clarification on the above conditions please make an issue and ask us.
|
|
||||||
|
|
||||||
Be aware that if you build this software without removing the provided API keys in [CMakeLists.txt](CMakeLists.txt) you are accepting the following terms and conditions:
|
|
||||||
|
|
||||||
- [Microsoft Identity Platform Terms of Use](https://docs.microsoft.com/en-us/legal/microsoft-identity-platform/terms-of-use)
|
|
||||||
- [CurseForge 3rd Party API Terms and Conditions](https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions)
|
|
||||||
|
|
||||||
If you do not agree with these terms and conditions, then remove the associated API keys from the [CMakeLists.txt](CMakeLists.txt) file by setting them to an empty string (`""`).
|
|
||||||
|
|
||||||
## Sponsors & Partners
|
|
||||||
|
|
||||||
We thank all the wonderful backers over at Open Collective! Support Prism Launcher by [becoming a backer](https://opencollective.com/prismlauncher).
|
|
||||||
|
|
||||||
[](https://opencollective.com/prismlauncher#backers)
|
|
||||||
|
|
||||||
Thanks to JetBrains for providing us a few licenses for all their products, as part of their [Open Source program](https://www.jetbrains.com/opensource/).
|
|
||||||
|
|
||||||
[](https://www.jetbrains.com/opensource/)
|
|
||||||
|
|
||||||
Thanks to Weblate for hosting our translation efforts.
|
|
||||||
|
|
||||||
<a href="https://hosted.weblate.org/engage/prismlauncher/">
|
|
||||||
<img src="https://hosted.weblate.org/widgets/prismlauncher/-/open-graph.png" alt="Translation status" width="300" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
Thanks to Netlify for providing us their excellent web services, as part of their [Open Source program](https://www.netlify.com/open-source/)
|
|
||||||
|
|
||||||
<a href="https://www.netlify.com"> <img src="https://www.netlify.com/v3/img/components/netlify-color-accent.svg" alt="Deploys by Netlify" /> </a>
|
|
||||||
|
|
||||||
Thanks to the awesome people over at [MacStadium](https://www.macstadium.com/), for providing M1-Macs for development purposes!
|
|
||||||
|
|
||||||
<a href="https://www.macstadium.com"><img src="https://uploads-ssl.webflow.com/5ac3c046c82724970fc60918/5c019d917bba312af7553b49_MacStadium-developerlogo.png" alt="Powered by MacStadium" width="300"></a>
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
All launcher code is available under the GPL-3.0-only license.
|
All launcher code is available under the GPL-3.0-only license.
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
The logo and related assets are under the CC BY-SA 4.0 license.
|
|
||||||
|
@ -76,9 +76,7 @@ Config::Config()
|
|||||||
|
|
||||||
// Assume that builds outside of Git repos are "stable"
|
// Assume that builds outside of Git repos are "stable"
|
||||||
if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND")
|
if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND")
|
||||||
|| GIT_TAG == QStringLiteral("GITDIR-NOTFOUND")
|
|| GIT_TAG == QStringLiteral("GITDIR-NOTFOUND"))
|
||||||
|| GIT_REFSPEC == QStringLiteral("")
|
|
||||||
|| GIT_TAG == QStringLiteral("GIT-NOTFOUND"))
|
|
||||||
{
|
{
|
||||||
GIT_REFSPEC = "refs/heads/stable";
|
GIT_REFSPEC = "refs/heads/stable";
|
||||||
GIT_TAG = versionString();
|
GIT_TAG = versionString();
|
||||||
|
@ -161,8 +161,6 @@ class Config {
|
|||||||
QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2";
|
QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2";
|
||||||
QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2";
|
QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2";
|
||||||
|
|
||||||
QString FLAME_BASE_URL = "https://api.curseforge.com/v1";
|
|
||||||
|
|
||||||
QString versionString() const;
|
QString versionString() const;
|
||||||
/**
|
/**
|
||||||
* \brief Converts the Version to a string.
|
* \brief Converts the Version to a string.
|
||||||
|
@ -44,28 +44,5 @@
|
|||||||
<string>${MACOSX_SPARKLE_UPDATE_PUBLIC_KEY}</string>
|
<string>${MACOSX_SPARKLE_UPDATE_PUBLIC_KEY}</string>
|
||||||
<key>SUFeedURL</key>
|
<key>SUFeedURL</key>
|
||||||
<string>${MACOSX_SPARKLE_UPDATE_FEED_URL}</string>
|
<string>${MACOSX_SPARKLE_UPDATE_FEED_URL}</string>
|
||||||
<key>CFBundleDocumentTypes</key>
|
|
||||||
<array>
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleTypeExtensions</key>
|
|
||||||
<array>
|
|
||||||
<string>zip</string>
|
|
||||||
<string>mrpack</string>
|
|
||||||
</array>
|
|
||||||
<key>CFBundleTypeName</key>
|
|
||||||
<string>Prism Launcher instance</string>
|
|
||||||
<key>CFBundleTypeOSTypes</key>
|
|
||||||
<array>
|
|
||||||
<string>TEXT</string>
|
|
||||||
<string>utxt</string>
|
|
||||||
<string>TUTX</string>
|
|
||||||
<string>****</string>
|
|
||||||
</array>
|
|
||||||
<key>CFBundleTypeRole</key>
|
|
||||||
<string>Viewer</string>
|
|
||||||
<key>LSHandlerRank</key>
|
|
||||||
<string>Alternate</string>
|
|
||||||
</dict>
|
|
||||||
</array>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
31
flake.lock
generated
31
flake.lock
generated
@ -3,11 +3,11 @@
|
|||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1668681692,
|
"lastModified": 1650374568,
|
||||||
"narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=",
|
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
|
||||||
"owner": "edolstra",
|
"owner": "edolstra",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "009399224d5e398d03b22badca40a37ac85412a1",
|
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -34,11 +34,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1671417167,
|
"lastModified": 1666057921,
|
||||||
"narHash": "sha256-JkHam6WQOwZN1t2C2sbp1TqMv3TVRjzrdoejqfefwrM=",
|
"narHash": "sha256-VpQqtXdj6G7cH//SvoprjR7XT3KS7p+tCVebGK1N6tE=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "bb31220cca6d044baa6dc2715b07497a2a7c4bc7",
|
"rev": "88eab1e431cabd0ed621428d8b40d425a07af39f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -52,7 +52,24 @@
|
|||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": "flake-compat",
|
||||||
"libnbtplusplus": "libnbtplusplus",
|
"libnbtplusplus": "libnbtplusplus",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs",
|
||||||
|
"tomlplusplus": "tomlplusplus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tomlplusplus": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1666091090,
|
||||||
|
"narHash": "sha256-djpMCFPvkJcfynV8WnsYdtwLq+J7jpV1iM4C6TojiyM=",
|
||||||
|
"owner": "marzer",
|
||||||
|
"repo": "tomlplusplus",
|
||||||
|
"rev": "1e4a3833d013aee08f58c5b31c69f709afc69f73",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "marzer",
|
||||||
|
"repo": "tomlplusplus",
|
||||||
|
"type": "github"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -5,9 +5,10 @@
|
|||||||
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||||
flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
|
flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
|
||||||
libnbtplusplus = { url = "github:PrismLauncher/libnbtplusplus"; flake = false; };
|
libnbtplusplus = { url = "github:PrismLauncher/libnbtplusplus"; flake = false; };
|
||||||
|
tomlplusplus = { url = "github:marzer/tomlplusplus"; flake = false; };
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, libnbtplusplus, ... }:
|
outputs = { self, nixpkgs, libnbtplusplus, tomlplusplus, ... }:
|
||||||
let
|
let
|
||||||
# User-friendly version number.
|
# User-friendly version number.
|
||||||
version = builtins.substring 0 8 self.lastModifiedDate;
|
version = builtins.substring 0 8 self.lastModifiedDate;
|
||||||
@ -22,8 +23,8 @@
|
|||||||
pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system});
|
pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system});
|
||||||
|
|
||||||
packagesFn = pkgs: rec {
|
packagesFn = pkgs: rec {
|
||||||
prismlauncher-qt5 = pkgs.libsForQt5.callPackage ./nix { inherit version self libnbtplusplus; };
|
prismlauncher = pkgs.libsForQt5.callPackage ./nix { inherit version self libnbtplusplus tomlplusplus; };
|
||||||
prismlauncher = pkgs.qt6Packages.callPackage ./nix { inherit version self libnbtplusplus; };
|
prismlauncher-qt6 = pkgs.qt6Packages.callPackage ./nix { inherit version self libnbtplusplus tomlplusplus; };
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
id: org.prismlauncher.PrismLauncher
|
|
||||||
runtime: org.kde.Platform
|
|
||||||
runtime-version: "5.15-22.08"
|
|
||||||
sdk: org.kde.Sdk
|
|
||||||
sdk-extensions:
|
|
||||||
- org.freedesktop.Sdk.Extension.openjdk17
|
|
||||||
- org.freedesktop.Sdk.Extension.openjdk8
|
|
||||||
add-extensions:
|
|
||||||
com.valvesoftware.Steam.Utility.gamescope:
|
|
||||||
version: stable
|
|
||||||
add-ld-path: lib
|
|
||||||
no-autodownload: true
|
|
||||||
autodelete: false
|
|
||||||
directory: utils/gamescope
|
|
||||||
|
|
||||||
command: prismlauncher
|
|
||||||
finish-args:
|
|
||||||
- --share=ipc
|
|
||||||
- --socket=x11
|
|
||||||
- --socket=wayland
|
|
||||||
- --device=all
|
|
||||||
- --share=network
|
|
||||||
- --socket=pulseaudio
|
|
||||||
# for Discord RPC mods
|
|
||||||
- --filesystem=xdg-run/app/com.discordapp.Discord:create
|
|
||||||
# Mod drag&drop
|
|
||||||
- --filesystem=xdg-download:ro
|
|
||||||
|
|
||||||
modules:
|
|
||||||
- name: prismlauncher
|
|
||||||
buildsystem: cmake-ninja
|
|
||||||
config-opts:
|
|
||||||
- -DLauncher_BUILD_PLATFORM=flatpak
|
|
||||||
- -DCMAKE_BUILD_TYPE=Debug
|
|
||||||
build-options:
|
|
||||||
env:
|
|
||||||
JAVA_HOME: /usr/lib/sdk/openjdk17/jvm/openjdk-17
|
|
||||||
JAVA_COMPILER: /usr/lib/sdk/openjdk17/jvm/openjdk-17/bin/javac
|
|
||||||
sources:
|
|
||||||
- type: dir
|
|
||||||
path: ../
|
|
||||||
- name: openjdk
|
|
||||||
buildsystem: simple
|
|
||||||
build-commands:
|
|
||||||
- mkdir -p /app/jdk/
|
|
||||||
- /usr/lib/sdk/openjdk17/install.sh
|
|
||||||
- mv /app/jre /app/jdk/17
|
|
||||||
- /usr/lib/sdk/openjdk8/install.sh
|
|
||||||
- mv /app/jre /app/jdk/8
|
|
||||||
cleanup: [/jre]
|
|
||||||
- name: xrandr
|
|
||||||
buildsystem: autotools
|
|
||||||
sources:
|
|
||||||
- type: archive
|
|
||||||
url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.1.tar.xz
|
|
||||||
sha256: 7bc76daf9d72f8aff885efad04ce06b90488a1a169d118dea8a2b661832e8762
|
|
||||||
cleanup: [/share/man, /bin/xkeystone]
|
|
||||||
- name: gamemode
|
|
||||||
buildsystem: meson
|
|
||||||
config-opts:
|
|
||||||
- -Dwith-sd-bus-provider=no-daemon
|
|
||||||
- -Dwith-examples=false
|
|
||||||
post-install:
|
|
||||||
# gamemoderun is installed for users who want to use wrapper commands
|
|
||||||
# post-install is running inside the build dir, we need it from the source though
|
|
||||||
- install -Dm755 ../data/gamemoderun -t /app/bin
|
|
||||||
sources:
|
|
||||||
- type: git
|
|
||||||
url: https://github.com/FeralInteractive/gamemode
|
|
||||||
tag: "1.7"
|
|
||||||
commit: 4dc99dff76218718763a6b07fc1900fa6d1dafd9
|
|
||||||
- name: enhance
|
|
||||||
buildsystem: simple
|
|
||||||
build-commands:
|
|
||||||
- mkdir -p /app/utils/gamescope
|
|
||||||
- install -Dm755 prime-run /app/bin/prime-run
|
|
||||||
- mv /app/bin/prismlauncher /app/bin/prismrun
|
|
||||||
- install -Dm755 prismlauncher /app/bin/prismlauncher
|
|
||||||
sources:
|
|
||||||
- type: file
|
|
||||||
path: ../flatpak/prime-run
|
|
||||||
- type: file
|
|
||||||
path: ../flatpak/prismlauncher
|
|
@ -1,4 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
export __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only __GLX_VENDOR_LIBRARY_NAME=nvidia
|
|
||||||
exec "$@"
|
|
@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# discord RPC
|
|
||||||
for i in {0..9}; do
|
|
||||||
test -S "$XDG_RUNTIME_DIR"/discord-ipc-"$i" || ln -sf {app/com.discordapp.Discord,"$XDG_RUNTIME_DIR"}/discord-ipc-"$i";
|
|
||||||
done
|
|
||||||
|
|
||||||
export PATH="${PATH}${PATH:+:}/app/utils/gamescope/bin:/usr/lib/extensions/vulkan/MangoHud/bin"
|
|
||||||
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}${LD_LIBRARY_PATH:+:}/usr/lib/extensions/vulkan/MangoHud/\$LIB/"
|
|
||||||
|
|
||||||
exec /app/bin/prismrun "$@"
|
|
@ -1,12 +1,8 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* PolyMC - Minecraft Launcher
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
* Copyright (C) 2022 Lenny McLennington <lenny@sneed.church>
|
* Copyright (C) 2022 Lenny McLennington <lenny@sneed.church>
|
||||||
* Copyright (C) 2022 Tayou <tayou@gmx.net>
|
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -41,14 +37,10 @@
|
|||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
|
|
||||||
#include "DataMigrationTask.h"
|
|
||||||
#include "net/PasteUpload.h"
|
#include "net/PasteUpload.h"
|
||||||
#include "pathmatcher/MultiMatcher.h"
|
|
||||||
#include "pathmatcher/SimplePrefixMatcher.h"
|
|
||||||
#include "ui/MainWindow.h"
|
#include "ui/MainWindow.h"
|
||||||
#include "ui/InstanceWindow.h"
|
#include "ui/InstanceWindow.h"
|
||||||
|
|
||||||
#include "ui/dialogs/ProgressDialog.h"
|
|
||||||
#include "ui/instanceview/AccessibleInstanceView.h"
|
#include "ui/instanceview/AccessibleInstanceView.h"
|
||||||
|
|
||||||
#include "ui/pages/BasePageProvider.h"
|
#include "ui/pages/BasePageProvider.h"
|
||||||
@ -62,6 +54,17 @@
|
|||||||
#include "ui/pages/global/APIPage.h"
|
#include "ui/pages/global/APIPage.h"
|
||||||
#include "ui/pages/global/CustomCommandsPage.h"
|
#include "ui/pages/global/CustomCommandsPage.h"
|
||||||
|
|
||||||
|
#include "ui/themes/ITheme.h"
|
||||||
|
#include "ui/themes/SystemTheme.h"
|
||||||
|
#include "ui/themes/DarkTheme.h"
|
||||||
|
#include "ui/themes/BrightTheme.h"
|
||||||
|
#include "ui/themes/CustomTheme.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include "ui/WinDarkmode.h"
|
||||||
|
#include <versionhelpers.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ui/setupwizard/SetupWizard.h"
|
#include "ui/setupwizard/SetupWizard.h"
|
||||||
#include "ui/setupwizard/LanguageWizardPage.h"
|
#include "ui/setupwizard/LanguageWizardPage.h"
|
||||||
#include "ui/setupwizard/JavaWizardPage.h"
|
#include "ui/setupwizard/JavaWizardPage.h"
|
||||||
@ -71,8 +74,6 @@
|
|||||||
|
|
||||||
#include "ui/pagedialog/PageDialog.h"
|
#include "ui/pagedialog/PageDialog.h"
|
||||||
|
|
||||||
#include "ui/themes/ThemeManager.h"
|
|
||||||
|
|
||||||
#include "ApplicationMessage.h"
|
#include "ApplicationMessage.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -92,7 +93,6 @@
|
|||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
|
||||||
#include "InstanceList.h"
|
#include "InstanceList.h"
|
||||||
#include "MTPixmapCache.h"
|
|
||||||
|
|
||||||
#include <minecraft/auth/AccountList.h>
|
#include <minecraft/auth/AccountList.h>
|
||||||
#include "icons/IconList.h"
|
#include "icons/IconList.h"
|
||||||
@ -121,7 +121,6 @@
|
|||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include "gamemode_client.h"
|
#include "gamemode_client.h"
|
||||||
#include "MangoHud.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -138,15 +137,20 @@
|
|||||||
|
|
||||||
static const QLatin1String liveCheckFile("live.check");
|
static const QLatin1String liveCheckFile("live.check");
|
||||||
|
|
||||||
PixmapCache* PixmapCache::s_instance = nullptr;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/** This is used so that we can output to the log file in addition to the CLI. */
|
|
||||||
void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||||
{
|
{
|
||||||
QString out = qFormatLogMessage(type, context, msg);
|
const char *levels = "DWCFIS";
|
||||||
out += QChar::LineFeed;
|
const QString format("%1 %2 %3\n");
|
||||||
|
|
||||||
|
qint64 msecstotal = APPLICATION->timeSinceStart();
|
||||||
|
qint64 seconds = msecstotal / 1000;
|
||||||
|
qint64 msecs = msecstotal % 1000;
|
||||||
|
QString foo;
|
||||||
|
char buf[1025] = {0};
|
||||||
|
::snprintf(buf, 1024, "%5lld.%03lld", seconds, msecs);
|
||||||
|
|
||||||
|
QString out = format.arg(buf).arg(levels[type]).arg(msg);
|
||||||
|
|
||||||
APPLICATION->logFile->write(out.toUtf8());
|
APPLICATION->logFile->write(out.toUtf8());
|
||||||
APPLICATION->logFile->flush();
|
APPLICATION->logFile->flush();
|
||||||
@ -225,7 +229,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN);
|
setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN);
|
||||||
setApplicationName(BuildConfig.LAUNCHER_NAME);
|
setApplicationName(BuildConfig.LAUNCHER_NAME);
|
||||||
setApplicationDisplayName(QString("%1 %2").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString()));
|
setApplicationDisplayName(QString("%1 %2").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString()));
|
||||||
setApplicationVersion(BuildConfig.printableVersionString() + "\n" + BuildConfig.GIT_COMMIT);
|
setApplicationVersion(BuildConfig.printableVersionString());
|
||||||
setDesktopFileName(BuildConfig.LAUNCHER_DESKTOPFILENAME);
|
setDesktopFileName(BuildConfig.LAUNCHER_DESKTOPFILENAME);
|
||||||
startTime = QDateTime::currentDateTime();
|
startTime = QDateTime::currentDateTime();
|
||||||
|
|
||||||
@ -242,8 +246,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
{{"s", "server"}, "Join the specified server on launch (only valid in combination with --launch)", "address"},
|
{{"s", "server"}, "Join the specified server on launch (only valid in combination with --launch)", "address"},
|
||||||
{{"a", "profile"}, "Use the account specified by its profile name (only valid in combination with --launch)", "profile"},
|
{{"a", "profile"}, "Use the account specified by its profile name (only valid in combination with --launch)", "profile"},
|
||||||
{"alive", "Write a small '" + liveCheckFile + "' file after the launcher starts"},
|
{"alive", "Write a small '" + liveCheckFile + "' file after the launcher starts"},
|
||||||
{{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"},
|
{{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"}
|
||||||
{"show", "Opens the window for the specified instance (by instance ID)", "show"}
|
|
||||||
});
|
});
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.addVersionOption();
|
parser.addVersionOption();
|
||||||
@ -255,7 +258,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
m_profileToUse = parser.value("profile");
|
m_profileToUse = parser.value("profile");
|
||||||
m_liveCheck = parser.isSet("alive");
|
m_liveCheck = parser.isSet("alive");
|
||||||
m_zipToImport = parser.value("import");
|
m_zipToImport = parser.value("import");
|
||||||
m_instanceIdToShowWindowOf = parser.value("show");
|
|
||||||
|
|
||||||
// error if --launch is missing with --server or --profile
|
// error if --launch is missing with --server or --profile
|
||||||
if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty())
|
if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty())
|
||||||
@ -300,6 +302,22 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
dataPath = foo.absolutePath();
|
dataPath = foo.absolutePath();
|
||||||
adjustedBy = "Persistent data path";
|
adjustedBy = "Persistent data path";
|
||||||
|
|
||||||
|
QDir polymcData(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), "PolyMC"));
|
||||||
|
if (polymcData.exists()) {
|
||||||
|
dataPath = polymcData.absolutePath();
|
||||||
|
adjustedBy = "PolyMC data path";
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
// TODO: this should be removed in a future version
|
||||||
|
// TODO: provide a migration path similar to macOS migration
|
||||||
|
QDir bar(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), "polymc"));
|
||||||
|
if (bar.exists()) {
|
||||||
|
dataPath = bar.absolutePath();
|
||||||
|
adjustedBy = "Legacy data path";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef Q_OS_MACOS
|
#ifndef Q_OS_MACOS
|
||||||
if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) {
|
if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) {
|
||||||
dataPath = m_rootPath;
|
dataPath = m_rootPath;
|
||||||
@ -419,26 +437,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qInstallMessageHandler(appDebugOutput);
|
qInstallMessageHandler(appDebugOutput);
|
||||||
|
|
||||||
qSetMessagePattern(
|
|
||||||
"%{time process}" " "
|
|
||||||
"%{if-debug}D%{endif}" "%{if-info}I%{endif}" "%{if-warning}W%{endif}" "%{if-critical}C%{endif}" "%{if-fatal}F%{endif}"
|
|
||||||
" " "|" " "
|
|
||||||
"%{if-category}[%{category}]: %{endif}"
|
|
||||||
"%{message}");
|
|
||||||
|
|
||||||
qDebug() << "<> Log initialized.";
|
qDebug() << "<> Log initialized.";
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
bool migrated = false;
|
|
||||||
|
|
||||||
if (!migrated)
|
|
||||||
migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", "polymc.cfg");
|
|
||||||
if (!migrated)
|
|
||||||
migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC", "multimc.cfg");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT;
|
qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT;
|
||||||
@ -498,7 +499,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
// Theming
|
// Theming
|
||||||
m_settings->registerSetting("IconTheme", QString("pe_colored"));
|
m_settings->registerSetting("IconTheme", QString("pe_colored"));
|
||||||
m_settings->registerSetting("ApplicationTheme", QString("system"));
|
m_settings->registerSetting("ApplicationTheme", QString("system"));
|
||||||
m_settings->registerSetting("BackgroundCat", QString("kitteh"));
|
|
||||||
|
|
||||||
// Remembered state
|
// Remembered state
|
||||||
m_settings->registerSetting("LastUsedGroupForNewInstance", QString());
|
m_settings->registerSetting("LastUsedGroupForNewInstance", QString());
|
||||||
@ -563,7 +563,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
|
|
||||||
// Memory
|
// Memory
|
||||||
m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512);
|
m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512);
|
||||||
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, suitableMaxMem());
|
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 4096);
|
||||||
m_settings->registerSetting("PermGen", 128);
|
m_settings->registerSetting("PermGen", 128);
|
||||||
|
|
||||||
// Java Settings
|
// Java Settings
|
||||||
@ -611,8 +611,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
// The cat
|
// The cat
|
||||||
m_settings->registerSetting("TheCat", false);
|
m_settings->registerSetting("TheCat", false);
|
||||||
|
|
||||||
m_settings->registerSetting("ToolbarsLocked", false);
|
|
||||||
|
|
||||||
m_settings->registerSetting("InstSortMode", "Name");
|
m_settings->registerSetting("InstSortMode", "Name");
|
||||||
m_settings->registerSetting("SelectedInstance", QString());
|
m_settings->registerSetting("SelectedInstance", QString());
|
||||||
|
|
||||||
@ -693,9 +691,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
m_globalSettingsProvider->addPage<AccountListPage>();
|
m_globalSettingsProvider->addPage<AccountListPage>();
|
||||||
m_globalSettingsProvider->addPage<APIPage>();
|
m_globalSettingsProvider->addPage<APIPage>();
|
||||||
}
|
}
|
||||||
|
|
||||||
PixmapCache::setInstance(new PixmapCache(this));
|
|
||||||
|
|
||||||
qDebug() << "<> Settings loaded.";
|
qDebug() << "<> Settings loaded.";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,8 +747,29 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
qDebug() << "<> Instance icons intialized.";
|
qDebug() << "<> Instance icons intialized.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Themes
|
// Icon themes
|
||||||
m_themeManager = std::make_unique<ThemeManager>(m_mainWindow);
|
{
|
||||||
|
// TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies!
|
||||||
|
// set icon theme search path!
|
||||||
|
auto searchPaths = QIcon::themeSearchPaths();
|
||||||
|
searchPaths.append("iconthemes");
|
||||||
|
QIcon::setThemeSearchPaths(searchPaths);
|
||||||
|
qDebug() << "<> Icon themes initialized.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize widget themes
|
||||||
|
{
|
||||||
|
auto insertTheme = [this](ITheme * theme)
|
||||||
|
{
|
||||||
|
m_themes.insert(std::make_pair(theme->id(), std::unique_ptr<ITheme>(theme)));
|
||||||
|
};
|
||||||
|
auto darkTheme = new DarkTheme();
|
||||||
|
insertTheme(new SystemTheme());
|
||||||
|
insertTheme(darkTheme);
|
||||||
|
insertTheme(new BrightTheme());
|
||||||
|
insertTheme(new CustomTheme(darkTheme, "custom"));
|
||||||
|
qDebug() << "<> Widget themes initialized.";
|
||||||
|
}
|
||||||
|
|
||||||
// initialize and load all instances
|
// initialize and load all instances
|
||||||
{
|
{
|
||||||
@ -918,24 +934,18 @@ bool Application::createSetupWizard()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::event(QEvent* event)
|
bool Application::event(QEvent* event) {
|
||||||
{
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
if (event->type() == QEvent::ApplicationStateChange) {
|
if (event->type() == QEvent::ApplicationStateChange) {
|
||||||
auto ev = static_cast<QApplicationStateChangeEvent*>(event);
|
auto ev = static_cast<QApplicationStateChangeEvent*>(event);
|
||||||
|
|
||||||
if (m_prevAppState == Qt::ApplicationActive && ev->applicationState() == Qt::ApplicationActive) {
|
if (m_prevAppState == Qt::ApplicationActive
|
||||||
|
&& ev->applicationState() == Qt::ApplicationActive) {
|
||||||
emit clickedOnDock();
|
emit clickedOnDock();
|
||||||
}
|
}
|
||||||
m_prevAppState = ev->applicationState();
|
m_prevAppState = ev->applicationState();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (event->type() == QEvent::FileOpen) {
|
|
||||||
auto ev = static_cast<QFileOpenEvent*>(event);
|
|
||||||
m_mainWindow->droppedURLs({ ev->url() });
|
|
||||||
}
|
|
||||||
|
|
||||||
return QApplication::event(event);
|
return QApplication::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -977,16 +987,6 @@ void Application::performMainStartupAction()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!m_instanceIdToShowWindowOf.isEmpty())
|
|
||||||
{
|
|
||||||
auto inst = instances()->getInstanceById(m_instanceIdToShowWindowOf);
|
|
||||||
if(inst)
|
|
||||||
{
|
|
||||||
qDebug() << "<> Showing window of instance " << m_instanceIdToShowWindowOf;
|
|
||||||
showInstanceWindow(inst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!m_mainWindow)
|
if(!m_mainWindow)
|
||||||
{
|
{
|
||||||
// normal main window
|
// normal main window
|
||||||
@ -1113,19 +1113,45 @@ std::shared_ptr<JavaInstallList> Application::javalist()
|
|||||||
return m_javalist;
|
return m_javalist;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<ITheme*> Application::getValidApplicationThemes()
|
std::vector<ITheme *> Application::getValidApplicationThemes()
|
||||||
{
|
{
|
||||||
return m_themeManager->getValidApplicationThemes();
|
std::vector<ITheme *> ret;
|
||||||
|
auto iter = m_themes.cbegin();
|
||||||
|
while (iter != m_themes.cend())
|
||||||
|
{
|
||||||
|
ret.push_back((*iter).second.get());
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setApplicationTheme(const QString& name, bool initial)
|
void Application::setApplicationTheme(const QString& name, bool initial)
|
||||||
{
|
{
|
||||||
m_themeManager->setApplicationTheme(name, initial);
|
auto systemPalette = qApp->palette();
|
||||||
|
auto themeIter = m_themes.find(name);
|
||||||
|
if(themeIter != m_themes.end())
|
||||||
|
{
|
||||||
|
auto & theme = (*themeIter).second;
|
||||||
|
theme->apply(initial);
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if (m_mainWindow && IsWindows10OrGreater()) {
|
||||||
|
if (QString::compare(theme->id(), "dark") == 0) {
|
||||||
|
WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), true);
|
||||||
|
} else {
|
||||||
|
WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning() << "Tried to set invalid theme:" << name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setIconTheme(const QString& name)
|
void Application::setIconTheme(const QString& name)
|
||||||
{
|
{
|
||||||
m_themeManager->setIconTheme(name);
|
QIcon::setThemeName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
QIcon Application::getThemedIcon(const QString& name)
|
QIcon Application::getThemedIcon(const QString& name)
|
||||||
@ -1348,7 +1374,16 @@ MainWindow* Application::showMainWindow(bool minimized)
|
|||||||
m_mainWindow = new MainWindow();
|
m_mainWindow = new MainWindow();
|
||||||
m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toByteArray()));
|
m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toByteArray()));
|
||||||
m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toByteArray()));
|
m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toByteArray()));
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if (IsWindows10OrGreater())
|
||||||
|
{
|
||||||
|
if (QString::compare(settings()->get("ApplicationTheme").toString(), "dark") == 0) {
|
||||||
|
WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), true);
|
||||||
|
} else {
|
||||||
|
WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if(minimized)
|
if(minimized)
|
||||||
{
|
{
|
||||||
m_mainWindow->showMinimized();
|
m_mainWindow->showMinimized();
|
||||||
@ -1513,8 +1548,17 @@ void Application::updateCapabilities()
|
|||||||
if (gamemode_query_status() >= 0)
|
if (gamemode_query_status() >= 0)
|
||||||
m_capabilities |= SupportsGameMode;
|
m_capabilities |= SupportsGameMode;
|
||||||
|
|
||||||
if (!MangoHud::getLibraryString().isEmpty())
|
{
|
||||||
m_capabilities |= SupportsMangoHud;
|
void *dummy = dlopen("libMangoHud_dlsym.so", RTLD_LAZY);
|
||||||
|
// try normal variant as well
|
||||||
|
if (dummy == NULL)
|
||||||
|
dummy = dlopen("libMangoHud.so", RTLD_LAZY);
|
||||||
|
|
||||||
|
if (dummy != NULL) {
|
||||||
|
dlclose(dummy);
|
||||||
|
m_capabilities |= SupportsMangoHud;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1525,8 +1569,7 @@ QString Application::getJarPath(QString jarFile)
|
|||||||
FS::PathCombine(m_rootPath, "share/" + BuildConfig.LAUNCHER_APP_BINARY_NAME),
|
FS::PathCombine(m_rootPath, "share/" + BuildConfig.LAUNCHER_APP_BINARY_NAME),
|
||||||
#endif
|
#endif
|
||||||
FS::PathCombine(m_rootPath, "jars"),
|
FS::PathCombine(m_rootPath, "jars"),
|
||||||
FS::PathCombine(applicationDirPath(), "jars"),
|
FS::PathCombine(applicationDirPath(), "jars")
|
||||||
FS::PathCombine(applicationDirPath(), "..", "jars") // from inside build dir, for debuging
|
|
||||||
};
|
};
|
||||||
for(QString p : potentialPaths)
|
for(QString p : potentialPaths)
|
||||||
{
|
{
|
||||||
@ -1577,102 +1620,3 @@ QString Application::getUserAgentUncached()
|
|||||||
|
|
||||||
return BuildConfig.USER_AGENT_UNCACHED;
|
return BuildConfig.USER_AGENT_UNCACHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Application::suitableMaxMem()
|
|
||||||
{
|
|
||||||
float totalRAM = (float)Sys::getSystemRam() / (float)Sys::mebibyte;
|
|
||||||
int maxMemoryAlloc;
|
|
||||||
|
|
||||||
// If totalRAM < 6GB, use (totalRAM / 1.5), else 4GB
|
|
||||||
if (totalRAM < (4096 * 1.5))
|
|
||||||
maxMemoryAlloc = (int) (totalRAM / 1.5);
|
|
||||||
else
|
|
||||||
maxMemoryAlloc = 4096;
|
|
||||||
|
|
||||||
return maxMemoryAlloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Application::handleDataMigration(const QString& currentData,
|
|
||||||
const QString& oldData,
|
|
||||||
const QString& name,
|
|
||||||
const QString& configFile) const
|
|
||||||
{
|
|
||||||
QString nomigratePath = FS::PathCombine(currentData, name + "_nomigrate.txt");
|
|
||||||
QStringList configPaths = { FS::PathCombine(oldData, configFile), FS::PathCombine(oldData, BuildConfig.LAUNCHER_CONFIGFILE) };
|
|
||||||
|
|
||||||
QLocale locale;
|
|
||||||
|
|
||||||
// Is there a valid config at the old location?
|
|
||||||
bool configExists = false;
|
|
||||||
for (QString configPath : configPaths) {
|
|
||||||
configExists |= QFileInfo::exists(configPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!configExists || QFileInfo::exists(nomigratePath)) {
|
|
||||||
qDebug() << "<> No migration needed from" << name;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString message;
|
|
||||||
bool currentExists = QFileInfo::exists(FS::PathCombine(currentData, BuildConfig.LAUNCHER_CONFIGFILE));
|
|
||||||
|
|
||||||
if (currentExists) {
|
|
||||||
message = tr("Old data from %1 was found, but you already have existing data for %2. Sadly you will need to migrate yourself. Do "
|
|
||||||
"you want to be reminded of the pending data migration next time you start %2?")
|
|
||||||
.arg(name, BuildConfig.LAUNCHER_DISPLAYNAME);
|
|
||||||
} else {
|
|
||||||
message = tr("It looks like you used %1 before. Do you want to migrate your data to the new location of %2?")
|
|
||||||
.arg(name, BuildConfig.LAUNCHER_DISPLAYNAME);
|
|
||||||
|
|
||||||
QFileInfo logInfo(FS::PathCombine(oldData, name + "-0.log"));
|
|
||||||
if (logInfo.exists()) {
|
|
||||||
QString lastModified = logInfo.lastModified().toString(locale.dateFormat());
|
|
||||||
message = tr("It looks like you used %1 on %2 before. Do you want to migrate your data to the new location of %3?")
|
|
||||||
.arg(name, lastModified, BuildConfig.LAUNCHER_DISPLAYNAME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QMessageBox::StandardButton askMoveDialogue =
|
|
||||||
QMessageBox::question(nullptr, BuildConfig.LAUNCHER_DISPLAYNAME, message, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
|
||||||
|
|
||||||
auto setDoNotMigrate = [&nomigratePath] {
|
|
||||||
QFile file(nomigratePath);
|
|
||||||
file.open(QIODevice::WriteOnly);
|
|
||||||
};
|
|
||||||
|
|
||||||
// create no-migrate file if user doesn't want to migrate
|
|
||||||
if (askMoveDialogue != QMessageBox::Yes) {
|
|
||||||
qDebug() << "<> Migration declined for" << name;
|
|
||||||
setDoNotMigrate();
|
|
||||||
return currentExists; // cancel further migrations, if we already have a data directory
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentExists) {
|
|
||||||
// Migrate!
|
|
||||||
auto matcher = std::make_shared<MultiMatcher>();
|
|
||||||
matcher->add(std::make_shared<SimplePrefixMatcher>(configFile));
|
|
||||||
matcher->add(std::make_shared<SimplePrefixMatcher>(
|
|
||||||
BuildConfig.LAUNCHER_CONFIGFILE)); // it's possible that we already used that directory before
|
|
||||||
matcher->add(std::make_shared<SimplePrefixMatcher>("accounts.json"));
|
|
||||||
matcher->add(std::make_shared<SimplePrefixMatcher>("accounts/"));
|
|
||||||
matcher->add(std::make_shared<SimplePrefixMatcher>("assets/"));
|
|
||||||
matcher->add(std::make_shared<SimplePrefixMatcher>("icons/"));
|
|
||||||
matcher->add(std::make_shared<SimplePrefixMatcher>("instances/"));
|
|
||||||
matcher->add(std::make_shared<SimplePrefixMatcher>("libraries/"));
|
|
||||||
matcher->add(std::make_shared<SimplePrefixMatcher>("mods/"));
|
|
||||||
matcher->add(std::make_shared<SimplePrefixMatcher>("themes/"));
|
|
||||||
|
|
||||||
ProgressDialog diag;
|
|
||||||
DataMigrationTask task(nullptr, oldData, currentData, matcher);
|
|
||||||
if (diag.execWithTask(&task)) {
|
|
||||||
qDebug() << "<> Migration succeeded";
|
|
||||||
setDoNotMigrate();
|
|
||||||
} else {
|
|
||||||
QString reason = task.failReason();
|
|
||||||
QMessageBox::critical(nullptr, BuildConfig.LAUNCHER_DISPLAYNAME, tr("Migration failed! Reason: %1").arg(reason));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qWarning() << "<> Migration was skipped, due to existing data";
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* PolyMC - Minecraft Launcher
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
* Copyright (C) 2022 Tayou <tayou@gmx.net>
|
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -69,7 +68,6 @@ class BaseDetachedToolFactory;
|
|||||||
class TranslationsModel;
|
class TranslationsModel;
|
||||||
class ITheme;
|
class ITheme;
|
||||||
class MCEditTool;
|
class MCEditTool;
|
||||||
class ThemeManager;
|
|
||||||
|
|
||||||
namespace Meta {
|
namespace Meta {
|
||||||
class Index;
|
class Index;
|
||||||
@ -120,7 +118,7 @@ public:
|
|||||||
|
|
||||||
void setIconTheme(const QString& name);
|
void setIconTheme(const QString& name);
|
||||||
|
|
||||||
QList<ITheme*> getValidApplicationThemes();
|
std::vector<ITheme *> getValidApplicationThemes();
|
||||||
|
|
||||||
void setApplicationTheme(const QString& name, bool initial);
|
void setApplicationTheme(const QString& name, bool initial);
|
||||||
|
|
||||||
@ -200,8 +198,6 @@ public:
|
|||||||
|
|
||||||
void ShowGlobalSettings(class QWidget * parent, QString open_page = QString());
|
void ShowGlobalSettings(class QWidget * parent, QString open_page = QString());
|
||||||
|
|
||||||
int suitableMaxMem();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void updateAllowedChanged(bool status);
|
void updateAllowedChanged(bool status);
|
||||||
void globalSettingsAboutToOpen();
|
void globalSettingsAboutToOpen();
|
||||||
@ -231,7 +227,6 @@ private slots:
|
|||||||
void setupWizardFinished(int status);
|
void setupWizardFinished(int status);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool handleDataMigration(const QString & currentData, const QString & oldData, const QString & name, const QString & configFile) const;
|
|
||||||
bool createSetupWizard();
|
bool createSetupWizard();
|
||||||
void performMainStartupAction();
|
void performMainStartupAction();
|
||||||
|
|
||||||
@ -260,9 +255,9 @@ private:
|
|||||||
std::shared_ptr<JavaInstallList> m_javalist;
|
std::shared_ptr<JavaInstallList> m_javalist;
|
||||||
std::shared_ptr<TranslationsModel> m_translations;
|
std::shared_ptr<TranslationsModel> m_translations;
|
||||||
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
||||||
|
std::map<QString, std::unique_ptr<ITheme>> m_themes;
|
||||||
std::unique_ptr<MCEditTool> m_mcedit;
|
std::unique_ptr<MCEditTool> m_mcedit;
|
||||||
QSet<QString> m_features;
|
QSet<QString> m_features;
|
||||||
std::unique_ptr<ThemeManager> m_themeManager;
|
|
||||||
|
|
||||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
|
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
|
||||||
|
|
||||||
@ -304,7 +299,6 @@ public:
|
|||||||
QString m_profileToUse;
|
QString m_profileToUse;
|
||||||
bool m_liveCheck = false;
|
bool m_liveCheck = false;
|
||||||
QUrl m_zipToImport;
|
QUrl m_zipToImport;
|
||||||
QString m_instanceIdToShowWindowOf;
|
|
||||||
std::unique_ptr<QFile> logFile;
|
std::unique_ptr<QFile> logFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,8 +47,8 @@ void ApplicationMessage::parse(const QByteArray & input) {
|
|||||||
args.clear();
|
args.clear();
|
||||||
|
|
||||||
auto parsedArgs = root.value("args").toObject();
|
auto parsedArgs = root.value("args").toObject();
|
||||||
for(auto iter = parsedArgs.constBegin(); iter != parsedArgs.constEnd(); iter++) {
|
for(auto iter = parsedArgs.begin(); iter != parsedArgs.end(); iter++) {
|
||||||
args.insert(iter.key(), iter.value().toString());
|
args[iter.key()] = iter.value().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,8 +56,8 @@ QByteArray ApplicationMessage::serialize() {
|
|||||||
QJsonObject root;
|
QJsonObject root;
|
||||||
root.insert("command", command);
|
root.insert("command", command);
|
||||||
QJsonObject outArgs;
|
QJsonObject outArgs;
|
||||||
for (auto iter = args.constBegin(); iter != args.constEnd(); iter++) {
|
for (auto iter = args.begin(); iter != args.end(); iter++) {
|
||||||
outArgs.insert(iter.key(), iter.value());
|
outArgs[iter.key()] = iter.value();
|
||||||
}
|
}
|
||||||
root.insert("args", outArgs);
|
root.insert("args", outArgs);
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QHash>
|
#include <QMap>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
struct ApplicationMessage {
|
struct ApplicationMessage {
|
||||||
QString command;
|
QString command;
|
||||||
QHash<QString, QString> args;
|
QMap<QString, QString> args;
|
||||||
|
|
||||||
QByteArray serialize();
|
QByteArray serialize();
|
||||||
void parse(const QByteArray & input);
|
void parse(const QByteArray & input);
|
||||||
|
@ -17,14 +17,13 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "BaseVersion.h"
|
|
||||||
|
|
||||||
class MinecraftInstance;
|
class MinecraftInstance;
|
||||||
class QDir;
|
class QDir;
|
||||||
class QString;
|
class QString;
|
||||||
class QObject;
|
class QObject;
|
||||||
class Task;
|
class Task;
|
||||||
class BaseVersion;
|
class BaseVersion;
|
||||||
|
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
|
||||||
|
|
||||||
class BaseInstaller
|
class BaseInstaller
|
||||||
{
|
{
|
||||||
@ -36,7 +35,7 @@ public:
|
|||||||
virtual bool add(MinecraftInstance *to);
|
virtual bool add(MinecraftInstance *to);
|
||||||
virtual bool remove(MinecraftInstance *from);
|
virtual bool remove(MinecraftInstance *from);
|
||||||
|
|
||||||
virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersion::Ptr version, QObject *parent) = 0;
|
virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersionPtr version, QObject *parent) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual QString id() const = 0;
|
virtual QString id() const = 0;
|
||||||
|
@ -151,7 +151,7 @@ public:
|
|||||||
void copyManagedPack(BaseInstance& other);
|
void copyManagedPack(BaseInstance& other);
|
||||||
|
|
||||||
/// guess log level from a line of game log
|
/// guess log level from a line of game log
|
||||||
virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString &line, MessageLevel::Enum level)
|
virtual MessageLevel::Enum guessLevel(const QString &line, MessageLevel::Enum level)
|
||||||
{
|
{
|
||||||
return level;
|
return level;
|
||||||
};
|
};
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
class BaseVersion
|
class BaseVersion
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<BaseVersion>;
|
|
||||||
virtual ~BaseVersion() {}
|
virtual ~BaseVersion() {}
|
||||||
/*!
|
/*!
|
||||||
* A string used to identify this version in config files.
|
* A string used to identify this version in config files.
|
||||||
@ -55,4 +54,6 @@ public:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(BaseVersion::Ptr)
|
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(BaseVersionPtr)
|
||||||
|
@ -40,20 +40,20 @@ BaseVersionList::BaseVersionList(QObject *parent) : QAbstractListModel(parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseVersion::Ptr BaseVersionList::findVersion(const QString &descriptor)
|
BaseVersionPtr BaseVersionList::findVersion(const QString &descriptor)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count(); i++)
|
for (int i = 0; i < count(); i++)
|
||||||
{
|
{
|
||||||
if (at(i)->descriptor() == descriptor)
|
if (at(i)->descriptor() == descriptor)
|
||||||
return at(i);
|
return at(i);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return BaseVersionPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseVersion::Ptr BaseVersionList::getRecommended() const
|
BaseVersionPtr BaseVersionList::getRecommended() const
|
||||||
{
|
{
|
||||||
if (count() <= 0)
|
if (count() <= 0)
|
||||||
return nullptr;
|
return BaseVersionPtr();
|
||||||
else
|
else
|
||||||
return at(0);
|
return at(0);
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ QVariant BaseVersionList::data(const QModelIndex &index, int role) const
|
|||||||
if (index.row() > count())
|
if (index.row() > count())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
BaseVersion::Ptr version = at(index.row());
|
BaseVersionPtr version = at(index.row());
|
||||||
|
|
||||||
switch (role)
|
switch (role)
|
||||||
{
|
{
|
||||||
@ -95,12 +95,12 @@ BaseVersionList::RoleList BaseVersionList::providesRoles() const
|
|||||||
int BaseVersionList::rowCount(const QModelIndex &parent) const
|
int BaseVersionList::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
// Return count
|
// Return count
|
||||||
return parent.isValid() ? 0 : count();
|
return count();
|
||||||
}
|
}
|
||||||
|
|
||||||
int BaseVersionList::columnCount(const QModelIndex &parent) const
|
int BaseVersionList::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> BaseVersionList::roleNames() const
|
QHash<int, QByteArray> BaseVersionList::roleNames() const
|
||||||
|
@ -70,7 +70,7 @@ public:
|
|||||||
virtual bool isLoaded() = 0;
|
virtual bool isLoaded() = 0;
|
||||||
|
|
||||||
//! Gets the version at the given index.
|
//! Gets the version at the given index.
|
||||||
virtual const BaseVersion::Ptr at(int i) const = 0;
|
virtual const BaseVersionPtr at(int i) const = 0;
|
||||||
|
|
||||||
//! Returns the number of versions in the list.
|
//! Returns the number of versions in the list.
|
||||||
virtual int count() const = 0;
|
virtual int count() const = 0;
|
||||||
@ -90,13 +90,13 @@ public:
|
|||||||
* \return A const pointer to the version with the given descriptor. NULL if
|
* \return A const pointer to the version with the given descriptor. NULL if
|
||||||
* one doesn't exist.
|
* one doesn't exist.
|
||||||
*/
|
*/
|
||||||
virtual BaseVersion::Ptr findVersion(const QString &descriptor);
|
virtual BaseVersionPtr findVersion(const QString &descriptor);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the recommended version from this list
|
* \brief Gets the recommended version from this list
|
||||||
* If the list doesn't support recommended versions, this works exactly as getLatestStable
|
* If the list doesn't support recommended versions, this works exactly as getLatestStable
|
||||||
*/
|
*/
|
||||||
virtual BaseVersion::Ptr getRecommended() const;
|
virtual BaseVersionPtr getRecommended() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sorts the version list.
|
* Sorts the version list.
|
||||||
@ -117,5 +117,5 @@ slots:
|
|||||||
* then copies the versions and sets their parents correctly.
|
* then copies the versions and sets their parents correctly.
|
||||||
* \param versions List of versions whose parents should be set.
|
* \param versions List of versions whose parents should be set.
|
||||||
*/
|
*/
|
||||||
virtual void updateListData(QList<BaseVersion::Ptr> versions) = 0;
|
virtual void updateListData(QList<BaseVersionPtr> versions) = 0;
|
||||||
};
|
};
|
||||||
|
@ -24,15 +24,13 @@ set(CORE_SOURCES
|
|||||||
NullInstance.h
|
NullInstance.h
|
||||||
MMCZip.h
|
MMCZip.h
|
||||||
MMCZip.cpp
|
MMCZip.cpp
|
||||||
StringUtils.h
|
MMCStrings.h
|
||||||
StringUtils.cpp
|
MMCStrings.cpp
|
||||||
RuntimeContext.h
|
RuntimeContext.h
|
||||||
|
|
||||||
# Basic instance manipulation tasks (derived from InstanceTask)
|
# Basic instance manipulation tasks (derived from InstanceTask)
|
||||||
InstanceCreationTask.h
|
InstanceCreationTask.h
|
||||||
InstanceCreationTask.cpp
|
InstanceCreationTask.cpp
|
||||||
InstanceCopyPrefs.h
|
|
||||||
InstanceCopyPrefs.cpp
|
|
||||||
InstanceCopyTask.h
|
InstanceCopyTask.h
|
||||||
InstanceCopyTask.cpp
|
InstanceCopyTask.cpp
|
||||||
InstanceImportTask.h
|
InstanceImportTask.h
|
||||||
@ -89,18 +87,7 @@ set(CORE_SOURCES
|
|||||||
# Time
|
# Time
|
||||||
MMCTime.h
|
MMCTime.h
|
||||||
MMCTime.cpp
|
MMCTime.cpp
|
||||||
|
|
||||||
MTPixmapCache.h
|
|
||||||
)
|
)
|
||||||
if (UNIX AND NOT CYGWIN AND NOT APPLE)
|
|
||||||
set(CORE_SOURCES
|
|
||||||
${CORE_SOURCES}
|
|
||||||
|
|
||||||
# MangoHud
|
|
||||||
MangoHud.h
|
|
||||||
MangoHud.cpp
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(PATHMATCHER_SOURCES
|
set(PATHMATCHER_SOURCES
|
||||||
# Path matchers
|
# Path matchers
|
||||||
@ -108,7 +95,6 @@ set(PATHMATCHER_SOURCES
|
|||||||
pathmatcher/IPathMatcher.h
|
pathmatcher/IPathMatcher.h
|
||||||
pathmatcher/MultiMatcher.h
|
pathmatcher/MultiMatcher.h
|
||||||
pathmatcher/RegexpMatcher.h
|
pathmatcher/RegexpMatcher.h
|
||||||
pathmatcher/SimplePrefixMatcher.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(NET_SOURCES
|
set(NET_SOURCES
|
||||||
@ -551,26 +537,11 @@ set(ATLAUNCHER_SOURCES
|
|||||||
modplatform/atlauncher/ATLShareCode.h
|
modplatform/atlauncher/ATLShareCode.h
|
||||||
)
|
)
|
||||||
|
|
||||||
######## Logging categories ########
|
|
||||||
|
|
||||||
ecm_qt_declare_logging_category(CORE_SOURCES
|
|
||||||
HEADER Logging.h
|
|
||||||
IDENTIFIER authCredentials
|
|
||||||
CATEGORY_NAME "launcher.auth.credentials"
|
|
||||||
DEFAULT_SEVERITY Warning
|
|
||||||
DESCRIPTION "Secrets and credentials for debugging purposes"
|
|
||||||
EXPORT "${Launcher_Name}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if(KDE_INSTALL_LOGGINGCATEGORIESDIR) # only install if there is a standard path for this
|
|
||||||
ecm_qt_install_logging_categories(
|
|
||||||
EXPORT "${Launcher_Name}"
|
|
||||||
DESTINATION "${KDE_INSTALL_LOGGINGCATEGORIESDIR}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
################################ COMPILE ################################
|
################################ COMPILE ################################
|
||||||
|
|
||||||
|
# we need zlib
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
|
||||||
set(LOGIC_SOURCES
|
set(LOGIC_SOURCES
|
||||||
${CORE_SOURCES}
|
${CORE_SOURCES}
|
||||||
${PATHMATCHER_SOURCES}
|
${PATHMATCHER_SOURCES}
|
||||||
@ -605,8 +576,6 @@ SET(LAUNCHER_SOURCES
|
|||||||
# Application base
|
# Application base
|
||||||
Application.h
|
Application.h
|
||||||
Application.cpp
|
Application.cpp
|
||||||
DataMigrationTask.h
|
|
||||||
DataMigrationTask.cpp
|
|
||||||
UpdateController.cpp
|
UpdateController.cpp
|
||||||
UpdateController.h
|
UpdateController.h
|
||||||
ApplicationMessage.h
|
ApplicationMessage.h
|
||||||
@ -630,12 +599,9 @@ SET(LAUNCHER_SOURCES
|
|||||||
resources/pe_light/pe_light.qrc
|
resources/pe_light/pe_light.qrc
|
||||||
resources/pe_colored/pe_colored.qrc
|
resources/pe_colored/pe_colored.qrc
|
||||||
resources/pe_blue/pe_blue.qrc
|
resources/pe_blue/pe_blue.qrc
|
||||||
resources/breeze_dark/breeze_dark.qrc
|
|
||||||
resources/breeze_light/breeze_light.qrc
|
|
||||||
resources/OSX/OSX.qrc
|
resources/OSX/OSX.qrc
|
||||||
resources/iOS/iOS.qrc
|
resources/iOS/iOS.qrc
|
||||||
resources/flat/flat.qrc
|
resources/flat/flat.qrc
|
||||||
resources/flat_white/flat_white.qrc
|
|
||||||
resources/documents/documents.qrc
|
resources/documents/documents.qrc
|
||||||
../${Launcher_Branding_LogoQRC}
|
../${Launcher_Branding_LogoQRC}
|
||||||
|
|
||||||
@ -683,8 +649,6 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/themes/ITheme.h
|
ui/themes/ITheme.h
|
||||||
ui/themes/SystemTheme.cpp
|
ui/themes/SystemTheme.cpp
|
||||||
ui/themes/SystemTheme.h
|
ui/themes/SystemTheme.h
|
||||||
ui/themes/ThemeManager.cpp
|
|
||||||
ui/themes/ThemeManager.h
|
|
||||||
|
|
||||||
# Processes
|
# Processes
|
||||||
LaunchController.h
|
LaunchController.h
|
||||||
@ -709,8 +673,6 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/pages/instance/GameOptionsPage.h
|
ui/pages/instance/GameOptionsPage.h
|
||||||
ui/pages/instance/VersionPage.cpp
|
ui/pages/instance/VersionPage.cpp
|
||||||
ui/pages/instance/VersionPage.h
|
ui/pages/instance/VersionPage.h
|
||||||
ui/pages/instance/ManagedPackPage.cpp
|
|
||||||
ui/pages/instance/ManagedPackPage.h
|
|
||||||
ui/pages/instance/TexturePackPage.h
|
ui/pages/instance/TexturePackPage.h
|
||||||
ui/pages/instance/ResourcePackPage.h
|
ui/pages/instance/ResourcePackPage.h
|
||||||
ui/pages/instance/ShaderPackPage.h
|
ui/pages/instance/ShaderPackPage.h
|
||||||
@ -827,8 +789,6 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/dialogs/ExportInstanceDialog.h
|
ui/dialogs/ExportInstanceDialog.h
|
||||||
ui/dialogs/IconPickerDialog.cpp
|
ui/dialogs/IconPickerDialog.cpp
|
||||||
ui/dialogs/IconPickerDialog.h
|
ui/dialogs/IconPickerDialog.h
|
||||||
ui/dialogs/ImportResourcePackDialog.cpp
|
|
||||||
ui/dialogs/ImportResourcePackDialog.h
|
|
||||||
ui/dialogs/LoginDialog.cpp
|
ui/dialogs/LoginDialog.cpp
|
||||||
ui/dialogs/LoginDialog.h
|
ui/dialogs/LoginDialog.h
|
||||||
ui/dialogs/MSALoginDialog.cpp
|
ui/dialogs/MSALoginDialog.cpp
|
||||||
@ -923,6 +883,16 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/instanceview/VisualGroup.h
|
ui/instanceview/VisualGroup.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(LAUNCHER_SOURCES
|
||||||
|
${LAUNCHER_SOURCES}
|
||||||
|
|
||||||
|
# GUI - dark titlebar for Windows 10/11
|
||||||
|
ui/WinDarkmode.h
|
||||||
|
ui/WinDarkmode.cpp
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
qt_wrap_ui(LAUNCHER_UI
|
qt_wrap_ui(LAUNCHER_UI
|
||||||
ui/setupwizard/PasteWizardPage.ui
|
ui/setupwizard/PasteWizardPage.ui
|
||||||
ui/pages/global/AccountListPage.ui
|
ui/pages/global/AccountListPage.ui
|
||||||
@ -940,7 +910,6 @@ qt_wrap_ui(LAUNCHER_UI
|
|||||||
ui/pages/instance/OtherLogsPage.ui
|
ui/pages/instance/OtherLogsPage.ui
|
||||||
ui/pages/instance/InstanceSettingsPage.ui
|
ui/pages/instance/InstanceSettingsPage.ui
|
||||||
ui/pages/instance/VersionPage.ui
|
ui/pages/instance/VersionPage.ui
|
||||||
ui/pages/instance/ManagedPackPage.ui
|
|
||||||
ui/pages/instance/WorldListPage.ui
|
ui/pages/instance/WorldListPage.ui
|
||||||
ui/pages/instance/ScreenshotsPage.ui
|
ui/pages/instance/ScreenshotsPage.ui
|
||||||
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
|
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
|
||||||
@ -968,7 +937,6 @@ qt_wrap_ui(LAUNCHER_UI
|
|||||||
ui/dialogs/SkinUploadDialog.ui
|
ui/dialogs/SkinUploadDialog.ui
|
||||||
ui/dialogs/ExportInstanceDialog.ui
|
ui/dialogs/ExportInstanceDialog.ui
|
||||||
ui/dialogs/IconPickerDialog.ui
|
ui/dialogs/IconPickerDialog.ui
|
||||||
ui/dialogs/ImportResourcePackDialog.ui
|
|
||||||
ui/dialogs/MSALoginDialog.ui
|
ui/dialogs/MSALoginDialog.ui
|
||||||
ui/dialogs/OfflineLoginDialog.ui
|
ui/dialogs/OfflineLoginDialog.ui
|
||||||
ui/dialogs/AboutDialog.ui
|
ui/dialogs/AboutDialog.ui
|
||||||
@ -987,8 +955,6 @@ qt_add_resources(LAUNCHER_RESOURCES
|
|||||||
resources/pe_light/pe_light.qrc
|
resources/pe_light/pe_light.qrc
|
||||||
resources/pe_colored/pe_colored.qrc
|
resources/pe_colored/pe_colored.qrc
|
||||||
resources/pe_blue/pe_blue.qrc
|
resources/pe_blue/pe_blue.qrc
|
||||||
resources/breeze_dark/breeze_dark.qrc
|
|
||||||
resources/breeze_light/breeze_light.qrc
|
|
||||||
resources/OSX/OSX.qrc
|
resources/OSX/OSX.qrc
|
||||||
resources/iOS/iOS.qrc
|
resources/iOS/iOS.qrc
|
||||||
resources/flat/flat.qrc
|
resources/flat/flat.qrc
|
||||||
@ -1095,99 +1061,96 @@ if(INSTALL_BUNDLE STREQUAL "full")
|
|||||||
COMPONENT Runtime
|
COMPONENT Runtime
|
||||||
)
|
)
|
||||||
# Bundle plugins
|
# Bundle plugins
|
||||||
# Image formats
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||||
install(
|
# Image formats
|
||||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
|
||||||
CONFIGURATIONS Debug RelWithDebInfo ""
|
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
|
||||||
COMPONENT Runtime
|
|
||||||
REGEX "tga|tiff|mng" EXCLUDE
|
|
||||||
)
|
|
||||||
install(
|
|
||||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
|
||||||
CONFIGURATIONS Release MinSizeRel
|
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
|
||||||
COMPONENT Runtime
|
|
||||||
REGEX "tga|tiff|mng" EXCLUDE
|
|
||||||
REGEX "d\\." EXCLUDE
|
|
||||||
REGEX "_debug\\." EXCLUDE
|
|
||||||
REGEX "\\.dSYM" EXCLUDE
|
|
||||||
)
|
|
||||||
# Icon engines
|
|
||||||
install(
|
|
||||||
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
|
|
||||||
CONFIGURATIONS Debug RelWithDebInfo ""
|
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
|
||||||
COMPONENT Runtime
|
|
||||||
REGEX "fontawesome" EXCLUDE
|
|
||||||
)
|
|
||||||
install(
|
|
||||||
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
|
|
||||||
CONFIGURATIONS Release MinSizeRel
|
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
|
||||||
COMPONENT Runtime
|
|
||||||
REGEX "fontawesome" EXCLUDE
|
|
||||||
REGEX "d\\." EXCLUDE
|
|
||||||
REGEX "_debug\\." EXCLUDE
|
|
||||||
REGEX "\\.dSYM" EXCLUDE
|
|
||||||
)
|
|
||||||
# Platform plugins
|
|
||||||
install(
|
|
||||||
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
|
|
||||||
CONFIGURATIONS Debug RelWithDebInfo ""
|
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
|
||||||
COMPONENT Runtime
|
|
||||||
REGEX "minimal|linuxfb|offscreen" EXCLUDE
|
|
||||||
)
|
|
||||||
install(
|
|
||||||
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
|
|
||||||
CONFIGURATIONS Release MinSizeRel
|
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
|
||||||
COMPONENT Runtime
|
|
||||||
REGEX "minimal|linuxfb|offscreen" EXCLUDE
|
|
||||||
REGEX "[^2]d\\." EXCLUDE
|
|
||||||
REGEX "_debug\\." EXCLUDE
|
|
||||||
REGEX "\\.dSYM" EXCLUDE
|
|
||||||
)
|
|
||||||
# Style plugins
|
|
||||||
if(EXISTS "${QT_PLUGINS_DIR}/styles")
|
|
||||||
install(
|
install(
|
||||||
DIRECTORY "${QT_PLUGINS_DIR}/styles"
|
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||||
CONFIGURATIONS Debug RelWithDebInfo ""
|
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
COMPONENT Runtime
|
COMPONENT Runtime
|
||||||
|
REGEX "tga|tiff|mng" EXCLUDE
|
||||||
)
|
)
|
||||||
|
# Icon engines
|
||||||
install(
|
install(
|
||||||
DIRECTORY "${QT_PLUGINS_DIR}/styles"
|
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
|
||||||
CONFIGURATIONS Release MinSizeRel
|
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
COMPONENT Runtime
|
COMPONENT Runtime
|
||||||
|
REGEX "fontawesome" EXCLUDE
|
||||||
|
)
|
||||||
|
# Platform plugins
|
||||||
|
install(
|
||||||
|
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
|
||||||
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
|
COMPONENT Runtime
|
||||||
|
REGEX "minimal|linuxfb|offscreen" EXCLUDE
|
||||||
|
)
|
||||||
|
# Style plugins
|
||||||
|
if(EXISTS "${QT_PLUGINS_DIR}/styles")
|
||||||
|
install(
|
||||||
|
DIRECTORY "${QT_PLUGINS_DIR}/styles"
|
||||||
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
|
COMPONENT Runtime
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
# TLS plugins (Qt 6 only)
|
||||||
|
if(EXISTS "${QT_PLUGINS_DIR}/tls")
|
||||||
|
install(
|
||||||
|
DIRECTORY "${QT_PLUGINS_DIR}/tls"
|
||||||
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
|
COMPONENT Runtime
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# Image formats
|
||||||
|
install(
|
||||||
|
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||||
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
|
COMPONENT Runtime
|
||||||
|
REGEX "tga|tiff|mng" EXCLUDE
|
||||||
REGEX "d\\." EXCLUDE
|
REGEX "d\\." EXCLUDE
|
||||||
REGEX "_debug\\." EXCLUDE
|
REGEX "_debug\\." EXCLUDE
|
||||||
REGEX "\\.dSYM" EXCLUDE
|
REGEX "\\.dSYM" EXCLUDE
|
||||||
)
|
)
|
||||||
endif()
|
# Icon engines
|
||||||
# TLS plugins (Qt 6 only)
|
|
||||||
if(EXISTS "${QT_PLUGINS_DIR}/tls")
|
|
||||||
install(
|
install(
|
||||||
DIRECTORY "${QT_PLUGINS_DIR}/tls"
|
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
|
||||||
CONFIGURATIONS Debug RelWithDebInfo ""
|
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
COMPONENT Runtime
|
COMPONENT Runtime
|
||||||
PATTERN "*qopensslbackend*" EXCLUDE
|
REGEX "fontawesome" EXCLUDE
|
||||||
PATTERN "*qcertonlybackend*" EXCLUDE
|
REGEX "d\\." EXCLUDE
|
||||||
)
|
|
||||||
install(
|
|
||||||
DIRECTORY "${QT_PLUGINS_DIR}/tls"
|
|
||||||
CONFIGURATIONS Release MinSizeRel
|
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
|
||||||
COMPONENT Runtime
|
|
||||||
REGEX "dd\\." EXCLUDE
|
|
||||||
REGEX "_debug\\." EXCLUDE
|
REGEX "_debug\\." EXCLUDE
|
||||||
REGEX "\\.dSYM" EXCLUDE
|
REGEX "\\.dSYM" EXCLUDE
|
||||||
PATTERN "*qopensslbackend*" EXCLUDE
|
|
||||||
PATTERN "*qcertonlybackend*" EXCLUDE
|
|
||||||
)
|
)
|
||||||
|
# Platform plugins
|
||||||
|
install(
|
||||||
|
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
|
||||||
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
|
COMPONENT Runtime
|
||||||
|
REGEX "minimal|linuxfb|offscreen" EXCLUDE
|
||||||
|
REGEX "d\\." EXCLUDE
|
||||||
|
REGEX "_debug\\." EXCLUDE
|
||||||
|
REGEX "\\.dSYM" EXCLUDE
|
||||||
|
)
|
||||||
|
# Style plugins
|
||||||
|
if(EXISTS "${QT_PLUGINS_DIR}/styles")
|
||||||
|
install(
|
||||||
|
DIRECTORY "${QT_PLUGINS_DIR}/styles"
|
||||||
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
|
COMPONENT Runtime
|
||||||
|
REGEX "d\\." EXCLUDE
|
||||||
|
REGEX "_debug\\." EXCLUDE
|
||||||
|
REGEX "\\.dSYM" EXCLUDE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
# TLS plugins (Qt 6 only)
|
||||||
|
if(EXISTS "${QT_PLUGINS_DIR}/tls")
|
||||||
|
install(
|
||||||
|
DIRECTORY "${QT_PLUGINS_DIR}/tls"
|
||||||
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
|
COMPONENT Runtime
|
||||||
|
REGEX "_debug\\." EXCLUDE
|
||||||
|
REGEX "\\.dSYM" EXCLUDE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
configure_file(
|
configure_file(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in"
|
"${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in"
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
|
|
||||||
#include "DataMigrationTask.h"
|
|
||||||
|
|
||||||
#include "FileSystem.h"
|
|
||||||
|
|
||||||
#include <QDirIterator>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QMap>
|
|
||||||
|
|
||||||
#include <QtConcurrent>
|
|
||||||
|
|
||||||
DataMigrationTask::DataMigrationTask(QObject* parent,
|
|
||||||
const QString& sourcePath,
|
|
||||||
const QString& targetPath,
|
|
||||||
const IPathMatcher::Ptr pathMatcher)
|
|
||||||
: Task(parent), m_sourcePath(sourcePath), m_targetPath(targetPath), m_pathMatcher(pathMatcher), m_copy(sourcePath, targetPath)
|
|
||||||
{
|
|
||||||
m_copy.matcher(m_pathMatcher.get()).whitelist(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataMigrationTask::executeTask()
|
|
||||||
{
|
|
||||||
setStatus(tr("Scanning files..."));
|
|
||||||
|
|
||||||
// 1. Scan
|
|
||||||
// Check how many files we gotta copy
|
|
||||||
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
|
|
||||||
return m_copy(true); // dry run to collect amount of files
|
|
||||||
});
|
|
||||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
|
|
||||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::dryRunAborted);
|
|
||||||
m_copyFutureWatcher.setFuture(m_copyFuture);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataMigrationTask::dryRunFinished()
|
|
||||||
{
|
|
||||||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
|
|
||||||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::dryRunAborted);
|
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
if (!m_copyFuture.isValid() || !m_copyFuture.result()) {
|
|
||||||
#else
|
|
||||||
if (!m_copyFuture.result()) {
|
|
||||||
#endif
|
|
||||||
emitFailed(tr("Failed to scan source path."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Copy
|
|
||||||
// Actually copy all files now.
|
|
||||||
m_toCopy = m_copy.totalCopied();
|
|
||||||
connect(&m_copy, &FS::copy::fileCopied, [&, this](const QString& relativeName) {
|
|
||||||
QString shortenedName = relativeName;
|
|
||||||
// shorten the filename to hopefully fit into one line
|
|
||||||
if (shortenedName.length() > 50)
|
|
||||||
shortenedName = relativeName.left(20) + "…" + relativeName.right(29);
|
|
||||||
setProgress(m_copy.totalCopied(), m_toCopy);
|
|
||||||
setStatus(tr("Copying %1…").arg(shortenedName));
|
|
||||||
});
|
|
||||||
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
|
|
||||||
return m_copy(false); // actually copy now
|
|
||||||
});
|
|
||||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
|
|
||||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::copyAborted);
|
|
||||||
m_copyFutureWatcher.setFuture(m_copyFuture);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataMigrationTask::dryRunAborted()
|
|
||||||
{
|
|
||||||
emitFailed(tr("Aborted"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataMigrationTask::copyFinished()
|
|
||||||
{
|
|
||||||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
|
|
||||||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::copyAborted);
|
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
if (!m_copyFuture.isValid() || !m_copyFuture.result()) {
|
|
||||||
#else
|
|
||||||
if (!m_copyFuture.result()) {
|
|
||||||
#endif
|
|
||||||
emitFailed(tr("Some paths could not be copied!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emitSucceeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataMigrationTask::copyAborted()
|
|
||||||
{
|
|
||||||
emitFailed(tr("Aborted"));
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "FileSystem.h"
|
|
||||||
#include "pathmatcher/IPathMatcher.h"
|
|
||||||
#include "tasks/Task.h"
|
|
||||||
|
|
||||||
#include <QFuture>
|
|
||||||
#include <QFutureWatcher>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Migrate existing data from other MMC-like launchers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class DataMigrationTask : public Task {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit DataMigrationTask(QObject* parent, const QString& sourcePath, const QString& targetPath, const IPathMatcher::Ptr pathmatcher);
|
|
||||||
~DataMigrationTask() override = default;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void executeTask() override;
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void dryRunFinished();
|
|
||||||
void dryRunAborted();
|
|
||||||
void copyFinished();
|
|
||||||
void copyAborted();
|
|
||||||
|
|
||||||
private:
|
|
||||||
const QString& m_sourcePath;
|
|
||||||
const QString& m_targetPath;
|
|
||||||
const IPathMatcher::Ptr m_pathMatcher;
|
|
||||||
|
|
||||||
FS::copy m_copy;
|
|
||||||
int m_toCopy = 0;
|
|
||||||
QFuture<bool> m_copyFuture;
|
|
||||||
QFutureWatcher<bool> m_copyFutureWatcher;
|
|
||||||
};
|
|
@ -44,19 +44,15 @@
|
|||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "DesktopServices.h"
|
#include "DesktopServices.h"
|
||||||
#include "StringUtils.h"
|
|
||||||
|
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
#include <objidl.h>
|
#include <objidl.h>
|
||||||
#include <shlguid.h>
|
#include <shlguid.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <shobjidl.h>
|
#include <shobjidl.h>
|
||||||
#include <sys/utime.h>
|
#include <sys/utime.h>
|
||||||
#include <versionhelpers.h>
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winnls.h>
|
#include <winnls.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -83,6 +79,22 @@ namespace fs = std::filesystem;
|
|||||||
namespace fs = ghc::filesystem;
|
namespace fs = ghc::filesystem;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined Q_OS_WIN32
|
||||||
|
|
||||||
|
std::wstring toStdString(QString s)
|
||||||
|
{
|
||||||
|
return s.toStdWString();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
std::string toStdString(QString s)
|
||||||
|
{
|
||||||
|
return s.toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace FS {
|
namespace FS {
|
||||||
|
|
||||||
void ensureExists(const QDir& dir)
|
void ensureExists(const QDir& dir)
|
||||||
@ -151,13 +163,9 @@ bool ensureFolderPathExists(QString foldernamepath)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Copies a directory and it's contents from src to dest
|
bool copy::operator()(const QString& offset)
|
||||||
/// @param offset subdirectory form src to copy to dest
|
|
||||||
/// @return if there was an error during the filecopy
|
|
||||||
bool copy::operator()(const QString& offset, bool dryRun)
|
|
||||||
{
|
{
|
||||||
using copy_opts = fs::copy_options;
|
using copy_opts = fs::copy_options;
|
||||||
m_copied = 0; // reset counter
|
|
||||||
|
|
||||||
// NOTE always deep copy on windows. the alternatives are too messy.
|
// NOTE always deep copy on windows. the alternatives are too messy.
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
@ -177,21 +185,18 @@ bool copy::operator()(const QString& offset, bool dryRun)
|
|||||||
|
|
||||||
// Function that'll do the actual copying
|
// Function that'll do the actual copying
|
||||||
auto copy_file = [&](QString src_path, QString relative_dst_path) {
|
auto copy_file = [&](QString src_path, QString relative_dst_path) {
|
||||||
if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist))
|
if (m_blacklist && m_blacklist->matches(relative_dst_path))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto dst_path = PathCombine(dst, relative_dst_path);
|
auto dst_path = PathCombine(dst, relative_dst_path);
|
||||||
if (!dryRun) {
|
ensureFilePathExists(dst_path);
|
||||||
ensureFilePathExists(dst_path);
|
|
||||||
fs::copy(StringUtils::toStdString(src_path), StringUtils::toStdString(dst_path), opt, err);
|
fs::copy(toStdString(src_path), toStdString(dst_path), opt, err);
|
||||||
}
|
|
||||||
if (err) {
|
if (err) {
|
||||||
qWarning() << "Failed to copy files:" << QString::fromStdString(err.message());
|
qWarning() << "Failed to copy files:" << QString::fromStdString(err.message());
|
||||||
qDebug() << "Source file:" << src_path;
|
qDebug() << "Source file:" << src_path;
|
||||||
qDebug() << "Destination file:" << dst_path;
|
qDebug() << "Destination file:" << dst_path;
|
||||||
}
|
}
|
||||||
m_copied++;
|
|
||||||
emit fileCopied(relative_dst_path);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// We can't use copy_opts::recursive because we need to take into account the
|
// We can't use copy_opts::recursive because we need to take into account the
|
||||||
@ -208,7 +213,7 @@ bool copy::operator()(const QString& offset, bool dryRun)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the root src is not a directory, the previous iterator won't run.
|
// If the root src is not a directory, the previous iterator won't run.
|
||||||
if (!fs::is_directory(StringUtils::toStdString(src)))
|
if (!fs::is_directory(toStdString(src)))
|
||||||
copy_file(src, "");
|
copy_file(src, "");
|
||||||
|
|
||||||
return err.value() == 0;
|
return err.value() == 0;
|
||||||
@ -218,7 +223,7 @@ bool deletePath(QString path)
|
|||||||
{
|
{
|
||||||
std::error_code err;
|
std::error_code err;
|
||||||
|
|
||||||
fs::remove_all(StringUtils::toStdString(path), err);
|
fs::remove_all(toStdString(path), err);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
qWarning() << "Failed to remove files:" << QString::fromStdString(err.message());
|
qWarning() << "Failed to remove files:" << QString::fromStdString(err.message());
|
||||||
@ -235,10 +240,6 @@ bool trash(QString path, QString *pathInTrash = nullptr)
|
|||||||
// FIXME: Figure out trash in Flatpak. Qt seemingly doesn't use the Trash portal
|
// FIXME: Figure out trash in Flatpak. Qt seemingly doesn't use the Trash portal
|
||||||
if (DesktopServices::isFlatpak())
|
if (DesktopServices::isFlatpak())
|
||||||
return false;
|
return false;
|
||||||
#if defined Q_OS_WIN32
|
|
||||||
if (IsWindowsServer())
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
return QFile::moveToTrash(path, pathInTrash);
|
return QFile::moveToTrash(path, pathInTrash);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -349,35 +350,12 @@ QString getDesktopDir()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cross-platform Shortcut creation
|
// Cross-platform Shortcut creation
|
||||||
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon)
|
bool createShortCut(QString location, QString dest, QStringList args, QString name, QString icon)
|
||||||
{
|
{
|
||||||
#if defined(Q_OS_MACOS)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
destination += ".command";
|
location = PathCombine(location, name + ".desktop");
|
||||||
|
|
||||||
QFile f(destination);
|
QFile f(location);
|
||||||
f.open(QIODevice::WriteOnly | QIODevice::Text);
|
|
||||||
QTextStream stream(&f);
|
|
||||||
|
|
||||||
QString argstring;
|
|
||||||
if (!args.empty())
|
|
||||||
argstring = " \"" + args.join("\" \"") + "\"";
|
|
||||||
|
|
||||||
stream << "#!/bin/bash"
|
|
||||||
<< "\n";
|
|
||||||
stream << "\""
|
|
||||||
<< target
|
|
||||||
<< "\" "
|
|
||||||
<< argstring
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
stream.flush();
|
|
||||||
f.close();
|
|
||||||
|
|
||||||
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
|
||||||
QFile f(destination);
|
|
||||||
f.open(QIODevice::WriteOnly | QIODevice::Text);
|
f.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||||
QTextStream stream(&f);
|
QTextStream stream(&f);
|
||||||
|
|
||||||
@ -389,12 +367,10 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
|
|||||||
<< "\n";
|
<< "\n";
|
||||||
stream << "Type=Application"
|
stream << "Type=Application"
|
||||||
<< "\n";
|
<< "\n";
|
||||||
stream << "Exec=\"" << target.toLocal8Bit() << "\"" << argstring.toLocal8Bit() << "\n";
|
stream << "TryExec=" << dest.toLocal8Bit() << "\n";
|
||||||
|
stream << "Exec=" << dest.toLocal8Bit() << argstring.toLocal8Bit() << "\n";
|
||||||
stream << "Name=" << name.toLocal8Bit() << "\n";
|
stream << "Name=" << name.toLocal8Bit() << "\n";
|
||||||
if (!icon.isEmpty())
|
stream << "Icon=" << icon.toLocal8Bit() << "\n";
|
||||||
{
|
|
||||||
stream << "Icon=" << icon.toLocal8Bit() << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.flush();
|
stream.flush();
|
||||||
f.close();
|
f.close();
|
||||||
@ -402,132 +378,25 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
|
|||||||
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
|
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined Q_OS_WIN
|
||||||
QFileInfo targetInfo(target);
|
// TODO: Fix
|
||||||
|
// QFile file(PathCombine(location, name + ".lnk"));
|
||||||
|
// WCHAR *file_w;
|
||||||
|
// WCHAR *dest_w;
|
||||||
|
// WCHAR *args_w;
|
||||||
|
// file.fileName().toWCharArray(file_w);
|
||||||
|
// dest.toWCharArray(dest_w);
|
||||||
|
|
||||||
if (!targetInfo.exists())
|
// QString argStr;
|
||||||
{
|
// for (int i = 0; i < args.count(); i++)
|
||||||
qWarning() << "Target file does not exist!";
|
// {
|
||||||
return false;
|
// argStr.append(args[i]);
|
||||||
}
|
// argStr.append(" ");
|
||||||
|
// }
|
||||||
|
// argStr.toWCharArray(args_w);
|
||||||
|
|
||||||
target = targetInfo.absoluteFilePath();
|
// return SUCCEEDED(CreateLink(file_w, dest_w, args_w));
|
||||||
|
return false;
|
||||||
if (target.length() >= MAX_PATH)
|
|
||||||
{
|
|
||||||
qWarning() << "Target file path is too long!";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!icon.isEmpty() && icon.length() >= MAX_PATH)
|
|
||||||
{
|
|
||||||
qWarning() << "Icon path is too long!";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
destination += ".lnk";
|
|
||||||
|
|
||||||
if (destination.length() >= MAX_PATH)
|
|
||||||
{
|
|
||||||
qWarning() << "Destination path is too long!";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString argStr;
|
|
||||||
int argCount = args.count();
|
|
||||||
for (int i = 0; i < argCount; i++)
|
|
||||||
{
|
|
||||||
if (args[i].contains(' '))
|
|
||||||
{
|
|
||||||
argStr.append('"').append(args[i]).append('"');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
argStr.append(args[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < argCount - 1)
|
|
||||||
{
|
|
||||||
argStr.append(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argStr.length() >= MAX_PATH)
|
|
||||||
{
|
|
||||||
qWarning() << "Arguments string is too long!";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
|
|
||||||
// ...yes, you need to initialize the entire COM stack just to make a shortcut
|
|
||||||
hres = CoInitialize(nullptr);
|
|
||||||
if (FAILED(hres))
|
|
||||||
{
|
|
||||||
qWarning() << "Failed to initialize COM!";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
WCHAR wsz[MAX_PATH];
|
|
||||||
|
|
||||||
IShellLink* psl;
|
|
||||||
|
|
||||||
// create an IShellLink instance - this stores the shortcut's attributes
|
|
||||||
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
|
|
||||||
if (SUCCEEDED(hres))
|
|
||||||
{
|
|
||||||
wmemset(wsz, 0, MAX_PATH);
|
|
||||||
target.toWCharArray(wsz);
|
|
||||||
psl->SetPath(wsz);
|
|
||||||
|
|
||||||
wmemset(wsz, 0, MAX_PATH);
|
|
||||||
argStr.toWCharArray(wsz);
|
|
||||||
psl->SetArguments(wsz);
|
|
||||||
|
|
||||||
wmemset(wsz, 0, MAX_PATH);
|
|
||||||
targetInfo.absolutePath().toWCharArray(wsz);
|
|
||||||
psl->SetWorkingDirectory(wsz); // "Starts in" attribute
|
|
||||||
|
|
||||||
if (!icon.isEmpty())
|
|
||||||
{
|
|
||||||
wmemset(wsz, 0, MAX_PATH);
|
|
||||||
icon.toWCharArray(wsz);
|
|
||||||
psl->SetIconLocation(wsz, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// query an IPersistFile interface from our IShellLink instance
|
|
||||||
// this is the interface that will actually let us save the shortcut to disk!
|
|
||||||
IPersistFile* ppf;
|
|
||||||
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
|
|
||||||
if (SUCCEEDED(hres))
|
|
||||||
{
|
|
||||||
wmemset(wsz, 0, MAX_PATH);
|
|
||||||
destination.toWCharArray(wsz);
|
|
||||||
hres = ppf->Save(wsz, TRUE);
|
|
||||||
if (FAILED(hres))
|
|
||||||
{
|
|
||||||
qWarning() << "IPresistFile->Save() failed";
|
|
||||||
qWarning() << "hres = " << hres;
|
|
||||||
}
|
|
||||||
ppf->Release();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qWarning() << "Failed to query IPersistFile interface from IShellLink instance";
|
|
||||||
qWarning() << "hres = " << hres;
|
|
||||||
}
|
|
||||||
psl->Release();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qWarning() << "Failed to create IShellLink instance";
|
|
||||||
qWarning() << "hres = " << hres;
|
|
||||||
}
|
|
||||||
|
|
||||||
// go away COM, nobody likes you
|
|
||||||
CoUninitialize();
|
|
||||||
|
|
||||||
return SUCCEEDED(hres);
|
|
||||||
#else
|
#else
|
||||||
qWarning("Desktop Shortcuts not supported on your platform!");
|
qWarning("Desktop Shortcuts not supported on your platform!");
|
||||||
return false;
|
return false;
|
||||||
@ -545,7 +414,7 @@ bool overrideFolder(QString overwritten_path, QString override_path)
|
|||||||
fs::copy_options opt = copy_opts::recursive | copy_opts::overwrite_existing;
|
fs::copy_options opt = copy_opts::recursive | copy_opts::overwrite_existing;
|
||||||
|
|
||||||
// FIXME: hello traveller! Apparently std::copy does NOT overwrite existing files on GNU libstdc++ on Windows?
|
// FIXME: hello traveller! Apparently std::copy does NOT overwrite existing files on GNU libstdc++ on Windows?
|
||||||
fs::copy(StringUtils::toStdString(override_path), StringUtils::toStdString(overwritten_path), opt, err);
|
fs::copy(toStdString(override_path), toStdString(overwritten_path), opt, err);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
qCritical() << QString("Failed to apply override from %1 to %2").arg(override_path, overwritten_path);
|
qCritical() << QString("Failed to apply override from %1 to %2").arg(override_path, overwritten_path);
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFlags>
|
#include <QFlags>
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
namespace FS {
|
namespace FS {
|
||||||
|
|
||||||
@ -76,11 +75,9 @@ bool ensureFilePathExists(QString filenamepath);
|
|||||||
*/
|
*/
|
||||||
bool ensureFolderPathExists(QString filenamepath);
|
bool ensureFolderPathExists(QString filenamepath);
|
||||||
|
|
||||||
/// @brief Copies a directory and it's contents from src to dest
|
class copy {
|
||||||
class copy : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
public:
|
||||||
copy(const QString& src, const QString& dst, QObject* parent = nullptr) : QObject(parent)
|
copy(const QString& src, const QString& dst)
|
||||||
{
|
{
|
||||||
m_src.setPath(src);
|
m_src.setPath(src);
|
||||||
m_dst.setPath(dst);
|
m_dst.setPath(dst);
|
||||||
@ -90,35 +87,21 @@ class copy : public QObject {
|
|||||||
m_followSymlinks = follow;
|
m_followSymlinks = follow;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
copy& matcher(const IPathMatcher* filter)
|
copy& blacklist(const IPathMatcher* filter)
|
||||||
{
|
{
|
||||||
m_matcher = filter;
|
m_blacklist = filter;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
copy& whitelist(bool whitelist)
|
bool operator()() { return operator()(QString()); }
|
||||||
{
|
|
||||||
m_whitelist = whitelist;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); }
|
|
||||||
|
|
||||||
int totalCopied() { return m_copied; }
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void fileCopied(const QString& relativeName);
|
|
||||||
// TODO: maybe add a "shouldCopy" signal in the future?
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool operator()(const QString& offset, bool dryRun = false);
|
bool operator()(const QString& offset);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_followSymlinks = true;
|
bool m_followSymlinks = true;
|
||||||
const IPathMatcher* m_matcher = nullptr;
|
const IPathMatcher* m_blacklist = nullptr;
|
||||||
bool m_whitelist = false;
|
|
||||||
QDir m_src;
|
QDir m_src;
|
||||||
QDir m_dst;
|
QDir m_dst;
|
||||||
int m_copied;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,9 +155,4 @@ QString getDesktopDir();
|
|||||||
// Overrides one folder with the contents of another, preserving items exclusive to the first folder
|
// Overrides one folder with the contents of another, preserving items exclusive to the first folder
|
||||||
// Equivalent to doing QDir::rename, but allowing for overrides
|
// Equivalent to doing QDir::rename, but allowing for overrides
|
||||||
bool overrideFolder(QString overwritten_path, QString override_path);
|
bool overrideFolder(QString overwritten_path, QString override_path);
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a shortcut to the specified target file at the specified destination path.
|
|
||||||
*/
|
|
||||||
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon);
|
|
||||||
}
|
}
|
||||||
|
@ -1,135 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by marcelohdez on 10/22/22.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "InstanceCopyPrefs.h"
|
|
||||||
|
|
||||||
bool InstanceCopyPrefs::allTrue() const
|
|
||||||
{
|
|
||||||
return copySaves &&
|
|
||||||
keepPlaytime &&
|
|
||||||
copyGameOptions &&
|
|
||||||
copyResourcePacks &&
|
|
||||||
copyShaderPacks &&
|
|
||||||
copyServers &&
|
|
||||||
copyMods &&
|
|
||||||
copyScreenshots;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a single RegEx string of the selected folders/files to filter out (ex: ".minecraft/saves|.minecraft/server.dat")
|
|
||||||
QString InstanceCopyPrefs::getSelectedFiltersAsRegex() const
|
|
||||||
{
|
|
||||||
QStringList filters;
|
|
||||||
|
|
||||||
if(!copySaves)
|
|
||||||
filters << "saves";
|
|
||||||
|
|
||||||
if(!copyGameOptions)
|
|
||||||
filters << "options.txt";
|
|
||||||
|
|
||||||
if(!copyResourcePacks)
|
|
||||||
filters << "resourcepacks" << "texturepacks";
|
|
||||||
|
|
||||||
if(!copyShaderPacks)
|
|
||||||
filters << "shaderpacks";
|
|
||||||
|
|
||||||
if(!copyServers)
|
|
||||||
filters << "servers.dat" << "servers.dat_old" << "server-resource-packs";
|
|
||||||
|
|
||||||
if(!copyMods)
|
|
||||||
filters << "coremods" << "mods" << "config";
|
|
||||||
|
|
||||||
if(!copyScreenshots)
|
|
||||||
filters << "screenshots";
|
|
||||||
|
|
||||||
// If we have any filters to add, join them as a single regex string to return:
|
|
||||||
if (!filters.isEmpty()) {
|
|
||||||
const QString MC_ROOT = "[.]?minecraft/";
|
|
||||||
// Ensure first filter starts with root, then join other filters with OR regex before root (ex: ".minecraft/saves|.minecraft/mods"):
|
|
||||||
return MC_ROOT + filters.join("|" + MC_ROOT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// ======= Getters =======
|
|
||||||
bool InstanceCopyPrefs::isCopySavesEnabled() const
|
|
||||||
{
|
|
||||||
return copySaves;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceCopyPrefs::isKeepPlaytimeEnabled() const
|
|
||||||
{
|
|
||||||
return keepPlaytime;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceCopyPrefs::isCopyGameOptionsEnabled() const
|
|
||||||
{
|
|
||||||
return copyGameOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceCopyPrefs::isCopyResourcePacksEnabled() const
|
|
||||||
{
|
|
||||||
return copyResourcePacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceCopyPrefs::isCopyShaderPacksEnabled() const
|
|
||||||
{
|
|
||||||
return copyShaderPacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceCopyPrefs::isCopyServersEnabled() const
|
|
||||||
{
|
|
||||||
return copyServers;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceCopyPrefs::isCopyModsEnabled() const
|
|
||||||
{
|
|
||||||
return copyMods;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceCopyPrefs::isCopyScreenshotsEnabled() const
|
|
||||||
{
|
|
||||||
return copyScreenshots;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ======= Setters =======
|
|
||||||
void InstanceCopyPrefs::enableCopySaves(bool b)
|
|
||||||
{
|
|
||||||
copySaves = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceCopyPrefs::enableKeepPlaytime(bool b)
|
|
||||||
{
|
|
||||||
keepPlaytime = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceCopyPrefs::enableCopyGameOptions(bool b)
|
|
||||||
{
|
|
||||||
copyGameOptions = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceCopyPrefs::enableCopyResourcePacks(bool b)
|
|
||||||
{
|
|
||||||
copyResourcePacks = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceCopyPrefs::enableCopyShaderPacks(bool b)
|
|
||||||
{
|
|
||||||
copyShaderPacks = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceCopyPrefs::enableCopyServers(bool b)
|
|
||||||
{
|
|
||||||
copyServers = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceCopyPrefs::enableCopyMods(bool b)
|
|
||||||
{
|
|
||||||
copyMods = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceCopyPrefs::enableCopyScreenshots(bool b)
|
|
||||||
{
|
|
||||||
copyScreenshots = b;
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by marcelohdez on 10/22/22.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
struct InstanceCopyPrefs {
|
|
||||||
public:
|
|
||||||
[[nodiscard]] bool allTrue() const;
|
|
||||||
[[nodiscard]] QString getSelectedFiltersAsRegex() const;
|
|
||||||
// Getters
|
|
||||||
[[nodiscard]] bool isCopySavesEnabled() const;
|
|
||||||
[[nodiscard]] bool isKeepPlaytimeEnabled() const;
|
|
||||||
[[nodiscard]] bool isCopyGameOptionsEnabled() const;
|
|
||||||
[[nodiscard]] bool isCopyResourcePacksEnabled() const;
|
|
||||||
[[nodiscard]] bool isCopyShaderPacksEnabled() const;
|
|
||||||
[[nodiscard]] bool isCopyServersEnabled() const;
|
|
||||||
[[nodiscard]] bool isCopyModsEnabled() const;
|
|
||||||
[[nodiscard]] bool isCopyScreenshotsEnabled() const;
|
|
||||||
// Setters
|
|
||||||
void enableCopySaves(bool b);
|
|
||||||
void enableKeepPlaytime(bool b);
|
|
||||||
void enableCopyGameOptions(bool b);
|
|
||||||
void enableCopyResourcePacks(bool b);
|
|
||||||
void enableCopyShaderPacks(bool b);
|
|
||||||
void enableCopyServers(bool b);
|
|
||||||
void enableCopyMods(bool b);
|
|
||||||
void enableCopyScreenshots(bool b);
|
|
||||||
|
|
||||||
protected: // data
|
|
||||||
bool copySaves = true;
|
|
||||||
bool keepPlaytime = true;
|
|
||||||
bool copyGameOptions = true;
|
|
||||||
bool copyResourcePacks = true;
|
|
||||||
bool copyShaderPacks = true;
|
|
||||||
bool copyServers = true;
|
|
||||||
bool copyMods = true;
|
|
||||||
bool copyScreenshots = true;
|
|
||||||
};
|
|
@ -5,17 +5,15 @@
|
|||||||
#include "pathmatcher/RegexpMatcher.h"
|
#include "pathmatcher/RegexpMatcher.h"
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrentRun>
|
||||||
|
|
||||||
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs)
|
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime)
|
||||||
{
|
{
|
||||||
m_origInstance = origInstance;
|
m_origInstance = origInstance;
|
||||||
m_keepPlaytime = prefs.isKeepPlaytimeEnabled();
|
m_keepPlaytime = keepPlaytime;
|
||||||
|
|
||||||
QString filters = prefs.getSelectedFiltersAsRegex();
|
if(!copySaves)
|
||||||
if (!filters.isEmpty())
|
|
||||||
{
|
{
|
||||||
// Set regex filter:
|
|
||||||
// FIXME: get this from the original instance type...
|
// FIXME: get this from the original instance type...
|
||||||
auto matcherReal = new RegexpMatcher(filters);
|
auto matcherReal = new RegexpMatcher("[.]?minecraft/saves");
|
||||||
matcherReal->caseSensitive(false);
|
matcherReal->caseSensitive(false);
|
||||||
m_matcher.reset(matcherReal);
|
m_matcher.reset(matcherReal);
|
||||||
}
|
}
|
||||||
@ -25,12 +23,10 @@ void InstanceCopyTask::executeTask()
|
|||||||
{
|
{
|
||||||
setStatus(tr("Copying instance %1").arg(m_origInstance->name()));
|
setStatus(tr("Copying instance %1").arg(m_origInstance->name()));
|
||||||
|
|
||||||
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]{
|
FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
|
||||||
FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
|
folderCopy.followSymlinks(false).blacklist(m_matcher.get());
|
||||||
folderCopy.followSymlinks(false).matcher(m_matcher.get());
|
|
||||||
|
|
||||||
return folderCopy();
|
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy);
|
||||||
});
|
|
||||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished);
|
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished);
|
||||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &InstanceCopyTask::copyAborted);
|
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &InstanceCopyTask::copyAborted);
|
||||||
m_copyFutureWatcher.setFuture(m_copyFuture);
|
m_copyFutureWatcher.setFuture(m_copyFuture);
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
#include <QUrl>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
#include <QUrl>
|
|
||||||
#include "BaseInstance.h"
|
|
||||||
#include "BaseVersion.h"
|
|
||||||
#include "InstanceCopyPrefs.h"
|
|
||||||
#include "InstanceTask.h"
|
|
||||||
#include "net/NetJob.h"
|
|
||||||
#include "settings/SettingsObject.h"
|
#include "settings/SettingsObject.h"
|
||||||
#include "tasks/Task.h"
|
#include "BaseVersion.h"
|
||||||
|
#include "BaseInstance.h"
|
||||||
|
#include "InstanceTask.h"
|
||||||
|
|
||||||
class InstanceCopyTask : public InstanceTask
|
class InstanceCopyTask : public InstanceTask
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs);
|
explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Entry point for tasks.
|
//! Entry point for tasks.
|
||||||
@ -23,8 +22,7 @@ protected:
|
|||||||
void copyFinished();
|
void copyFinished();
|
||||||
void copyAborted();
|
void copyAborted();
|
||||||
|
|
||||||
private:
|
private: /* data */
|
||||||
/* data */
|
|
||||||
InstancePtr m_origInstance;
|
InstancePtr m_origInstance;
|
||||||
QFuture<bool> m_copyFuture;
|
QFuture<bool> m_copyFuture;
|
||||||
QFutureWatcher<bool> m_copyFutureWatcher;
|
QFutureWatcher<bool> m_copyFutureWatcher;
|
||||||
|
@ -25,13 +25,9 @@ void InstanceCreationTask::executeTask()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
qWarning() << "Instance creation failed!";
|
qWarning() << "Instance creation failed!";
|
||||||
if (!m_error_message.isEmpty()) {
|
if (!m_error_message.isEmpty())
|
||||||
qWarning() << "Reason: " << m_error_message;
|
qWarning() << "Reason: " << m_error_message;
|
||||||
emitFailed(tr("Error while creating new instance:\n%1").arg(m_error_message));
|
emitFailed(tr("Error while creating new instance."));
|
||||||
} else {
|
|
||||||
emitFailed(tr("Error while creating new instance."));
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,9 +55,11 @@
|
|||||||
|
|
||||||
#include <quazip/quazipdir.h>
|
#include <quazip/quazipdir.h>
|
||||||
|
|
||||||
InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent, QMap<QString, QString>&& extra_info)
|
InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent)
|
||||||
: m_sourceUrl(sourceUrl), m_extra_info(extra_info), m_parent(parent)
|
{
|
||||||
{}
|
m_sourceUrl = sourceUrl;
|
||||||
|
m_parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
bool InstanceImportTask::abort()
|
bool InstanceImportTask::abort()
|
||||||
{
|
{
|
||||||
@ -162,14 +164,18 @@ void InstanceImportTask::processZipPack()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QStringList paths_to_ignore { "overrides/" };
|
QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg");
|
||||||
|
QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json");
|
||||||
|
|
||||||
if (QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg", paths_to_ignore); !mmcRoot.isNull()) {
|
if (!mmcRoot.isNull())
|
||||||
|
{
|
||||||
// process as MultiMC instance/pack
|
// process as MultiMC instance/pack
|
||||||
qDebug() << "MultiMC:" << mmcRoot;
|
qDebug() << "MultiMC:" << mmcRoot;
|
||||||
root = mmcRoot;
|
root = mmcRoot;
|
||||||
m_modpackType = ModpackType::MultiMC;
|
m_modpackType = ModpackType::MultiMC;
|
||||||
} else if (QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json", paths_to_ignore); !flameRoot.isNull()) {
|
}
|
||||||
|
else if(!flameRoot.isNull())
|
||||||
|
{
|
||||||
// process as Flame pack
|
// process as Flame pack
|
||||||
qDebug() << "Flame:" << flameRoot;
|
qDebug() << "Flame:" << flameRoot;
|
||||||
root = flameRoot;
|
root = flameRoot;
|
||||||
@ -257,34 +263,14 @@ void InstanceImportTask::extractAborted()
|
|||||||
|
|
||||||
void InstanceImportTask::processFlame()
|
void InstanceImportTask::processFlame()
|
||||||
{
|
{
|
||||||
FlameCreationTask* inst_creation_task = nullptr;
|
auto* inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent);
|
||||||
if (!m_extra_info.isEmpty()) {
|
|
||||||
auto pack_id_it = m_extra_info.constFind("pack_id");
|
|
||||||
Q_ASSERT(pack_id_it != m_extra_info.constEnd());
|
|
||||||
auto pack_id = pack_id_it.value();
|
|
||||||
|
|
||||||
auto pack_version_id_it = m_extra_info.constFind("pack_version_id");
|
|
||||||
Q_ASSERT(pack_version_id_it != m_extra_info.constEnd());
|
|
||||||
auto pack_version_id = pack_version_id_it.value();
|
|
||||||
|
|
||||||
QString original_instance_id;
|
|
||||||
auto original_instance_id_it = m_extra_info.constFind("original_instance_id");
|
|
||||||
if (original_instance_id_it != m_extra_info.constEnd())
|
|
||||||
original_instance_id = original_instance_id_it.value();
|
|
||||||
|
|
||||||
inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
|
|
||||||
} else {
|
|
||||||
// FIXME: Find a way to get IDs in directly imported ZIPs
|
|
||||||
inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, {}, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
inst_creation_task->setName(*this);
|
inst_creation_task->setName(*this);
|
||||||
inst_creation_task->setIcon(m_instIcon);
|
inst_creation_task->setIcon(m_instIcon);
|
||||||
inst_creation_task->setGroup(m_instGroup);
|
inst_creation_task->setGroup(m_instGroup);
|
||||||
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
|
|
||||||
|
|
||||||
connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
|
connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
|
||||||
setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
|
setOverride(inst_creation_task->shouldOverride());
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
});
|
});
|
||||||
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
|
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
|
||||||
@ -341,41 +327,14 @@ void InstanceImportTask::processMultiMC()
|
|||||||
|
|
||||||
void InstanceImportTask::processModrinth()
|
void InstanceImportTask::processModrinth()
|
||||||
{
|
{
|
||||||
ModrinthCreationTask* inst_creation_task = nullptr;
|
auto* inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, m_sourceUrl.toString());
|
||||||
if (!m_extra_info.isEmpty()) {
|
|
||||||
auto pack_id_it = m_extra_info.constFind("pack_id");
|
|
||||||
Q_ASSERT(pack_id_it != m_extra_info.constEnd());
|
|
||||||
auto pack_id = pack_id_it.value();
|
|
||||||
|
|
||||||
QString pack_version_id;
|
|
||||||
auto pack_version_id_it = m_extra_info.constFind("pack_version_id");
|
|
||||||
if (pack_version_id_it != m_extra_info.constEnd())
|
|
||||||
pack_version_id = pack_version_id_it.value();
|
|
||||||
|
|
||||||
QString original_instance_id;
|
|
||||||
auto original_instance_id_it = m_extra_info.constFind("original_instance_id");
|
|
||||||
if (original_instance_id_it != m_extra_info.constEnd())
|
|
||||||
original_instance_id = original_instance_id_it.value();
|
|
||||||
|
|
||||||
inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
|
|
||||||
} else {
|
|
||||||
QString pack_id;
|
|
||||||
if (!m_sourceUrl.isEmpty()) {
|
|
||||||
QRegularExpression regex(R"(data\/(.*)\/versions)");
|
|
||||||
pack_id = regex.match(m_sourceUrl.toString()).captured(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Find a way to get the ID in directly imported ZIPs
|
|
||||||
inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
inst_creation_task->setName(*this);
|
inst_creation_task->setName(*this);
|
||||||
inst_creation_task->setIcon(m_instIcon);
|
inst_creation_task->setIcon(m_instIcon);
|
||||||
inst_creation_task->setGroup(m_instGroup);
|
inst_creation_task->setGroup(m_instGroup);
|
||||||
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
|
|
||||||
|
|
||||||
connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
|
connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
|
||||||
setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
|
setOverride(inst_creation_task->shouldOverride());
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
});
|
});
|
||||||
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
|
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
|
||||||
|
@ -56,7 +56,7 @@ class InstanceImportTask : public InstanceTask
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr, QMap<QString, QString>&& extra_info = {});
|
explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr);
|
||||||
|
|
||||||
bool abort() override;
|
bool abort() override;
|
||||||
const QVector<Flame::File> &getBlockedFiles() const
|
const QVector<Flame::File> &getBlockedFiles() const
|
||||||
@ -101,10 +101,6 @@ private: /* data */
|
|||||||
Modrinth,
|
Modrinth,
|
||||||
} m_modpackType = ModpackType::Unknown;
|
} m_modpackType = ModpackType::Unknown;
|
||||||
|
|
||||||
// Extra info we might need, that's available before, but can't be derived from
|
|
||||||
// the source URL / the resource it points to alone.
|
|
||||||
QMap<QString, QString> m_extra_info;
|
|
||||||
|
|
||||||
//FIXME: nuke
|
//FIXME: nuke
|
||||||
QWidget* m_parent;
|
QWidget* m_parent;
|
||||||
};
|
};
|
||||||
|
@ -816,7 +816,7 @@ class InstanceStaging : public Task {
|
|||||||
void childSucceded()
|
void childSucceded()
|
||||||
{
|
{
|
||||||
unsigned sleepTime = backoff();
|
unsigned sleepTime = backoff();
|
||||||
if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, *m_child.get()))
|
if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, m_child->shouldOverride()))
|
||||||
{
|
{
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
return;
|
return;
|
||||||
@ -880,22 +880,25 @@ QString InstanceList::getStagedInstancePath()
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, InstanceTask const& commiting)
|
bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, bool should_override)
|
||||||
{
|
{
|
||||||
QDir dir;
|
QDir dir;
|
||||||
QString instID;
|
QString instID;
|
||||||
InstancePtr inst;
|
InstancePtr inst;
|
||||||
|
|
||||||
auto should_override = commiting.shouldOverride();
|
|
||||||
|
|
||||||
if (should_override) {
|
if (should_override) {
|
||||||
instID = commiting.originalInstanceID();
|
// This is to avoid problems when the instance folder gets manually renamed
|
||||||
|
if ((inst = getInstanceByManagedName(instanceName.originalName()))) {
|
||||||
|
instID = QFileInfo(inst->instanceRoot()).fileName();
|
||||||
|
} else if ((inst = getInstanceByManagedName(instanceName.modifiedName()))) {
|
||||||
|
instID = QFileInfo(inst->instanceRoot()).fileName();
|
||||||
|
} else {
|
||||||
|
instID = FS::RemoveInvalidFilenameChars(instanceName.modifiedName(), '-');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
instID = FS::DirNameFromString(instanceName.modifiedName(), m_instDir);
|
instID = FS::DirNameFromString(instanceName.modifiedName(), m_instDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(!instID.isEmpty());
|
|
||||||
|
|
||||||
{
|
{
|
||||||
WatchLock lock(m_watcher, m_instDir);
|
WatchLock lock(m_watcher, m_instDir);
|
||||||
QString destination = FS::PathCombine(m_instDir, instID);
|
QString destination = FS::PathCombine(m_instDir, instID);
|
||||||
|
@ -133,7 +133,7 @@ public:
|
|||||||
* should_override is used when another similar instance already exists, and we want to override it
|
* should_override is used when another similar instance already exists, and we want to override it
|
||||||
* - for instance, when updating 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, const QString& groupName, bool should_override);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a previously created staging area given by @keyPath - used when creation fails.
|
* Destroy a previously created staging area given by @keyPath - used when creation fails.
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include "ui/pages/BasePageProvider.h"
|
#include "ui/pages/BasePageProvider.h"
|
||||||
#include "ui/pages/instance/LogPage.h"
|
#include "ui/pages/instance/LogPage.h"
|
||||||
#include "ui/pages/instance/VersionPage.h"
|
#include "ui/pages/instance/VersionPage.h"
|
||||||
#include "ui/pages/instance/ManagedPackPage.h"
|
|
||||||
#include "ui/pages/instance/ModFolderPage.h"
|
#include "ui/pages/instance/ModFolderPage.h"
|
||||||
#include "ui/pages/instance/ResourcePackPage.h"
|
#include "ui/pages/instance/ResourcePackPage.h"
|
||||||
#include "ui/pages/instance/TexturePackPage.h"
|
#include "ui/pages/instance/TexturePackPage.h"
|
||||||
@ -34,7 +33,6 @@ public:
|
|||||||
values.append(new LogPage(inst));
|
values.append(new LogPage(inst));
|
||||||
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
|
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
|
||||||
values.append(new VersionPage(onesix.get()));
|
values.append(new VersionPage(onesix.get()));
|
||||||
values.append(ManagedPackPage::createPage(onesix.get()));
|
|
||||||
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList());
|
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList());
|
||||||
modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
|
modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
|
||||||
values.append(modsPage);
|
values.append(modsPage);
|
||||||
|
@ -18,29 +18,6 @@ InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& ol
|
|||||||
return InstanceNameChange::ShouldKeep;
|
return InstanceNameChange::ShouldKeep;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShouldUpdate askIfShouldUpdate(QWidget *parent, QString original_version_name)
|
|
||||||
{
|
|
||||||
auto info = CustomMessageBox::selectable(
|
|
||||||
parent, QObject::tr("Similar modpack was found!"),
|
|
||||||
QObject::tr("One or more of your instances are from this same modpack%1. Do you want to create a "
|
|
||||||
"separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before "
|
|
||||||
"updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).")
|
|
||||||
.arg(original_version_name),
|
|
||||||
QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort);
|
|
||||||
info->setButtonText(QMessageBox::Ok, QObject::tr("Update existing instance"));
|
|
||||||
info->setButtonText(QMessageBox::Abort, QObject::tr("Create new instance"));
|
|
||||||
info->setButtonText(QMessageBox::Reset, QObject::tr("Cancel"));
|
|
||||||
|
|
||||||
info->exec();
|
|
||||||
|
|
||||||
if (info->clickedButton() == info->button(QMessageBox::Ok))
|
|
||||||
return ShouldUpdate::Update;
|
|
||||||
if (info->clickedButton() == info->button(QMessageBox::Abort))
|
|
||||||
return ShouldUpdate::SkipUpdating;
|
|
||||||
return ShouldUpdate::Cancel;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QString InstanceName::name() const
|
QString InstanceName::name() const
|
||||||
{
|
{
|
||||||
if (!m_modified_name.isEmpty())
|
if (!m_modified_name.isEmpty())
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
/* Helpers */
|
/* Helpers */
|
||||||
enum class InstanceNameChange { ShouldChange, ShouldKeep };
|
enum class InstanceNameChange { ShouldChange, ShouldKeep };
|
||||||
[[nodiscard]] InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& old_name, const QString& new_name);
|
[[nodiscard]] InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& old_name, const QString& new_name);
|
||||||
enum class ShouldUpdate { Update, SkipUpdating, Cancel };
|
|
||||||
[[nodiscard]] ShouldUpdate askIfShouldUpdate(QWidget* parent, QString original_version_name);
|
|
||||||
|
|
||||||
struct InstanceName {
|
struct InstanceName {
|
||||||
public:
|
public:
|
||||||
@ -44,20 +42,10 @@ class InstanceTask : public Task, public InstanceName {
|
|||||||
void setGroup(const QString& group) { m_instGroup = group; }
|
void setGroup(const QString& group) { m_instGroup = group; }
|
||||||
QString group() const { return m_instGroup; }
|
QString group() const { return m_instGroup; }
|
||||||
|
|
||||||
[[nodiscard]] bool shouldConfirmUpdate() const { return m_confirm_update; }
|
|
||||||
void setConfirmUpdate(bool confirm) { m_confirm_update = confirm; }
|
|
||||||
|
|
||||||
bool shouldOverride() const { return m_override_existing; }
|
bool shouldOverride() const { return m_override_existing; }
|
||||||
|
|
||||||
[[nodiscard]] QString originalInstanceID() const { return m_original_instance_id; };
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setOverride(bool override, QString instance_id_to_override = {})
|
void setOverride(bool override) { m_override_existing = override; }
|
||||||
{
|
|
||||||
m_override_existing = override;
|
|
||||||
if (!instance_id_to_override.isEmpty())
|
|
||||||
m_original_instance_id = instance_id_to_override;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected: /* data */
|
protected: /* data */
|
||||||
SettingsObjectPtr m_globalSettings;
|
SettingsObjectPtr m_globalSettings;
|
||||||
@ -66,7 +54,4 @@ class InstanceTask : public Task, public InstanceName {
|
|||||||
QString m_stagingPath;
|
QString m_stagingPath;
|
||||||
|
|
||||||
bool m_override_existing = false;
|
bool m_override_existing = false;
|
||||||
bool m_confirm_update = true;
|
|
||||||
|
|
||||||
QString m_original_instance_id;
|
|
||||||
};
|
};
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
#include "JavaCommon.h"
|
#include "JavaCommon.h"
|
||||||
#include "java/JavaUtils.h"
|
#include "java/JavaUtils.h"
|
||||||
#include "ui/dialogs/CustomMessageBox.h"
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
|
#include <MMCStrings.h>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)
|
bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)
|
||||||
|
@ -1,28 +1,26 @@
|
|||||||
#include "StringUtils.h"
|
#include "MMCStrings.h"
|
||||||
|
|
||||||
/// If you're wondering where these came from exactly, then know you're not the only one =D
|
|
||||||
|
|
||||||
/// TAKEN FROM Qt, because it doesn't expose it intelligently
|
/// TAKEN FROM Qt, because it doesn't expose it intelligently
|
||||||
static inline QChar getNextChar(const QString& s, int location)
|
static inline QChar getNextChar(const QString &s, int location)
|
||||||
{
|
{
|
||||||
return (location < s.length()) ? s.at(location) : QChar();
|
return (location < s.length()) ? s.at(location) : QChar();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TAKEN FROM Qt, because it doesn't expose it intelligently
|
/// TAKEN FROM Qt, because it doesn't expose it intelligently
|
||||||
int StringUtils::naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs)
|
int Strings::naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs)
|
||||||
{
|
{
|
||||||
int l1 = 0, l2 = 0;
|
for (int l1 = 0, l2 = 0; l1 <= s1.count() && l2 <= s2.count(); ++l1, ++l2)
|
||||||
while (l1 <= s1.count() && l2 <= s2.count()) {
|
{
|
||||||
// skip spaces, tabs and 0's
|
// skip spaces, tabs and 0's
|
||||||
QChar c1 = getNextChar(s1, l1);
|
QChar c1 = getNextChar(s1, l1);
|
||||||
while (c1.isSpace())
|
while (c1.isSpace())
|
||||||
c1 = getNextChar(s1, ++l1);
|
c1 = getNextChar(s1, ++l1);
|
||||||
|
|
||||||
QChar c2 = getNextChar(s2, l2);
|
QChar c2 = getNextChar(s2, l2);
|
||||||
while (c2.isSpace())
|
while (c2.isSpace())
|
||||||
c2 = getNextChar(s2, ++l2);
|
c2 = getNextChar(s2, ++l2);
|
||||||
|
|
||||||
if (c1.isDigit() && c2.isDigit()) {
|
if (c1.isDigit() && c2.isDigit())
|
||||||
|
{
|
||||||
while (c1.digitValue() == 0)
|
while (c1.digitValue() == 0)
|
||||||
c1 = getNextChar(s1, ++l1);
|
c1 = getNextChar(s1, ++l1);
|
||||||
while (c2.digitValue() == 0)
|
while (c2.digitValue() == 0)
|
||||||
@ -32,8 +30,11 @@ int StringUtils::naturalCompare(const QString& s1, const QString& s2, Qt::CaseSe
|
|||||||
int lookAheadLocation2 = l2;
|
int lookAheadLocation2 = l2;
|
||||||
int currentReturnValue = 0;
|
int currentReturnValue = 0;
|
||||||
// find the last digit, setting currentReturnValue as we go if it isn't equal
|
// find the last digit, setting currentReturnValue as we go if it isn't equal
|
||||||
for (QChar lookAhead1 = c1, lookAhead2 = c2; (lookAheadLocation1 <= s1.length() && lookAheadLocation2 <= s2.length());
|
for (QChar lookAhead1 = c1, lookAhead2 = c2;
|
||||||
lookAhead1 = getNextChar(s1, ++lookAheadLocation1), lookAhead2 = getNextChar(s2, ++lookAheadLocation2)) {
|
(lookAheadLocation1 <= s1.length() && lookAheadLocation2 <= s2.length());
|
||||||
|
lookAhead1 = getNextChar(s1, ++lookAheadLocation1),
|
||||||
|
lookAhead2 = getNextChar(s2, ++lookAheadLocation2))
|
||||||
|
{
|
||||||
bool is1ADigit = !lookAhead1.isNull() && lookAhead1.isDigit();
|
bool is1ADigit = !lookAhead1.isNull() && lookAhead1.isDigit();
|
||||||
bool is2ADigit = !lookAhead2.isNull() && lookAhead2.isDigit();
|
bool is2ADigit = !lookAhead2.isNull() && lookAhead2.isDigit();
|
||||||
if (!is1ADigit && !is2ADigit)
|
if (!is1ADigit && !is2ADigit)
|
||||||
@ -42,10 +43,14 @@ int StringUtils::naturalCompare(const QString& s1, const QString& s2, Qt::CaseSe
|
|||||||
return -1;
|
return -1;
|
||||||
if (!is2ADigit)
|
if (!is2ADigit)
|
||||||
return 1;
|
return 1;
|
||||||
if (currentReturnValue == 0) {
|
if (currentReturnValue == 0)
|
||||||
if (lookAhead1 < lookAhead2) {
|
{
|
||||||
|
if (lookAhead1 < lookAhead2)
|
||||||
|
{
|
||||||
currentReturnValue = -1;
|
currentReturnValue = -1;
|
||||||
} else if (lookAhead1 > lookAhead2) {
|
}
|
||||||
|
else if (lookAhead1 > lookAhead2)
|
||||||
|
{
|
||||||
currentReturnValue = 1;
|
currentReturnValue = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,24 +58,19 @@ int StringUtils::naturalCompare(const QString& s1, const QString& s2, Qt::CaseSe
|
|||||||
if (currentReturnValue != 0)
|
if (currentReturnValue != 0)
|
||||||
return currentReturnValue;
|
return currentReturnValue;
|
||||||
}
|
}
|
||||||
|
if (cs == Qt::CaseInsensitive)
|
||||||
if (cs == Qt::CaseInsensitive) {
|
{
|
||||||
if (!c1.isLower())
|
if (!c1.isLower())
|
||||||
c1 = c1.toLower();
|
c1 = c1.toLower();
|
||||||
if (!c2.isLower())
|
if (!c2.isLower())
|
||||||
c2 = c2.toLower();
|
c2 = c2.toLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
int r = QString::localeAwareCompare(c1, c2);
|
int r = QString::localeAwareCompare(c1, c2);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
l1 += 1;
|
|
||||||
l2 += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The two strings are the same (02 == 2) so fall back to the normal sort
|
// The two strings are the same (02 == 2) so fall back to the normal sort
|
||||||
return QString::compare(s1, s2, cs);
|
return QString::compare(s1, s2, cs);
|
||||||
}
|
}
|
8
launcher/MMCStrings.h
Normal file
8
launcher/MMCStrings.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Strings
|
||||||
|
{
|
||||||
|
int naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs);
|
||||||
|
}
|
@ -28,11 +28,11 @@ QString Time::prettifyDuration(int64_t duration) {
|
|||||||
int days = (int) (duration / 24);
|
int days = (int) (duration / 24);
|
||||||
if((hours == 0)&&(days == 0))
|
if((hours == 0)&&(days == 0))
|
||||||
{
|
{
|
||||||
return QObject::tr("%1min %2s").arg(minutes).arg(seconds);
|
return QObject::tr("%1m %2s").arg(minutes).arg(seconds);
|
||||||
}
|
}
|
||||||
if (days == 0)
|
if (days == 0)
|
||||||
{
|
{
|
||||||
return QObject::tr("%1h %2min").arg(hours).arg(minutes);
|
return QObject::tr("%1h %2m").arg(hours).arg(minutes);
|
||||||
}
|
}
|
||||||
return QObject::tr("%1d %2h %3min").arg(days).arg(hours).arg(minutes);
|
return QObject::tr("%1d %2h %3m").arg(days).arg(hours).arg(minutes);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
#include "MMCZip.h"
|
#include "MMCZip.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
// ours
|
// ours
|
||||||
@ -229,27 +228,23 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ours
|
// ours
|
||||||
QString MMCZip::findFolderOfFileInZip(QuaZip* zip, const QString& what, const QStringList& ignore_paths, const QString& root)
|
QString MMCZip::findFolderOfFileInZip(QuaZip * zip, const QString & what, const QString &root)
|
||||||
{
|
{
|
||||||
QuaZipDir rootDir(zip, root);
|
QuaZipDir rootDir(zip, root);
|
||||||
for (auto&& fileName : rootDir.entryList(QDir::Files)) {
|
for(auto fileName: rootDir.entryList(QDir::Files))
|
||||||
if (fileName == what)
|
{
|
||||||
|
if(fileName == what)
|
||||||
return root;
|
return root;
|
||||||
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
}
|
||||||
|
for(auto fileName: rootDir.entryList(QDir::Dirs))
|
||||||
// Recurse the search to non-ignored subfolders
|
{
|
||||||
for (auto&& fileName : rootDir.entryList(QDir::Dirs)) {
|
QString result = findFolderOfFileInZip(zip, what, root + fileName);
|
||||||
if (ignore_paths.contains(fileName))
|
if(!result.isEmpty())
|
||||||
continue;
|
{
|
||||||
|
|
||||||
QString result = findFolderOfFileInZip(zip, what, ignore_paths, root + fileName);
|
|
||||||
if (!result.isEmpty())
|
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return QString();
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ours
|
// ours
|
||||||
|
@ -80,11 +80,9 @@ namespace MMCZip
|
|||||||
/**
|
/**
|
||||||
* Find a single file in archive by file name (not path)
|
* Find a single file in archive by file name (not path)
|
||||||
*
|
*
|
||||||
* \param ignore_paths paths to skip when recursing the search
|
|
||||||
*
|
|
||||||
* \return the path prefix where the file is
|
* \return the path prefix where the file is
|
||||||
*/
|
*/
|
||||||
QString findFolderOfFileInZip(QuaZip * zip, const QString & what, const QStringList& ignore_paths = {}, const QString &root = QString(""));
|
QString findFolderOfFileInZip(QuaZip * zip, const QString & what, const QString &root = QString(""));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a multiple files of the same name in archive by file name
|
* Find a multiple files of the same name in archive by file name
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QPixmapCache>
|
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
#define GET_TYPE() \
|
|
||||||
Qt::ConnectionType type; \
|
|
||||||
if (QThread::currentThread() != QCoreApplication::instance()->thread()) \
|
|
||||||
type = Qt::BlockingQueuedConnection; \
|
|
||||||
else \
|
|
||||||
type = Qt::DirectConnection;
|
|
||||||
|
|
||||||
#define DEFINE_FUNC_NO_PARAM(NAME, RET_TYPE) \
|
|
||||||
static RET_TYPE NAME() \
|
|
||||||
{ \
|
|
||||||
RET_TYPE ret; \
|
|
||||||
GET_TYPE() \
|
|
||||||
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret)); \
|
|
||||||
return ret; \
|
|
||||||
}
|
|
||||||
#define DEFINE_FUNC_ONE_PARAM(NAME, RET_TYPE, PARAM_1_TYPE) \
|
|
||||||
static RET_TYPE NAME(PARAM_1_TYPE p1) \
|
|
||||||
{ \
|
|
||||||
RET_TYPE ret; \
|
|
||||||
GET_TYPE() \
|
|
||||||
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret), Q_ARG(PARAM_1_TYPE, p1)); \
|
|
||||||
return ret; \
|
|
||||||
}
|
|
||||||
#define DEFINE_FUNC_TWO_PARAM(NAME, RET_TYPE, PARAM_1_TYPE, PARAM_2_TYPE) \
|
|
||||||
static RET_TYPE NAME(PARAM_1_TYPE p1, PARAM_2_TYPE p2) \
|
|
||||||
{ \
|
|
||||||
RET_TYPE ret; \
|
|
||||||
GET_TYPE() \
|
|
||||||
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret), Q_ARG(PARAM_1_TYPE, p1), \
|
|
||||||
Q_ARG(PARAM_2_TYPE, p2)); \
|
|
||||||
return ret; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A wrapper around QPixmapCache with thread affinity with the main thread.
|
|
||||||
*/
|
|
||||||
class PixmapCache final : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
PixmapCache(QObject* parent) : QObject(parent) {}
|
|
||||||
~PixmapCache() override = default;
|
|
||||||
|
|
||||||
static PixmapCache& instance() { return *s_instance; }
|
|
||||||
static void setInstance(PixmapCache* i) { s_instance = i; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
DEFINE_FUNC_NO_PARAM(cacheLimit, int)
|
|
||||||
DEFINE_FUNC_NO_PARAM(clear, bool)
|
|
||||||
DEFINE_FUNC_TWO_PARAM(find, bool, const QString&, QPixmap*)
|
|
||||||
DEFINE_FUNC_TWO_PARAM(find, bool, const QPixmapCache::Key&, QPixmap*)
|
|
||||||
DEFINE_FUNC_TWO_PARAM(insert, bool, const QString&, const QPixmap&)
|
|
||||||
DEFINE_FUNC_ONE_PARAM(insert, QPixmapCache::Key, const QPixmap&)
|
|
||||||
DEFINE_FUNC_ONE_PARAM(remove, bool, const QString&)
|
|
||||||
DEFINE_FUNC_ONE_PARAM(remove, bool, const QPixmapCache::Key&)
|
|
||||||
DEFINE_FUNC_TWO_PARAM(replace, bool, const QPixmapCache::Key&, const QPixmap&)
|
|
||||||
DEFINE_FUNC_ONE_PARAM(setCacheLimit, bool, int)
|
|
||||||
|
|
||||||
// NOTE: Every function returns something non-void to simplify the macros.
|
|
||||||
private slots:
|
|
||||||
int _cacheLimit() { return QPixmapCache::cacheLimit(); }
|
|
||||||
bool _clear()
|
|
||||||
{
|
|
||||||
QPixmapCache::clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool _find(const QString& key, QPixmap* pixmap) { return QPixmapCache::find(key, pixmap); }
|
|
||||||
bool _find(const QPixmapCache::Key& key, QPixmap* pixmap) { return QPixmapCache::find(key, pixmap); }
|
|
||||||
bool _insert(const QString& key, const QPixmap& pixmap) { return QPixmapCache::insert(key, pixmap); }
|
|
||||||
QPixmapCache::Key _insert(const QPixmap& pixmap) { return QPixmapCache::insert(pixmap); }
|
|
||||||
bool _remove(const QString& key)
|
|
||||||
{
|
|
||||||
QPixmapCache::remove(key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool _remove(const QPixmapCache::Key& key)
|
|
||||||
{
|
|
||||||
QPixmapCache::remove(key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool _replace(const QPixmapCache::Key& key, const QPixmap& pixmap) { return QPixmapCache::replace(key, pixmap); }
|
|
||||||
bool _setCacheLimit(int n)
|
|
||||||
{
|
|
||||||
QPixmapCache::setCacheLimit(n);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static PixmapCache* s_instance;
|
|
||||||
};
|
|
@ -1,90 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
/*
|
|
||||||
* PrismLauncher - Minecraft Launcher
|
|
||||||
* Copyright (C) 2022 Jan Drögehoff <sentrycraft123@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QString>
|
|
||||||
#include <QtGlobal>
|
|
||||||
|
|
||||||
#include "MangoHud.h"
|
|
||||||
#include "FileSystem.h"
|
|
||||||
#include "Json.h"
|
|
||||||
|
|
||||||
namespace MangoHud {
|
|
||||||
|
|
||||||
QString getLibraryString()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Check for vulkan layers in this order:
|
|
||||||
*
|
|
||||||
* $VK_LAYER_PATH
|
|
||||||
* $XDG_DATA_DIRS (/usr/local/share/:/usr/share/)
|
|
||||||
* $XDG_DATA_HOME (~/.local/share)
|
|
||||||
* /etc
|
|
||||||
* $XDG_CONFIG_DIRS (/etc/xdg)
|
|
||||||
* $XDG_CONFIG_HOME (~/.config)
|
|
||||||
*/
|
|
||||||
|
|
||||||
QStringList vkLayerList;
|
|
||||||
{
|
|
||||||
QString home = QDir::homePath();
|
|
||||||
|
|
||||||
QString vkLayerPath = qEnvironmentVariable("VK_LAYER_PATH");
|
|
||||||
if (!vkLayerPath.isEmpty()) {
|
|
||||||
vkLayerList << vkLayerPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList xdgDataDirs = qEnvironmentVariable("XDG_DATA_DIRS", "/usr/local/share/:/usr/share/").split(QLatin1String(":"));
|
|
||||||
for (QString dir : xdgDataDirs) {
|
|
||||||
vkLayerList << FS::PathCombine(dir, "vulkan", "implicit_layer.d");
|
|
||||||
}
|
|
||||||
|
|
||||||
QString xdgDataHome = qEnvironmentVariable("XDG_DATA_HOME");
|
|
||||||
if (xdgDataHome.isEmpty()) {
|
|
||||||
xdgDataHome = FS::PathCombine(home, ".local", "share");
|
|
||||||
}
|
|
||||||
vkLayerList << FS::PathCombine(xdgDataHome, "vulkan", "implicit_layer.d");
|
|
||||||
|
|
||||||
vkLayerList << "/etc";
|
|
||||||
|
|
||||||
QStringList xdgConfigDirs = qEnvironmentVariable("XDG_CONFIG_DIRS", "/etc/xdg").split(QLatin1String(":"));
|
|
||||||
for (QString dir : xdgConfigDirs) {
|
|
||||||
vkLayerList << FS::PathCombine(dir, "vulkan", "implicit_layer.d");
|
|
||||||
}
|
|
||||||
|
|
||||||
QString xdgConfigHome = qEnvironmentVariable("XDG_CONFIG_HOME");
|
|
||||||
if (xdgConfigHome.isEmpty()) {
|
|
||||||
xdgConfigHome = FS::PathCombine(home, ".config");
|
|
||||||
}
|
|
||||||
vkLayerList << FS::PathCombine(xdgConfigHome, "vulkan", "implicit_layer.d");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (QString vkLayer : vkLayerList) {
|
|
||||||
QString filePath = FS::PathCombine(vkLayer, "MangoHud.json");
|
|
||||||
if (!QFile::exists(filePath))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto conf = Json::requireDocument(filePath, vkLayer);
|
|
||||||
auto confObject = Json::requireObject(conf, vkLayer);
|
|
||||||
auto layer = Json::ensureObject(confObject, "layer");
|
|
||||||
return Json::ensureString(layer, "library_path");
|
|
||||||
}
|
|
||||||
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
} // namespace MangoHud
|
|
@ -1,27 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
/*
|
|
||||||
* PrismLauncher - Minecraft Launcher
|
|
||||||
* Copyright (C) 2022 Jan Drögehoff <sentrycraft123@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
namespace MangoHud {
|
|
||||||
|
|
||||||
QString getLibraryString();
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
namespace StringUtils {
|
|
||||||
|
|
||||||
#if defined Q_OS_WIN32
|
|
||||||
using string = std::wstring;
|
|
||||||
|
|
||||||
inline string toStdString(QString s)
|
|
||||||
{
|
|
||||||
return s.toStdWString();
|
|
||||||
}
|
|
||||||
inline QString fromStdString(string s)
|
|
||||||
{
|
|
||||||
return QString::fromStdWString(s);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
using string = std::string;
|
|
||||||
|
|
||||||
inline string toStdString(QString s)
|
|
||||||
{
|
|
||||||
return s.toStdString();
|
|
||||||
}
|
|
||||||
inline QString fromStdString(string s)
|
|
||||||
{
|
|
||||||
return QString::fromStdString(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs);
|
|
||||||
} // namespace StringUtils
|
|
@ -311,14 +311,14 @@ QModelIndex VersionProxyModel::index(int row, int column, const QModelIndex &par
|
|||||||
|
|
||||||
int VersionProxyModel::columnCount(const QModelIndex &parent) const
|
int VersionProxyModel::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : m_columns.size();
|
return m_columns.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int VersionProxyModel::rowCount(const QModelIndex &parent) const
|
int VersionProxyModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
if(sourceModel())
|
if(sourceModel())
|
||||||
{
|
{
|
||||||
return sourceModel()->rowCount(parent);
|
return sourceModel()->rowCount();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ Qt::DropActions IconList::supportedDropActions() const
|
|||||||
return Qt::CopyAction;
|
return Qt::CopyAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, [[maybe_unused]] const QModelIndex &parent)
|
bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||||
{
|
{
|
||||||
if (action == Qt::IgnoreAction)
|
if (action == Qt::IgnoreAction)
|
||||||
return true;
|
return true;
|
||||||
@ -302,7 +302,7 @@ QVariant IconList::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
int IconList::rowCount(const QModelIndex &parent) const
|
int IconList::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : icons.size();
|
return icons.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IconList::installIcons(const QStringList &iconFiles)
|
void IconList::installIcons(const QStringList &iconFiles)
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
#include "JavaInstall.h"
|
#include "JavaInstall.h"
|
||||||
|
#include <MMCStrings.h>
|
||||||
#include "StringUtils.h"
|
|
||||||
|
|
||||||
bool JavaInstall::operator<(const JavaInstall &rhs)
|
bool JavaInstall::operator<(const JavaInstall &rhs)
|
||||||
{
|
{
|
||||||
auto archCompare = StringUtils::naturalCompare(arch, rhs.arch, Qt::CaseInsensitive);
|
auto archCompare = Strings::naturalCompare(arch, rhs.arch, Qt::CaseInsensitive);
|
||||||
if(archCompare != 0)
|
if(archCompare != 0)
|
||||||
return archCompare < 0;
|
return archCompare < 0;
|
||||||
if(id < rhs.id)
|
if(id < rhs.id)
|
||||||
@ -15,7 +14,7 @@ bool JavaInstall::operator<(const JavaInstall &rhs)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return StringUtils::naturalCompare(path, rhs.path, Qt::CaseInsensitive) < 0;
|
return Strings::naturalCompare(path, rhs.path, Qt::CaseInsensitive) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JavaInstall::operator==(const JavaInstall &rhs)
|
bool JavaInstall::operator==(const JavaInstall &rhs)
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "java/JavaInstallList.h"
|
#include "java/JavaInstallList.h"
|
||||||
#include "java/JavaCheckerJob.h"
|
#include "java/JavaCheckerJob.h"
|
||||||
#include "java/JavaUtils.h"
|
#include "java/JavaUtils.h"
|
||||||
|
#include "MMCStrings.h"
|
||||||
#include "minecraft/VersionFilterData.h"
|
#include "minecraft/VersionFilterData.h"
|
||||||
|
|
||||||
JavaInstallList::JavaInstallList(QObject *parent) : BaseVersionList(parent)
|
JavaInstallList::JavaInstallList(QObject *parent) : BaseVersionList(parent)
|
||||||
@ -72,7 +73,7 @@ void JavaInstallList::load()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const BaseVersion::Ptr JavaInstallList::at(int i) const
|
const BaseVersionPtr JavaInstallList::at(int i) const
|
||||||
{
|
{
|
||||||
return m_vlist.at(i);
|
return m_vlist.at(i);
|
||||||
}
|
}
|
||||||
@ -121,7 +122,7 @@ BaseVersionList::RoleList JavaInstallList::providesRoles() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void JavaInstallList::updateListData(QList<BaseVersion::Ptr> versions)
|
void JavaInstallList::updateListData(QList<BaseVersionPtr> versions)
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
m_vlist = versions;
|
m_vlist = versions;
|
||||||
@ -136,7 +137,7 @@ void JavaInstallList::updateListData(QList<BaseVersion::Ptr> versions)
|
|||||||
m_loadTask.reset();
|
m_loadTask.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right)
|
bool sortJavas(BaseVersionPtr left, BaseVersionPtr right)
|
||||||
{
|
{
|
||||||
auto rleft = std::dynamic_pointer_cast<JavaInstall>(right);
|
auto rleft = std::dynamic_pointer_cast<JavaInstall>(right);
|
||||||
auto rright = std::dynamic_pointer_cast<JavaInstall>(left);
|
auto rright = std::dynamic_pointer_cast<JavaInstall>(left);
|
||||||
@ -209,11 +210,11 @@ void JavaListLoadTask::javaCheckerFinished()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<BaseVersion::Ptr> javas_bvp;
|
QList<BaseVersionPtr> javas_bvp;
|
||||||
for (auto java : candidates)
|
for (auto java : candidates)
|
||||||
{
|
{
|
||||||
//qDebug() << java->id << java->arch << " at " << java->path;
|
//qDebug() << java->id << java->arch << " at " << java->path;
|
||||||
BaseVersion::Ptr bp_java = std::dynamic_pointer_cast<BaseVersion>(java);
|
BaseVersionPtr bp_java = std::dynamic_pointer_cast<BaseVersion>(java);
|
||||||
|
|
||||||
if (bp_java)
|
if (bp_java)
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
Task::Ptr getLoadTask() override;
|
Task::Ptr getLoadTask() override;
|
||||||
bool isLoaded() override;
|
bool isLoaded() override;
|
||||||
const BaseVersion::Ptr at(int i) const override;
|
const BaseVersionPtr at(int i) const override;
|
||||||
int count() const override;
|
int count() const override;
|
||||||
void sortVersions() override;
|
void sortVersions() override;
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ public:
|
|||||||
RoleList providesRoles() const override;
|
RoleList providesRoles() const override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateListData(QList<BaseVersion::Ptr> versions) override;
|
void updateListData(QList<BaseVersionPtr> versions) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void load();
|
void load();
|
||||||
@ -59,7 +59,7 @@ protected:
|
|||||||
protected:
|
protected:
|
||||||
Status m_status = Status::NotDone;
|
Status m_status = Status::NotDone;
|
||||||
shared_qobject_ptr<JavaListLoadTask> m_loadTask;
|
shared_qobject_ptr<JavaListLoadTask> m_loadTask;
|
||||||
QList<BaseVersion::Ptr> m_vlist;
|
QList<BaseVersionPtr> m_vlist;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JavaListLoadTask : public Task
|
class JavaListLoadTask : public Task
|
||||||
|
@ -439,28 +439,19 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
javas.append(FS::PathCombine(prefix, "bin/java"));
|
javas.append(FS::PathCombine(prefix, "bin/java"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// java installed in a snap is installed in the standard directory, but underneath $SNAP
|
|
||||||
auto snap = qEnvironmentVariable("SNAP");
|
|
||||||
auto scanJavaDirs = [&](const QString & dirPath)
|
|
||||||
{
|
|
||||||
scanJavaDir(dirPath);
|
|
||||||
if (!snap.isNull()) {
|
|
||||||
scanJavaDir(snap + dirPath);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// oracle RPMs
|
// oracle RPMs
|
||||||
scanJavaDirs("/usr/java");
|
scanJavaDir("/usr/java");
|
||||||
// general locations used by distro packaging
|
// general locations used by distro packaging
|
||||||
scanJavaDirs("/usr/lib/jvm");
|
scanJavaDir("/usr/lib/jvm");
|
||||||
scanJavaDirs("/usr/lib64/jvm");
|
scanJavaDir("/usr/lib64/jvm");
|
||||||
scanJavaDirs("/usr/lib32/jvm");
|
scanJavaDir("/usr/lib32/jvm");
|
||||||
// javas stored in Prism Launcher's folder
|
// javas stored in Prism Launcher's folder
|
||||||
scanJavaDirs("java");
|
scanJavaDir("java");
|
||||||
// manually installed JDKs in /opt
|
// manually installed JDKs in /opt
|
||||||
scanJavaDirs("/opt/jdk");
|
scanJavaDir("/opt/jdk");
|
||||||
scanJavaDirs("/opt/jdks");
|
scanJavaDir("/opt/jdks");
|
||||||
// flatpak
|
// flatpak
|
||||||
scanJavaDirs("/app/jdk");
|
scanJavaDir("/app/jdk");
|
||||||
javas = addJavasFromEnv(javas);
|
javas = addJavasFromEnv(javas);
|
||||||
javas.removeDuplicates();
|
javas.removeDuplicates();
|
||||||
return javas;
|
return javas;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "JavaVersion.h"
|
#include "JavaVersion.h"
|
||||||
|
#include <MMCStrings.h>
|
||||||
#include "StringUtils.h"
|
|
||||||
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@ -99,12 +98,12 @@ bool JavaVersion::operator<(const JavaVersion &rhs)
|
|||||||
else if(thisPre && rhsPre)
|
else if(thisPre && rhsPre)
|
||||||
{
|
{
|
||||||
// both are prereleases - use natural compare...
|
// both are prereleases - use natural compare...
|
||||||
return StringUtils::naturalCompare(m_prerelease, rhs.m_prerelease, Qt::CaseSensitive) < 0;
|
return Strings::naturalCompare(m_prerelease, rhs.m_prerelease, Qt::CaseSensitive) < 0;
|
||||||
}
|
}
|
||||||
// neither is prerelease, so they are the same -> this cannot be less than rhs
|
// neither is prerelease, so they are the same -> this cannot be less than rhs
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else return StringUtils::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0;
|
else return Strings::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JavaVersion::operator==(const JavaVersion &rhs)
|
bool JavaVersion::operator==(const JavaVersion &rhs)
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include "launch/LaunchTask.h"
|
#include "launch/LaunchTask.h"
|
||||||
#include "MessageLevel.h"
|
#include "MessageLevel.h"
|
||||||
|
#include "MMCStrings.h"
|
||||||
#include "java/JavaChecker.h"
|
#include "java/JavaChecker.h"
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
@ -81,19 +81,14 @@ int main(int argc, char *argv[])
|
|||||||
Q_INIT_RESOURCE(pe_light);
|
Q_INIT_RESOURCE(pe_light);
|
||||||
Q_INIT_RESOURCE(pe_blue);
|
Q_INIT_RESOURCE(pe_blue);
|
||||||
Q_INIT_RESOURCE(pe_colored);
|
Q_INIT_RESOURCE(pe_colored);
|
||||||
Q_INIT_RESOURCE(breeze_dark);
|
|
||||||
Q_INIT_RESOURCE(breeze_light);
|
|
||||||
Q_INIT_RESOURCE(OSX);
|
Q_INIT_RESOURCE(OSX);
|
||||||
Q_INIT_RESOURCE(iOS);
|
Q_INIT_RESOURCE(iOS);
|
||||||
Q_INIT_RESOURCE(flat);
|
Q_INIT_RESOURCE(flat);
|
||||||
Q_INIT_RESOURCE(flat_white);
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
case Application::Failed:
|
case Application::Failed:
|
||||||
return 1;
|
return 1;
|
||||||
case Application::Succeeded:
|
case Application::Succeeded:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ Index::Index(QObject *parent)
|
|||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Index::Index(const QVector<VersionList::Ptr> &lists, QObject *parent)
|
Index::Index(const QVector<VersionListPtr> &lists, QObject *parent)
|
||||||
: QAbstractListModel(parent), m_lists(lists)
|
: QAbstractListModel(parent), m_lists(lists)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_lists.size(); ++i)
|
for (int i = 0; i < m_lists.size(); ++i)
|
||||||
@ -41,7 +41,7 @@ QVariant Index::data(const QModelIndex &index, int role) const
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionList::Ptr list = m_lists.at(index.row());
|
VersionListPtr list = m_lists.at(index.row());
|
||||||
switch (role)
|
switch (role)
|
||||||
{
|
{
|
||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
@ -58,11 +58,11 @@ QVariant Index::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
int Index::rowCount(const QModelIndex &parent) const
|
int Index::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : m_lists.size();
|
return m_lists.size();
|
||||||
}
|
}
|
||||||
int Index::columnCount(const QModelIndex &parent) const
|
int Index::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : 1;
|
return 1;
|
||||||
}
|
}
|
||||||
QVariant Index::headerData(int section, Qt::Orientation orientation, int role) const
|
QVariant Index::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
{
|
{
|
||||||
@ -81,9 +81,9 @@ bool Index::hasUid(const QString &uid) const
|
|||||||
return m_uids.contains(uid);
|
return m_uids.contains(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionList::Ptr Index::get(const QString &uid)
|
VersionListPtr Index::get(const QString &uid)
|
||||||
{
|
{
|
||||||
VersionList::Ptr out = m_uids.value(uid, nullptr);
|
VersionListPtr out = m_uids.value(uid, nullptr);
|
||||||
if(!out)
|
if(!out)
|
||||||
{
|
{
|
||||||
out = std::make_shared<VersionList>(uid);
|
out = std::make_shared<VersionList>(uid);
|
||||||
@ -92,7 +92,7 @@ VersionList::Ptr Index::get(const QString &uid)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Version::Ptr Index::get(const QString &uid, const QString &version)
|
VersionPtr Index::get(const QString &uid, const QString &version)
|
||||||
{
|
{
|
||||||
auto list = get(uid);
|
auto list = get(uid);
|
||||||
return list->getVersion(version);
|
return list->getVersion(version);
|
||||||
@ -105,7 +105,7 @@ void Index::parse(const QJsonObject& obj)
|
|||||||
|
|
||||||
void Index::merge(const std::shared_ptr<Index> &other)
|
void Index::merge(const std::shared_ptr<Index> &other)
|
||||||
{
|
{
|
||||||
const QVector<VersionList::Ptr> lists = std::dynamic_pointer_cast<Index>(other)->m_lists;
|
const QVector<VersionListPtr> lists = std::dynamic_pointer_cast<Index>(other)->m_lists;
|
||||||
// initial load, no need to merge
|
// initial load, no need to merge
|
||||||
if (m_lists.isEmpty())
|
if (m_lists.isEmpty())
|
||||||
{
|
{
|
||||||
@ -120,7 +120,7 @@ void Index::merge(const std::shared_ptr<Index> &other)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (const VersionList::Ptr &list : lists)
|
for (const VersionListPtr &list : lists)
|
||||||
{
|
{
|
||||||
if (m_uids.contains(list->uid()))
|
if (m_uids.contains(list->uid()))
|
||||||
{
|
{
|
||||||
@ -138,7 +138,7 @@ void Index::merge(const std::shared_ptr<Index> &other)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Index::connectVersionList(const int row, const VersionList::Ptr &list)
|
void Index::connectVersionList(const int row, const VersionListPtr &list)
|
||||||
{
|
{
|
||||||
connect(list.get(), &VersionList::nameChanged, this, [this, row]()
|
connect(list.get(), &VersionList::nameChanged, this, [this, row]()
|
||||||
{
|
{
|
||||||
|
@ -19,19 +19,20 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "BaseEntity.h"
|
#include "BaseEntity.h"
|
||||||
#include "meta/VersionList.h"
|
|
||||||
|
|
||||||
class Task;
|
class Task;
|
||||||
|
|
||||||
namespace Meta
|
namespace Meta
|
||||||
{
|
{
|
||||||
|
using VersionListPtr = std::shared_ptr<class VersionList>;
|
||||||
|
using VersionPtr = std::shared_ptr<class Version>;
|
||||||
|
|
||||||
class Index : public QAbstractListModel, public BaseEntity
|
class Index : public QAbstractListModel, public BaseEntity
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit Index(QObject *parent = nullptr);
|
explicit Index(QObject *parent = nullptr);
|
||||||
explicit Index(const QVector<VersionList::Ptr> &lists, QObject *parent = nullptr);
|
explicit Index(const QVector<VersionListPtr> &lists, QObject *parent = nullptr);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -48,21 +49,21 @@ public:
|
|||||||
QString localFilename() const override { return "index.json"; }
|
QString localFilename() const override { return "index.json"; }
|
||||||
|
|
||||||
// queries
|
// queries
|
||||||
VersionList::Ptr get(const QString &uid);
|
VersionListPtr get(const QString &uid);
|
||||||
Version::Ptr get(const QString &uid, const QString &version);
|
VersionPtr get(const QString &uid, const QString &version);
|
||||||
bool hasUid(const QString &uid) const;
|
bool hasUid(const QString &uid) const;
|
||||||
|
|
||||||
QVector<VersionList::Ptr> lists() const { return m_lists; }
|
QVector<VersionListPtr> lists() const { return m_lists; }
|
||||||
|
|
||||||
public: // for usage by parsers only
|
public: // for usage by parsers only
|
||||||
void merge(const std::shared_ptr<Index> &other);
|
void merge(const std::shared_ptr<Index> &other);
|
||||||
void parse(const QJsonObject &obj) override;
|
void parse(const QJsonObject &obj) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<VersionList::Ptr> m_lists;
|
QVector<VersionListPtr> m_lists;
|
||||||
QHash<QString, VersionList::Ptr> m_uids;
|
QHash<QString, VersionListPtr> m_uids;
|
||||||
|
|
||||||
void connectVersionList(const int row, const VersionList::Ptr &list);
|
void connectVersionList(const int row, const VersionListPtr &list);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,11 +37,11 @@ MetadataVersion currentFormatVersion()
|
|||||||
static std::shared_ptr<Index> parseIndexInternal(const QJsonObject &obj)
|
static std::shared_ptr<Index> parseIndexInternal(const QJsonObject &obj)
|
||||||
{
|
{
|
||||||
const QVector<QJsonObject> objects = requireIsArrayOf<QJsonObject>(obj, "packages");
|
const QVector<QJsonObject> objects = requireIsArrayOf<QJsonObject>(obj, "packages");
|
||||||
QVector<VersionList::Ptr> lists;
|
QVector<VersionListPtr> lists;
|
||||||
lists.reserve(objects.size());
|
lists.reserve(objects.size());
|
||||||
std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject &obj)
|
std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject &obj)
|
||||||
{
|
{
|
||||||
VersionList::Ptr list = std::make_shared<VersionList>(requireString(obj, "uid"));
|
VersionListPtr list = std::make_shared<VersionList>(requireString(obj, "uid"));
|
||||||
list->setName(ensureString(obj, "name", QString()));
|
list->setName(ensureString(obj, "name", QString()));
|
||||||
return list;
|
return list;
|
||||||
});
|
});
|
||||||
@ -49,9 +49,9 @@ static std::shared_ptr<Index> parseIndexInternal(const QJsonObject &obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
static Version::Ptr parseCommonVersion(const QString &uid, const QJsonObject &obj)
|
static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj)
|
||||||
{
|
{
|
||||||
Version::Ptr version = std::make_shared<Version>(uid, requireString(obj, "version"));
|
VersionPtr version = std::make_shared<Version>(uid, requireString(obj, "version"));
|
||||||
version->setTime(QDateTime::fromString(requireString(obj, "releaseTime"), Qt::ISODate).toMSecsSinceEpoch() / 1000);
|
version->setTime(QDateTime::fromString(requireString(obj, "releaseTime"), Qt::ISODate).toMSecsSinceEpoch() / 1000);
|
||||||
version->setType(ensureString(obj, "type", QString()));
|
version->setType(ensureString(obj, "type", QString()));
|
||||||
version->setRecommended(ensureBoolean(obj, QString("recommended"), false));
|
version->setRecommended(ensureBoolean(obj, QString("recommended"), false));
|
||||||
@ -63,9 +63,9 @@ static Version::Ptr parseCommonVersion(const QString &uid, const QJsonObject &ob
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Version::Ptr parseVersionInternal(const QJsonObject &obj)
|
static std::shared_ptr<Version> parseVersionInternal(const QJsonObject &obj)
|
||||||
{
|
{
|
||||||
Version::Ptr version = parseCommonVersion(requireString(obj, "uid"), obj);
|
VersionPtr version = parseCommonVersion(requireString(obj, "uid"), obj);
|
||||||
|
|
||||||
version->setData(OneSixVersionFormat::versionFileFromJson(QJsonDocument(obj),
|
version->setData(OneSixVersionFormat::versionFileFromJson(QJsonDocument(obj),
|
||||||
QString("%1/%2.json").arg(version->uid(), version->version()),
|
QString("%1/%2.json").arg(version->uid(), version->version()),
|
||||||
@ -74,12 +74,12 @@ static Version::Ptr parseVersionInternal(const QJsonObject &obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Version list / package
|
// Version list / package
|
||||||
static VersionList::Ptr parseVersionListInternal(const QJsonObject &obj)
|
static std::shared_ptr<VersionList> parseVersionListInternal(const QJsonObject &obj)
|
||||||
{
|
{
|
||||||
const QString uid = requireString(obj, "uid");
|
const QString uid = requireString(obj, "uid");
|
||||||
|
|
||||||
const QVector<QJsonObject> versionsRaw = requireIsArrayOf<QJsonObject>(obj, "versions");
|
const QVector<QJsonObject> versionsRaw = requireIsArrayOf<QJsonObject>(obj, "versions");
|
||||||
QVector<Version::Ptr> versions;
|
QVector<VersionPtr> versions;
|
||||||
versions.reserve(versionsRaw.size());
|
versions.reserve(versionsRaw.size());
|
||||||
std::transform(versionsRaw.begin(), versionsRaw.end(), std::back_inserter(versions), [uid](const QJsonObject &vObj)
|
std::transform(versionsRaw.begin(), versionsRaw.end(), std::back_inserter(versions), [uid](const QJsonObject &vObj)
|
||||||
{
|
{
|
||||||
@ -88,7 +88,7 @@ static VersionList::Ptr parseVersionListInternal(const QJsonObject &obj)
|
|||||||
return version;
|
return version;
|
||||||
});
|
});
|
||||||
|
|
||||||
VersionList::Ptr list = std::make_shared<VersionList>(uid);
|
VersionListPtr list = std::make_shared<VersionList>(uid);
|
||||||
list->setName(ensureString(obj, "name", QString()));
|
list->setName(ensureString(obj, "name", QString()));
|
||||||
list->setVersions(versions);
|
list->setVersions(versions);
|
||||||
return list;
|
return list;
|
||||||
|
@ -60,6 +60,11 @@ struct Require
|
|||||||
QString suggests;
|
QString suggests;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline Q_DECL_PURE_FUNCTION uint qHash(const Require &key, uint seed = 0) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
return qHash(key.uid, seed);
|
||||||
|
}
|
||||||
|
|
||||||
using RequireSet = std::set<Require>;
|
using RequireSet = std::set<Require>;
|
||||||
|
|
||||||
void parseIndex(const QJsonObject &obj, Index *ptr);
|
void parseIndex(const QJsonObject &obj, Index *ptr);
|
||||||
|
@ -54,7 +54,7 @@ void Meta::Version::parse(const QJsonObject& obj)
|
|||||||
parseVersion(obj, this);
|
parseVersion(obj, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Meta::Version::mergeFromList(const Meta::Version::Ptr& other)
|
void Meta::Version::mergeFromList(const Meta::VersionPtr& other)
|
||||||
{
|
{
|
||||||
if(other->m_providesRecommendations)
|
if(other->m_providesRecommendations)
|
||||||
{
|
{
|
||||||
@ -85,7 +85,7 @@ void Meta::Version::mergeFromList(const Meta::Version::Ptr& other)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Meta::Version::merge(const Version::Ptr &other)
|
void Meta::Version::merge(const VersionPtr &other)
|
||||||
{
|
{
|
||||||
mergeFromList(other);
|
mergeFromList(other);
|
||||||
if(other->m_data)
|
if(other->m_data)
|
||||||
|
@ -30,14 +30,13 @@
|
|||||||
|
|
||||||
namespace Meta
|
namespace Meta
|
||||||
{
|
{
|
||||||
|
using VersionPtr = std::shared_ptr<class Version>;
|
||||||
|
|
||||||
class Version : public QObject, public BaseVersion, public BaseEntity
|
class Version : public QObject, public BaseVersion, public BaseEntity
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public: /* con/des */
|
||||||
using Ptr = std::shared_ptr<Version>;
|
|
||||||
|
|
||||||
explicit Version(const QString &uid, const QString &version);
|
explicit Version(const QString &uid, const QString &version);
|
||||||
virtual ~Version();
|
virtual ~Version();
|
||||||
|
|
||||||
@ -79,8 +78,8 @@ public:
|
|||||||
return m_data != nullptr;
|
return m_data != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void merge(const Version::Ptr &other);
|
void merge(const VersionPtr &other);
|
||||||
void mergeFromList(const Version::Ptr &other);
|
void mergeFromList(const VersionPtr &other);
|
||||||
void parse(const QJsonObject &obj) override;
|
void parse(const QJsonObject &obj) override;
|
||||||
|
|
||||||
QString localFilename() const override;
|
QString localFilename() const override;
|
||||||
@ -114,4 +113,4 @@ private:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Meta::Version::Ptr)
|
Q_DECLARE_METATYPE(Meta::VersionPtr)
|
||||||
|
@ -40,7 +40,7 @@ bool VersionList::isLoaded()
|
|||||||
return BaseEntity::isLoaded();
|
return BaseEntity::isLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
const BaseVersion::Ptr VersionList::at(int i) const
|
const BaseVersionPtr VersionList::at(int i) const
|
||||||
{
|
{
|
||||||
return m_versions.at(i);
|
return m_versions.at(i);
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ int VersionList::count() const
|
|||||||
void VersionList::sortVersions()
|
void VersionList::sortVersions()
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
std::sort(m_versions.begin(), m_versions.end(), [](const Version::Ptr &a, const Version::Ptr &b)
|
std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b)
|
||||||
{
|
{
|
||||||
return *a.get() < *b.get();
|
return *a.get() < *b.get();
|
||||||
});
|
});
|
||||||
@ -66,7 +66,7 @@ QVariant VersionList::data(const QModelIndex &index, int role) const
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
Version::Ptr version = m_versions.at(index.row());
|
VersionPtr version = m_versions.at(index.row());
|
||||||
|
|
||||||
switch (role)
|
switch (role)
|
||||||
{
|
{
|
||||||
@ -129,9 +129,9 @@ QString VersionList::humanReadable() const
|
|||||||
return m_name.isEmpty() ? m_uid : m_name;
|
return m_name.isEmpty() ? m_uid : m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Version::Ptr VersionList::getVersion(const QString &version)
|
VersionPtr VersionList::getVersion(const QString &version)
|
||||||
{
|
{
|
||||||
Version::Ptr out = m_lookup.value(version, nullptr);
|
VersionPtr out = m_lookup.value(version, nullptr);
|
||||||
if(!out)
|
if(!out)
|
||||||
{
|
{
|
||||||
out = std::make_shared<Version>(m_uid, version);
|
out = std::make_shared<Version>(m_uid, version);
|
||||||
@ -143,7 +143,7 @@ Version::Ptr VersionList::getVersion(const QString &version)
|
|||||||
bool VersionList::hasVersion(QString version) const
|
bool VersionList::hasVersion(QString version) const
|
||||||
{
|
{
|
||||||
auto ver = std::find_if(m_versions.constBegin(), m_versions.constEnd(),
|
auto ver = std::find_if(m_versions.constBegin(), m_versions.constEnd(),
|
||||||
[&](Meta::Version::Ptr const& a){ return a->version() == version; });
|
[&](Meta::VersionPtr const& a){ return a->version() == version; });
|
||||||
return (ver != m_versions.constEnd());
|
return (ver != m_versions.constEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,11 +153,11 @@ void VersionList::setName(const QString &name)
|
|||||||
emit nameChanged(name);
|
emit nameChanged(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionList::setVersions(const QVector<Version::Ptr> &versions)
|
void VersionList::setVersions(const QVector<VersionPtr> &versions)
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
m_versions = versions;
|
m_versions = versions;
|
||||||
std::sort(m_versions.begin(), m_versions.end(), [](const Version::Ptr &a, const Version::Ptr &b)
|
std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b)
|
||||||
{
|
{
|
||||||
return a->rawTime() > b->rawTime();
|
return a->rawTime() > b->rawTime();
|
||||||
});
|
});
|
||||||
@ -168,7 +168,7 @@ void VersionList::setVersions(const QVector<Version::Ptr> &versions)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this is dumb, we have 'recommended' as part of the metadata already...
|
// FIXME: this is dumb, we have 'recommended' as part of the metadata already...
|
||||||
auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const Version::Ptr &ptr) { return ptr->type() == "release"; });
|
auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const VersionPtr &ptr) { return ptr->type() == "release"; });
|
||||||
m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt;
|
m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt;
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ void VersionList::parse(const QJsonObject& obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this is dumb, we have 'recommended' as part of the metadata already...
|
// FIXME: this is dumb, we have 'recommended' as part of the metadata already...
|
||||||
static const Meta::Version::Ptr &getBetterVersion(const Meta::Version::Ptr &a, const Meta::Version::Ptr &b)
|
static const Meta::VersionPtr &getBetterVersion(const Meta::VersionPtr &a, const Meta::VersionPtr &b)
|
||||||
{
|
{
|
||||||
if(!a)
|
if(!a)
|
||||||
return b;
|
return b;
|
||||||
@ -194,7 +194,7 @@ static const Meta::Version::Ptr &getBetterVersion(const Meta::Version::Ptr &a, c
|
|||||||
return (a->type() == "release" ? a : b);
|
return (a->type() == "release" ? a : b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionList::mergeFromIndex(const VersionList::Ptr &other)
|
void VersionList::mergeFromIndex(const VersionListPtr &other)
|
||||||
{
|
{
|
||||||
if (m_name != other->m_name)
|
if (m_name != other->m_name)
|
||||||
{
|
{
|
||||||
@ -202,7 +202,7 @@ void VersionList::mergeFromIndex(const VersionList::Ptr &other)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionList::merge(const VersionList::Ptr &other)
|
void VersionList::merge(const VersionListPtr &other)
|
||||||
{
|
{
|
||||||
if (m_name != other->m_name)
|
if (m_name != other->m_name)
|
||||||
{
|
{
|
||||||
@ -216,7 +216,7 @@ void VersionList::merge(const VersionList::Ptr &other)
|
|||||||
{
|
{
|
||||||
qWarning() << "Empty list loaded ...";
|
qWarning() << "Empty list loaded ...";
|
||||||
}
|
}
|
||||||
for (const Version::Ptr &version : other->m_versions)
|
for (const VersionPtr &version : other->m_versions)
|
||||||
{
|
{
|
||||||
// we already have the version. merge the contents
|
// we already have the version. merge the contents
|
||||||
if (m_lookup.contains(version->version()))
|
if (m_lookup.contains(version->version()))
|
||||||
@ -235,7 +235,7 @@ void VersionList::merge(const VersionList::Ptr &other)
|
|||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionList::setupAddedVersion(const int row, const Version::Ptr &version)
|
void VersionList::setupAddedVersion(const int row, const VersionPtr &version)
|
||||||
{
|
{
|
||||||
// FIXME: do not disconnect from everythin, disconnect only the lambdas here
|
// FIXME: do not disconnect from everythin, disconnect only the lambdas here
|
||||||
version->disconnect();
|
version->disconnect();
|
||||||
@ -244,7 +244,7 @@ void VersionList::setupAddedVersion(const int row, const Version::Ptr &version)
|
|||||||
connect(version.get(), &Version::typeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << TypeRole); });
|
connect(version.get(), &Version::typeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << TypeRole); });
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseVersion::Ptr VersionList::getRecommended() const
|
BaseVersionPtr VersionList::getRecommended() const
|
||||||
{
|
{
|
||||||
return m_recommended;
|
return m_recommended;
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "meta/Version.h"
|
|
||||||
|
|
||||||
namespace Meta
|
namespace Meta
|
||||||
{
|
{
|
||||||
|
using VersionPtr = std::shared_ptr<class Version>;
|
||||||
|
using VersionListPtr = std::shared_ptr<class VersionList>;
|
||||||
|
|
||||||
class VersionList : public BaseVersionList, public BaseEntity
|
class VersionList : public BaseVersionList, public BaseEntity
|
||||||
{
|
{
|
||||||
@ -33,8 +33,6 @@ class VersionList : public BaseVersionList, public BaseEntity
|
|||||||
public:
|
public:
|
||||||
explicit VersionList(const QString &uid, QObject *parent = nullptr);
|
explicit VersionList(const QString &uid, QObject *parent = nullptr);
|
||||||
|
|
||||||
using Ptr = std::shared_ptr<VersionList>;
|
|
||||||
|
|
||||||
enum Roles
|
enum Roles
|
||||||
{
|
{
|
||||||
UidRole = Qt::UserRole + 100,
|
UidRole = Qt::UserRole + 100,
|
||||||
@ -45,11 +43,11 @@ public:
|
|||||||
|
|
||||||
Task::Ptr getLoadTask() override;
|
Task::Ptr getLoadTask() override;
|
||||||
bool isLoaded() override;
|
bool isLoaded() override;
|
||||||
const BaseVersion::Ptr at(int i) const override;
|
const BaseVersionPtr at(int i) const override;
|
||||||
int count() const override;
|
int count() const override;
|
||||||
void sortVersions() override;
|
void sortVersions() override;
|
||||||
|
|
||||||
BaseVersion::Ptr getRecommended() const override;
|
BaseVersionPtr getRecommended() const override;
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role) const override;
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
RoleList providesRoles() const override;
|
RoleList providesRoles() const override;
|
||||||
@ -67,38 +65,38 @@ public:
|
|||||||
}
|
}
|
||||||
QString humanReadable() const;
|
QString humanReadable() const;
|
||||||
|
|
||||||
Version::Ptr getVersion(const QString &version);
|
VersionPtr getVersion(const QString &version);
|
||||||
bool hasVersion(QString version) const;
|
bool hasVersion(QString version) const;
|
||||||
|
|
||||||
QVector<Version::Ptr> versions() const
|
QVector<VersionPtr> versions() const
|
||||||
{
|
{
|
||||||
return m_versions;
|
return m_versions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public: // for usage only by parsers
|
public: // for usage only by parsers
|
||||||
void setName(const QString &name);
|
void setName(const QString &name);
|
||||||
void setVersions(const QVector<Version::Ptr> &versions);
|
void setVersions(const QVector<VersionPtr> &versions);
|
||||||
void merge(const VersionList::Ptr &other);
|
void merge(const VersionListPtr &other);
|
||||||
void mergeFromIndex(const VersionList::Ptr &other);
|
void mergeFromIndex(const VersionListPtr &other);
|
||||||
void parse(const QJsonObject &obj) override;
|
void parse(const QJsonObject &obj) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void nameChanged(const QString &name);
|
void nameChanged(const QString &name);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void updateListData(QList<BaseVersion::Ptr>) override
|
void updateListData(QList<BaseVersionPtr>) override
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<Version::Ptr> m_versions;
|
QVector<VersionPtr> m_versions;
|
||||||
QHash<QString, Version::Ptr> m_lookup;
|
QHash<QString, VersionPtr> m_lookup;
|
||||||
QString m_uid;
|
QString m_uid;
|
||||||
QString m_name;
|
QString m_name;
|
||||||
|
|
||||||
Version::Ptr m_recommended;
|
VersionPtr m_recommended;
|
||||||
|
|
||||||
void setupAddedVersion(const int row, const Version::Ptr &version);
|
void setupAddedVersion(const int row, const VersionPtr &version);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Q_DECLARE_METATYPE(Meta::VersionList::Ptr)
|
Q_DECLARE_METATYPE(Meta::VersionListPtr)
|
||||||
|
@ -10,7 +10,7 @@ typedef std::shared_ptr<Agent> AgentPtr;
|
|||||||
|
|
||||||
class Agent {
|
class Agent {
|
||||||
public:
|
public:
|
||||||
Agent(LibraryPtr library, const QString &argument)
|
Agent(LibraryPtr library, QString &argument)
|
||||||
{
|
{
|
||||||
m_library = library;
|
m_library = library;
|
||||||
m_argument = argument;
|
m_argument = argument;
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* PolyMC - Minecraft Launcher
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
* Copyright (C) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
* Copyright (C) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||||
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
|
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -44,6 +43,7 @@
|
|||||||
#include "settings/SettingsObject.h"
|
#include "settings/SettingsObject.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
|
#include "MMCStrings.h"
|
||||||
#include "pathmatcher/RegexpMatcher.h"
|
#include "pathmatcher/RegexpMatcher.h"
|
||||||
#include "pathmatcher/MultiMatcher.h"
|
#include "pathmatcher/MultiMatcher.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
@ -88,10 +88,6 @@
|
|||||||
#include "minecraft/gameoptions/GameOptions.h"
|
#include "minecraft/gameoptions/GameOptions.h"
|
||||||
#include "minecraft/update/FoldersTask.h"
|
#include "minecraft/update/FoldersTask.h"
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
#include "MangoHud.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IBUS "@im=ibus"
|
#define IBUS "@im=ibus"
|
||||||
|
|
||||||
// all of this because keeping things compatible with deprecated old settings
|
// all of this because keeping things compatible with deprecated old settings
|
||||||
@ -441,17 +437,6 @@ QStringList MinecraftInstance::javaArguments()
|
|||||||
return args;
|
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"))
|
|
||||||
return "legacy";
|
|
||||||
|
|
||||||
return "standard";
|
|
||||||
}
|
|
||||||
|
|
||||||
QMap<QString, QString> MinecraftInstance::getVariables()
|
QMap<QString, QString> MinecraftInstance::getVariables()
|
||||||
{
|
{
|
||||||
QMap<QString, QString> out;
|
QMap<QString, QString> out;
|
||||||
@ -486,22 +471,9 @@ QProcessEnvironment MinecraftInstance::createLaunchEnvironment()
|
|||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
if (settings()->get("EnableMangoHud").toBool() && APPLICATION->capabilities() & Application::SupportsMangoHud)
|
if (settings()->get("EnableMangoHud").toBool() && APPLICATION->capabilities() & Application::SupportsMangoHud)
|
||||||
{
|
{
|
||||||
|
auto preload = env.value("LD_PRELOAD", "") + ":libMangoHud_dlsym.so:libMangoHud.so";
|
||||||
|
|
||||||
auto preloadList = env.value("LD_PRELOAD").split(QLatin1String(":"));
|
env.insert("LD_PRELOAD", preload);
|
||||||
auto libPaths = env.value("LD_LIBRARY_PATH").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();
|
|
||||||
libPaths << mangoHudLib.absolutePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
env.insert("LD_PRELOAD", preloadList.join(QLatin1String(":")));
|
|
||||||
env.insert("LD_LIBRARY_PATH", libPaths.join(QLatin1String(":")));
|
|
||||||
env.insert("MANGOHUD", "1");
|
env.insert("MANGOHUD", "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,13 +628,26 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS
|
|||||||
launchScript += "sessionId " + session->session + "\n";
|
launchScript += "sessionId " + session->session + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// libraries and class path.
|
||||||
|
{
|
||||||
|
QStringList jars, nativeJars;
|
||||||
|
profile->getLibraryFiles(runtimeContext(), jars, nativeJars, getLocalLibraryPath(), binRoot());
|
||||||
|
for(auto file: jars)
|
||||||
|
{
|
||||||
|
launchScript += "cp " + file + "\n";
|
||||||
|
}
|
||||||
|
for(auto file: nativeJars)
|
||||||
|
{
|
||||||
|
launchScript += "ext " + file + "\n";
|
||||||
|
}
|
||||||
|
launchScript += "natives " + getNativePath() + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
for (auto trait : profile->getTraits())
|
for (auto trait : profile->getTraits())
|
||||||
{
|
{
|
||||||
launchScript += "traits " + trait + "\n";
|
launchScript += "traits " + trait + "\n";
|
||||||
}
|
}
|
||||||
|
launchScript += "launcher onesix\n";
|
||||||
launchScript += "launcher " + getLauncher() + "\n";
|
|
||||||
|
|
||||||
// qDebug() << "Generated launch script:" << launchScript;
|
// qDebug() << "Generated launch script:" << launchScript;
|
||||||
return launchScript;
|
return launchScript;
|
||||||
}
|
}
|
||||||
@ -798,8 +783,6 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr
|
|||||||
out << "Window size: " + QString::number(width) + " x " + QString::number(height);
|
out << "Window size: " + QString::number(width) + " x " + QString::number(height);
|
||||||
}
|
}
|
||||||
out << "";
|
out << "";
|
||||||
out << "Launcher: " + getLauncher();
|
|
||||||
out << "";
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1127,6 +1110,8 @@ std::shared_ptr<ResourcePackFolderModel> MinecraftInstance::resourcePackList() c
|
|||||||
if (!m_resource_pack_list)
|
if (!m_resource_pack_list)
|
||||||
{
|
{
|
||||||
m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir()));
|
m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir()));
|
||||||
|
m_resource_pack_list->enableInteraction(!isRunning());
|
||||||
|
connect(this, &BaseInstance::runningStatusChanged, m_resource_pack_list.get(), &ResourcePackFolderModel::disableInteraction);
|
||||||
}
|
}
|
||||||
return m_resource_pack_list;
|
return m_resource_pack_list;
|
||||||
}
|
}
|
||||||
@ -1136,6 +1121,8 @@ std::shared_ptr<TexturePackFolderModel> MinecraftInstance::texturePackList() con
|
|||||||
if (!m_texture_pack_list)
|
if (!m_texture_pack_list)
|
||||||
{
|
{
|
||||||
m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir()));
|
m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir()));
|
||||||
|
m_texture_pack_list->disableInteraction(isRunning());
|
||||||
|
connect(this, &BaseInstance::runningStatusChanged, m_texture_pack_list.get(), &ModFolderModel::disableInteraction);
|
||||||
}
|
}
|
||||||
return m_texture_pack_list;
|
return m_texture_pack_list;
|
||||||
}
|
}
|
||||||
@ -1145,6 +1132,8 @@ std::shared_ptr<ShaderPackFolderModel> MinecraftInstance::shaderPackList() const
|
|||||||
if (!m_shader_pack_list)
|
if (!m_shader_pack_list)
|
||||||
{
|
{
|
||||||
m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir()));
|
m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir()));
|
||||||
|
m_shader_pack_list->disableInteraction(isRunning());
|
||||||
|
connect(this, &BaseInstance::runningStatusChanged, m_shader_pack_list.get(), &ModFolderModel::disableInteraction);
|
||||||
}
|
}
|
||||||
return m_shader_pack_list;
|
return m_shader_pack_list;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* PolyMC - Minecraft Launcher
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
|
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -131,7 +130,6 @@ public:
|
|||||||
QString createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin);
|
QString createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin);
|
||||||
/// get arguments passed to java
|
/// get arguments passed to java
|
||||||
QStringList javaArguments();
|
QStringList javaArguments();
|
||||||
QString getLauncher();
|
|
||||||
|
|
||||||
/// get variables for launch command variable substitution/environment
|
/// get variables for launch command variable substitution/environment
|
||||||
QMap<QString, QString> getVariables() override;
|
QMap<QString, QString> getVariables() override;
|
||||||
|
@ -135,7 +135,7 @@ QJsonObject libDownloadInfoToJson(MojangLibraryDownloadInfo::Ptr libinfo)
|
|||||||
{
|
{
|
||||||
out.insert("artifact", downloadInfoToJson(libinfo->artifact));
|
out.insert("artifact", downloadInfoToJson(libinfo->artifact));
|
||||||
}
|
}
|
||||||
if(!libinfo->classifiers.isEmpty())
|
if(libinfo->classifiers.size())
|
||||||
{
|
{
|
||||||
QJsonObject classifiersOut;
|
QJsonObject classifiersOut;
|
||||||
for(auto iter = libinfo->classifiers.begin(); iter != libinfo->classifiers.end(); iter++)
|
for(auto iter = libinfo->classifiers.begin(); iter != libinfo->classifiers.end(); iter++)
|
||||||
@ -297,7 +297,7 @@ void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObj
|
|||||||
{
|
{
|
||||||
out.insert("assetIndex", assetIndexToJson(in->mojangAssetIndex));
|
out.insert("assetIndex", assetIndexToJson(in->mojangAssetIndex));
|
||||||
}
|
}
|
||||||
if(!in->mojangDownloads.isEmpty())
|
if(in->mojangDownloads.size())
|
||||||
{
|
{
|
||||||
QJsonObject downloadsOut;
|
QJsonObject downloadsOut;
|
||||||
for(auto iter = in->mojangDownloads.begin(); iter != in->mojangDownloads.end(); iter++)
|
for(auto iter = in->mojangDownloads.begin(); iter != in->mojangDownloads.end(); iter++)
|
||||||
@ -306,15 +306,6 @@ void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObj
|
|||||||
}
|
}
|
||||||
out.insert("downloads", downloadsOut);
|
out.insert("downloads", downloadsOut);
|
||||||
}
|
}
|
||||||
if(!in->compatibleJavaMajors.isEmpty())
|
|
||||||
{
|
|
||||||
QJsonArray compatibleJavaMajorsOut;
|
|
||||||
for(auto compatibleJavaMajor : in->compatibleJavaMajors)
|
|
||||||
{
|
|
||||||
compatibleJavaMajorsOut.append(compatibleJavaMajor);
|
|
||||||
}
|
|
||||||
out.insert("compatibleJavaMajors", compatibleJavaMajorsOut);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonDocument MojangVersionFormat::versionFileToJson(const VersionFilePtr &patch)
|
QJsonDocument MojangVersionFormat::versionFileToJson(const VersionFilePtr &patch)
|
||||||
@ -405,7 +396,7 @@ QJsonObject MojangVersionFormat::libraryToJson(Library *library)
|
|||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
libRoot.insert("natives", nativeList);
|
libRoot.insert("natives", nativeList);
|
||||||
if (!library->m_extractExcludes.isEmpty())
|
if (library->m_extractExcludes.size())
|
||||||
{
|
{
|
||||||
QJsonArray excludes;
|
QJsonArray excludes;
|
||||||
QJsonObject extract;
|
QJsonObject extract;
|
||||||
@ -417,7 +408,7 @@ QJsonObject MojangVersionFormat::libraryToJson(Library *library)
|
|||||||
libRoot.insert("extract", extract);
|
libRoot.insert("extract", extract);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!library->m_rules.isEmpty())
|
if (library->m_rules.size())
|
||||||
{
|
{
|
||||||
QJsonArray allRules;
|
QJsonArray allRules;
|
||||||
for (auto &rule : library->m_rules)
|
for (auto &rule : library->m_rules)
|
||||||
|
@ -39,8 +39,6 @@
|
|||||||
#include "minecraft/ParseUtils.h"
|
#include "minecraft/ParseUtils.h"
|
||||||
#include <minecraft/MojangVersionFormat.h>
|
#include <minecraft/MojangVersionFormat.h>
|
||||||
|
|
||||||
#include <QRegularExpression>
|
|
||||||
|
|
||||||
using namespace Json;
|
using namespace Json;
|
||||||
|
|
||||||
static void readString(const QJsonObject &root, const QString &key, QString &variable)
|
static void readString(const QJsonObject &root, const QString &key, QString &variable)
|
||||||
@ -65,13 +63,13 @@ LibraryPtr OneSixVersionFormat::libraryFromJson(ProblemContainer & problems, con
|
|||||||
QJsonObject OneSixVersionFormat::libraryToJson(Library *library)
|
QJsonObject OneSixVersionFormat::libraryToJson(Library *library)
|
||||||
{
|
{
|
||||||
QJsonObject libRoot = MojangVersionFormat::libraryToJson(library);
|
QJsonObject libRoot = MojangVersionFormat::libraryToJson(library);
|
||||||
if (!library->m_absoluteURL.isEmpty())
|
if (library->m_absoluteURL.size())
|
||||||
libRoot.insert("MMC-absoluteUrl", library->m_absoluteURL);
|
libRoot.insert("MMC-absoluteUrl", library->m_absoluteURL);
|
||||||
if (!library->m_hint.isEmpty())
|
if (library->m_hint.size())
|
||||||
libRoot.insert("MMC-hint", library->m_hint);
|
libRoot.insert("MMC-hint", library->m_hint);
|
||||||
if (!library->m_filename.isEmpty())
|
if (library->m_filename.size())
|
||||||
libRoot.insert("MMC-filename", library->m_filename);
|
libRoot.insert("MMC-filename", library->m_filename);
|
||||||
if (!library->m_displayname.isEmpty())
|
if (library->m_displayname.size())
|
||||||
libRoot.insert("MMC-displayname", library->m_displayname);
|
libRoot.insert("MMC-displayname", library->m_displayname);
|
||||||
return libRoot;
|
return libRoot;
|
||||||
}
|
}
|
||||||
@ -123,15 +121,6 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
|||||||
out->uid = root.value("fileId").toString();
|
out->uid = root.value("fileId").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QRegularExpression valid_uid_regex{ QRegularExpression::anchoredPattern(QStringLiteral(R"([a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]+)*)")) };
|
|
||||||
if (!valid_uid_regex.match(out->uid).hasMatch()) {
|
|
||||||
qCritical() << "The component's 'uid' contains illegal characters! UID:" << out->uid;
|
|
||||||
out->addProblem(
|
|
||||||
ProblemSeverity::Error,
|
|
||||||
QObject::tr("The component's 'uid' contains illegal characters! This can cause security issues.")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
out->version = root.value("version").toString();
|
out->version = root.value("version").toString();
|
||||||
|
|
||||||
MojangVersionFormat::readVersionProperties(root, out.get());
|
MojangVersionFormat::readVersionProperties(root, out.get());
|
||||||
@ -236,10 +225,11 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
|||||||
{
|
{
|
||||||
QJsonObject agentObj = requireObject(agentVal);
|
QJsonObject agentObj = requireObject(agentVal);
|
||||||
auto lib = libraryFromJson(*out, agentObj, filename);
|
auto lib = libraryFromJson(*out, agentObj, filename);
|
||||||
|
|
||||||
QString arg = "";
|
QString arg = "";
|
||||||
readString(agentObj, "argument", arg);
|
if (agentObj.contains("argument"))
|
||||||
|
{
|
||||||
|
readString(agentObj, "argument", arg);
|
||||||
|
}
|
||||||
AgentPtr agent(new Agent(lib, arg));
|
AgentPtr agent(new Agent(lib, arg));
|
||||||
out->agents.append(agent);
|
out->agents.append(agent);
|
||||||
}
|
}
|
||||||
@ -342,20 +332,6 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch
|
|||||||
writeString(root, "appletClass", patch->appletClass);
|
writeString(root, "appletClass", patch->appletClass);
|
||||||
writeStringList(root, "+tweakers", patch->addTweakers);
|
writeStringList(root, "+tweakers", patch->addTweakers);
|
||||||
writeStringList(root, "+traits", patch->traits.values());
|
writeStringList(root, "+traits", patch->traits.values());
|
||||||
writeStringList(root, "+jvmArgs", patch->addnJvmArguments);
|
|
||||||
if (!patch->agents.isEmpty())
|
|
||||||
{
|
|
||||||
QJsonArray array;
|
|
||||||
for (auto value: patch->agents)
|
|
||||||
{
|
|
||||||
QJsonObject agentOut = OneSixVersionFormat::libraryToJson(value->library().get());
|
|
||||||
if (!value->argument().isEmpty())
|
|
||||||
agentOut.insert("argument", value->argument());
|
|
||||||
|
|
||||||
array.append(agentOut);
|
|
||||||
}
|
|
||||||
root.insert("+agents", array);
|
|
||||||
}
|
|
||||||
if (!patch->libraries.isEmpty())
|
if (!patch->libraries.isEmpty())
|
||||||
{
|
{
|
||||||
QJsonArray array;
|
QJsonArray array;
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* PolyMC - Minecraft Launcher
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
|
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -48,6 +47,7 @@
|
|||||||
#include "Exception.h"
|
#include "Exception.h"
|
||||||
#include "minecraft/OneSixVersionFormat.h"
|
#include "minecraft/OneSixVersionFormat.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
|
#include "meta/Index.h"
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
|
|
||||||
@ -55,6 +55,7 @@
|
|||||||
#include "PackProfile_p.h"
|
#include "PackProfile_p.h"
|
||||||
#include "ComponentUpdateTask.h"
|
#include "ComponentUpdateTask.h"
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
#include "modplatform/ModAPI.h"
|
#include "modplatform/ModAPI.h"
|
||||||
|
|
||||||
static const QMap<QString, ModAPI::ModLoaderType> modloaderMapping{
|
static const QMap<QString, ModAPI::ModLoaderType> modloaderMapping{
|
||||||
@ -612,7 +613,7 @@ QVariant PackProfile::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
bool PackProfile::setData(const QModelIndex& index, const QVariant& value, int role)
|
bool PackProfile::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||||
{
|
{
|
||||||
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index.parent()))
|
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -674,12 +675,12 @@ Qt::ItemFlags PackProfile::flags(const QModelIndex &index) const
|
|||||||
|
|
||||||
int PackProfile::rowCount(const QModelIndex &parent) const
|
int PackProfile::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : d->components.size();
|
return d->components.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int PackProfile::columnCount(const QModelIndex &parent) const
|
int PackProfile::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : NUM_COLUMNS;
|
return NUM_COLUMNS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackProfile::move(const int index, const MoveDirection direction)
|
void PackProfile::move(const int index, const MoveDirection direction)
|
||||||
@ -737,11 +738,6 @@ void PackProfile::installCustomJar(QString selectedFile)
|
|||||||
installCustomJar_internal(selectedFile);
|
installCustomJar_internal(selectedFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackProfile::installAgents(QStringList selectedFiles)
|
|
||||||
{
|
|
||||||
installAgents_internal(selectedFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PackProfile::installEmpty(const QString& uid, const QString& name)
|
bool PackProfile::installEmpty(const QString& uid, const QString& name)
|
||||||
{
|
{
|
||||||
QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
|
QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
|
||||||
@ -836,14 +832,18 @@ bool PackProfile::installJarMods_internal(QStringList filepaths)
|
|||||||
for(auto filepath:filepaths)
|
for(auto filepath:filepaths)
|
||||||
{
|
{
|
||||||
QFileInfo sourceInfo(filepath);
|
QFileInfo sourceInfo(filepath);
|
||||||
QString id = QUuid::createUuid().toString(QUuid::WithoutBraces);
|
auto uuid = QUuid::createUuid();
|
||||||
|
QString id = uuid.toString().remove('{').remove('}');
|
||||||
QString target_filename = id + ".jar";
|
QString target_filename = id + ".jar";
|
||||||
QString target_id = "custom.jarmod." + id;
|
QString target_id = "org.multimc.jarmod." + id;
|
||||||
QString target_name = sourceInfo.completeBaseName() + " (jar mod)";
|
QString target_name = sourceInfo.completeBaseName() + " (jar mod)";
|
||||||
QString finalPath = FS::PathCombine(d->m_instance->jarModsDir(), target_filename);
|
QString finalPath = FS::PathCombine(d->m_instance->jarModsDir(), target_filename);
|
||||||
|
|
||||||
QFileInfo targetInfo(finalPath);
|
QFileInfo targetInfo(finalPath);
|
||||||
Q_ASSERT(!targetInfo.exists());
|
if(targetInfo.exists())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath()))
|
if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath()))
|
||||||
{
|
{
|
||||||
@ -852,7 +852,7 @@ bool PackProfile::installJarMods_internal(QStringList filepaths)
|
|||||||
|
|
||||||
auto f = std::make_shared<VersionFile>();
|
auto f = std::make_shared<VersionFile>();
|
||||||
auto jarMod = std::make_shared<Library>();
|
auto jarMod = std::make_shared<Library>();
|
||||||
jarMod->setRawName(GradleSpecifier("custom.jarmods:" + id + ":1"));
|
jarMod->setRawName(GradleSpecifier("org.multimc.jarmods:" + id + ":1"));
|
||||||
jarMod->setFilename(target_filename);
|
jarMod->setFilename(target_filename);
|
||||||
jarMod->setDisplayName(sourceInfo.completeBaseName());
|
jarMod->setDisplayName(sourceInfo.completeBaseName());
|
||||||
jarMod->setHint("local");
|
jarMod->setHint("local");
|
||||||
@ -892,7 +892,7 @@ bool PackProfile::installCustomJar_internal(QString filepath)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto specifier = GradleSpecifier("custom:customjar:1");
|
auto specifier = GradleSpecifier("org.multimc:customjar:1");
|
||||||
QFileInfo sourceInfo(filepath);
|
QFileInfo sourceInfo(filepath);
|
||||||
QString target_filename = specifier.getFileName();
|
QString target_filename = specifier.getFileName();
|
||||||
QString target_id = specifier.artifactId();
|
QString target_id = specifier.artifactId();
|
||||||
@ -939,64 +939,6 @@ bool PackProfile::installCustomJar_internal(QString filepath)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PackProfile::installAgents_internal(QStringList filepaths)
|
|
||||||
{
|
|
||||||
// FIXME code duplication
|
|
||||||
const QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
|
|
||||||
if (!FS::ensureFolderPathExists(patchDir))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const QString libDir = d->m_instance->getLocalLibraryPath();
|
|
||||||
if (!FS::ensureFolderPathExists(libDir))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (const QString& source : filepaths) {
|
|
||||||
const QFileInfo sourceInfo(source);
|
|
||||||
const QString id = QUuid::createUuid().toString(QUuid::WithoutBraces);
|
|
||||||
const QString targetBaseName = id + ".jar";
|
|
||||||
const QString targetId = "custom.agent." + id;
|
|
||||||
const QString targetName = sourceInfo.completeBaseName() + " (agent)";
|
|
||||||
const QString target = FS::PathCombine(d->m_instance->getLocalLibraryPath(), targetBaseName);
|
|
||||||
|
|
||||||
const QFileInfo targetInfo(target);
|
|
||||||
Q_ASSERT(!targetInfo.exists());
|
|
||||||
|
|
||||||
if (!QFile::copy(source, target))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto versionFile = std::make_shared<VersionFile>();
|
|
||||||
|
|
||||||
auto agent = std::make_shared<Library>();
|
|
||||||
|
|
||||||
agent->setRawName("custom.agents:" + id + ":1");
|
|
||||||
agent->setFilename(targetBaseName);
|
|
||||||
agent->setDisplayName(sourceInfo.completeBaseName());
|
|
||||||
agent->setHint("local");
|
|
||||||
|
|
||||||
versionFile->agents.append(std::make_shared<Agent>(agent, QString()));
|
|
||||||
|
|
||||||
versionFile->name = targetName;
|
|
||||||
versionFile->uid = targetId;
|
|
||||||
|
|
||||||
QFile patchFile(FS::PathCombine(patchDir, targetId + ".json"));
|
|
||||||
|
|
||||||
if (!patchFile.open(QFile::WriteOnly)) {
|
|
||||||
qCritical() << "Error opening" << patchFile.fileName() << "for reading:" << patchFile.errorString();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
patchFile.write(OneSixVersionFormat::versionFileToJson(versionFile).toJson());
|
|
||||||
patchFile.close();
|
|
||||||
|
|
||||||
appendComponent(new Component(this, versionFile->uid, versionFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
scheduleSave();
|
|
||||||
invalidateLaunchProfile();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<LaunchProfile> PackProfile::getProfile() const
|
std::shared_ptr<LaunchProfile> PackProfile::getProfile() const
|
||||||
{
|
{
|
||||||
if(!d->m_profile)
|
if(!d->m_profile)
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* PolyMC - Minecraft Launcher
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
|
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -86,9 +85,6 @@ public:
|
|||||||
/// install a jar/zip as a replacement for the main jar
|
/// install a jar/zip as a replacement for the main jar
|
||||||
void installCustomJar(QString selectedFile);
|
void installCustomJar(QString selectedFile);
|
||||||
|
|
||||||
/// install Java agent files
|
|
||||||
void installAgents(QStringList selectedFiles);
|
|
||||||
|
|
||||||
enum MoveDirection { MoveUp, MoveDown };
|
enum MoveDirection { MoveUp, MoveDown };
|
||||||
/// move component file # up or down the list
|
/// move component file # up or down the list
|
||||||
void move(const int index, const MoveDirection direction);
|
void move(const int index, const MoveDirection direction);
|
||||||
@ -171,7 +167,6 @@ private:
|
|||||||
bool load();
|
bool load();
|
||||||
bool installJarMods_internal(QStringList filepaths);
|
bool installJarMods_internal(QStringList filepaths);
|
||||||
bool installCustomJar_internal(QString filepath);
|
bool installCustomJar_internal(QString filepath);
|
||||||
bool installAgents_internal(QStringList filepaths);
|
|
||||||
bool removeComponent_internal(ComponentPtr patch);
|
bool removeComponent_internal(ComponentPtr patch);
|
||||||
|
|
||||||
private: /* data */
|
private: /* data */
|
||||||
|
@ -104,7 +104,7 @@ public:
|
|||||||
class ImplicitRule : public Rule
|
class ImplicitRule : public Rule
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual bool applies(const Library *, [[maybe_unused]] const RuntimeContext & runtimeContext)
|
virtual bool applies(const Library *, const RuntimeContext & runtimeContext)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "minecraft/PackProfile.h"
|
#include "minecraft/PackProfile.h"
|
||||||
#include "settings/INISettingsObject.h"
|
#include "settings/INISettingsObject.h"
|
||||||
|
|
||||||
VanillaCreationTask::VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loader_version)
|
VanillaCreationTask::VanillaCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loader_version)
|
||||||
: InstanceCreationTask(), m_version(std::move(version)), m_using_loader(true), m_loader(std::move(loader)), m_loader_version(std::move(loader_version))
|
: InstanceCreationTask(), m_version(std::move(version)), m_using_loader(true), m_loader(std::move(loader)), m_loader_version(std::move(loader_version))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -7,16 +7,16 @@
|
|||||||
class VanillaCreationTask final : public InstanceCreationTask {
|
class VanillaCreationTask final : public InstanceCreationTask {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
VanillaCreationTask(BaseVersion::Ptr version) : InstanceCreationTask(), m_version(std::move(version)) {}
|
VanillaCreationTask(BaseVersionPtr version) : InstanceCreationTask(), m_version(std::move(version)) {}
|
||||||
VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loader_version);
|
VanillaCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loader_version);
|
||||||
|
|
||||||
bool createInstance() override;
|
bool createInstance() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Version to update to / create of the instance.
|
// Version to update to / create of the instance.
|
||||||
BaseVersion::Ptr m_version;
|
BaseVersionPtr m_version;
|
||||||
|
|
||||||
bool m_using_loader = false;
|
bool m_using_loader = false;
|
||||||
QString m_loader;
|
QString m_loader;
|
||||||
BaseVersion::Ptr m_loader_version;
|
BaseVersionPtr m_loader_version;
|
||||||
};
|
};
|
||||||
|
@ -173,7 +173,7 @@ bool WorldList::resetIcon(int row)
|
|||||||
|
|
||||||
int WorldList::columnCount(const QModelIndex &parent) const
|
int WorldList::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return parent.isValid()? 0 : 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant WorldList::data(const QModelIndex &index, int role) const
|
QVariant WorldList::data(const QModelIndex &index, int role) const
|
||||||
@ -398,8 +398,8 @@ void WorldList::installWorld(QFileInfo filename)
|
|||||||
w.install(m_dir.absolutePath());
|
w.install(m_dir.absolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column,
|
bool WorldList::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
|
||||||
[[maybe_unused]] const QModelIndex &parent)
|
const QModelIndex &parent)
|
||||||
{
|
{
|
||||||
if (action == Qt::IgnoreAction)
|
if (action == Qt::IgnoreAction)
|
||||||
return true;
|
return true;
|
||||||
|
@ -54,7 +54,7 @@ public:
|
|||||||
|
|
||||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const
|
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : static_cast<int>(size());
|
return size();
|
||||||
};
|
};
|
||||||
virtual QVariant headerData(int section, Qt::Orientation orientation,
|
virtual QVariant headerData(int section, Qt::Orientation orientation,
|
||||||
int role = Qt::DisplayRole) const;
|
int role = Qt::DisplayRole) const;
|
||||||
|
@ -408,20 +408,20 @@ QVariant AccountList::headerData(int section, Qt::Orientation orientation, int r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int AccountList::rowCount(const QModelIndex &parent) const
|
int AccountList::rowCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
// Return count
|
// Return count
|
||||||
return parent.isValid() ? 0 : count();
|
return count();
|
||||||
}
|
}
|
||||||
|
|
||||||
int AccountList::columnCount(const QModelIndex &parent) const
|
int AccountList::columnCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : NUM_COLUMNS;
|
return NUM_COLUMNS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::ItemFlags AccountList::flags(const QModelIndex &index) const
|
Qt::ItemFlags AccountList::flags(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (index.row() < 0 || index.row() >= rowCount(index.parent()) || !index.isValid())
|
if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
|
||||||
{
|
{
|
||||||
return Qt::NoItemFlags;
|
return Qt::NoItemFlags;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "Parsers.h"
|
#include "Parsers.h"
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
#include "Logging.h"
|
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
@ -76,7 +75,9 @@ bool getBool(QJsonValue value, bool & out) {
|
|||||||
|
|
||||||
bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString name) {
|
bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString name) {
|
||||||
qDebug() << "Parsing" << name <<":";
|
qDebug() << "Parsing" << name <<":";
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
if(jsonError.error) {
|
if(jsonError.error) {
|
||||||
@ -136,7 +137,9 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na
|
|||||||
|
|
||||||
bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
|
bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
|
||||||
qDebug() << "Parsing Minecraft profile...";
|
qDebug() << "Parsing Minecraft profile...";
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
|
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
@ -272,7 +275,9 @@ decoded base64 "value":
|
|||||||
|
|
||||||
bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
|
bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
|
||||||
qDebug() << "Parsing Minecraft profile...";
|
qDebug() << "Parsing Minecraft profile...";
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
|
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
@ -384,7 +389,9 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
|
|||||||
|
|
||||||
bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) {
|
bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) {
|
||||||
qDebug() << "Parsing Minecraft entitlements...";
|
qDebug() << "Parsing Minecraft entitlements...";
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
|
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
@ -417,7 +424,9 @@ bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output)
|
|||||||
|
|
||||||
bool parseRolloutResponse(QByteArray & data, bool& result) {
|
bool parseRolloutResponse(QByteArray & data, bool& result) {
|
||||||
qDebug() << "Parsing Rollout response...";
|
qDebug() << "Parsing Rollout response...";
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
|
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
@ -446,7 +455,9 @@ bool parseRolloutResponse(QByteArray & data, bool& result) {
|
|||||||
bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) {
|
bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) {
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
qDebug() << "Parsing Mojang response...";
|
qDebug() << "Parsing Mojang response...";
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
if(jsonError.error) {
|
if(jsonError.error) {
|
||||||
qWarning() << "Failed to parse response from api.minecraftservices.com/launcher/login as JSON: " << jsonError.errorString();
|
qWarning() << "Failed to parse response from api.minecraftservices.com/launcher/login as JSON: " << jsonError.errorString();
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include "Logging.h"
|
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
|
|
||||||
@ -42,7 +41,9 @@ void EntitlementsStep::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO: check presence of same entitlementsRequestId?
|
// TODO: check presence of same entitlementsRequestId?
|
||||||
// TODO: validate JWTs?
|
// TODO: validate JWTs?
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
#include "Logging.h"
|
|
||||||
#include "minecraft/auth/AccountTask.h"
|
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
|
#include "minecraft/auth/AccountTask.h"
|
||||||
#include "net/NetUtils.h"
|
#include "net/NetUtils.h"
|
||||||
|
|
||||||
LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) {
|
LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) {
|
||||||
@ -52,10 +51,14 @@ void LauncherLoginStep::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
if (error != QNetworkReply::NoError) {
|
if (error != QNetworkReply::NoError) {
|
||||||
qWarning() << "Reply error:" << error;
|
qWarning() << "Reply error:" << error;
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
if (Net::isApplicationError(error)) {
|
if (Net::isApplicationError(error)) {
|
||||||
emit finished(
|
emit finished(
|
||||||
AccountTaskState::STATE_FAILED_SOFT,
|
AccountTaskState::STATE_FAILED_SOFT,
|
||||||
@ -73,7 +76,9 @@ void LauncherLoginStep::onRequestDone(
|
|||||||
|
|
||||||
if(!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) {
|
if(!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) {
|
||||||
qWarning() << "Could not parse login_with_xbox response...";
|
qWarning() << "Could not parse login_with_xbox response...";
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
emit finished(
|
emit finished(
|
||||||
AccountTaskState::STATE_FAILED_SOFT,
|
AccountTaskState::STATE_FAILED_SOFT,
|
||||||
tr("Failed to parse the Minecraft access token response.")
|
tr("Failed to parse the Minecraft access token response.")
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "Logging.h"
|
|
||||||
|
|
||||||
using OAuth2 = Katabasis::DeviceFlow;
|
using OAuth2 = Katabasis::DeviceFlow;
|
||||||
using Activity = Katabasis::Activity;
|
using Activity = Katabasis::Activity;
|
||||||
@ -118,12 +117,14 @@ void MSAStep::onOAuthActivityChanged(Katabasis::Activity activity) {
|
|||||||
// Succeeded or did not invalidate tokens
|
// Succeeded or did not invalidate tokens
|
||||||
emit hideVerificationUriAndCode();
|
emit hideVerificationUriAndCode();
|
||||||
QVariantMap extraTokens = m_oauth2->extraTokens();
|
QVariantMap extraTokens = m_oauth2->extraTokens();
|
||||||
|
#ifndef NDEBUG
|
||||||
if (!extraTokens.isEmpty()) {
|
if (!extraTokens.isEmpty()) {
|
||||||
qCDebug(authCredentials()) << "Extra tokens in response:";
|
qDebug() << "Extra tokens in response:";
|
||||||
foreach (QString key, extraTokens.keys()) {
|
foreach (QString key, extraTokens.keys()) {
|
||||||
qCDebug(authCredentials()) << "\t" << key << ":" << extraTokens.value(key);
|
qDebug() << "\t" << key << ":" << extraTokens.value(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
emit finished(AccountTaskState::STATE_WORKING, tr("Got "));
|
emit finished(AccountTaskState::STATE_WORKING, tr("Got "));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
#include "Logging.h"
|
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
#include "net/NetUtils.h"
|
#include "net/NetUtils.h"
|
||||||
@ -41,7 +40,9 @@ void MinecraftProfileStep::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
if (error == QNetworkReply::ContentNotFoundError) {
|
if (error == QNetworkReply::ContentNotFoundError) {
|
||||||
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
|
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
|
||||||
if(m_data->type == AccountType::Mojang) {
|
if(m_data->type == AccountType::Mojang) {
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
#include "Logging.h"
|
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
#include "net/NetUtils.h"
|
#include "net/NetUtils.h"
|
||||||
@ -44,7 +43,9 @@ void MinecraftProfileStepMojang::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
if (error == QNetworkReply::ContentNotFoundError) {
|
if (error == QNetworkReply::ContentNotFoundError) {
|
||||||
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
|
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
|
||||||
if(m_data->type == AccountType::Mojang) {
|
if(m_data->type == AccountType::Mojang) {
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <QJsonParseError>
|
#include <QJsonParseError>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
#include "Logging.h"
|
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
#include "net/NetUtils.h"
|
#include "net/NetUtils.h"
|
||||||
@ -59,7 +58,9 @@ void XboxAuthorizationStep::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
if (error != QNetworkReply::NoError) {
|
if (error != QNetworkReply::NoError) {
|
||||||
qWarning() << "Reply error:" << error;
|
qWarning() << "Reply error:" << error;
|
||||||
if (Net::isApplicationError(error)) {
|
if (Net::isApplicationError(error)) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
#include "Logging.h"
|
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
#include "net/NetUtils.h"
|
#include "net/NetUtils.h"
|
||||||
@ -56,7 +56,9 @@ void XboxProfileStep::onRequestDone(
|
|||||||
|
|
||||||
if (error != QNetworkReply::NoError) {
|
if (error != QNetworkReply::NoError) {
|
||||||
qWarning() << "Reply error:" << error;
|
qWarning() << "Reply error:" << error;
|
||||||
qCDebug(authCredentials()) << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
if (Net::isApplicationError(error)) {
|
if (Net::isApplicationError(error)) {
|
||||||
emit finished(
|
emit finished(
|
||||||
AccountTaskState::STATE_FAILED_SOFT,
|
AccountTaskState::STATE_FAILED_SOFT,
|
||||||
@ -72,7 +74,9 @@ void XboxProfileStep::onRequestDone(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(authCredentials()) << "XBox profile: " << data;
|
#ifndef NDEBUG
|
||||||
|
qDebug() << "XBox profile: " << data;
|
||||||
|
#endif
|
||||||
|
|
||||||
emit finished(AccountTaskState::STATE_WORKING, tr("Got Xbox profile"));
|
emit finished(AccountTaskState::STATE_WORKING, tr("Got Xbox profile"));
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,5 @@ void VerifyJavaInstall::executeTask() {
|
|||||||
{
|
{
|
||||||
emit logLine(tr("Java version %1").arg(major), MessageLevel::Error);
|
emit logLine(tr("Java version %1").arg(major), MessageLevel::Error);
|
||||||
}
|
}
|
||||||
emit logLine(tr("Go to instance Java settings to change your Java version or disable the Java compatibility check if you know what you're doing."), MessageLevel::Error);
|
|
||||||
|
|
||||||
emitFailed(QString("Incompatible Java major version"));
|
emitFailed(QString("Incompatible Java major version"));
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in
|
|||||||
|
|
||||||
int ModFolderModel::columnCount(const QModelIndex &parent) const
|
int ModFolderModel::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : NUM_COLUMNS;
|
return NUM_COLUMNS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task* ModFolderModel::createUpdateTask()
|
Task* ModFolderModel::createUpdateTask()
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user