aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml16
-rw-r--r--.github/workflows/trigger_release.yml2
-rw-r--r--buildconfig/BuildConfig.h5
-rw-r--r--default.nix15
-rw-r--r--flake.lock62
-rw-r--r--flake.nix78
-rw-r--r--launcher/CMakeLists.txt9
-rw-r--r--launcher/FastFileIconProvider.cpp47
-rw-r--r--launcher/FastFileIconProvider.h26
-rw-r--r--launcher/FileIgnoreProxy.cpp256
-rw-r--r--launcher/FileIgnoreProxy.h72
-rw-r--r--launcher/InstanceCopyTask.cpp30
-rw-r--r--launcher/meta/JsonFormat.cpp7
-rw-r--r--launcher/meta/Version.cpp4
-rw-r--r--launcher/meta/Version.h4
-rw-r--r--launcher/meta/VersionList.cpp4
-rw-r--r--launcher/minecraft/Component.cpp4
-rw-r--r--launcher/minecraft/OneSixVersionFormat.cpp10
-rw-r--r--launcher/minecraft/VersionFile.h2
-rw-r--r--launcher/minecraft/mod/DataPack.cpp4
-rw-r--r--launcher/minecraft/mod/ResourcePack.cpp3
-rw-r--r--launcher/modplatform/atlauncher/ATLPackInstallTask.cpp2
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackExportTask.cpp319
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackExportTask.h77
-rw-r--r--launcher/net/ByteArraySink.h15
-rw-r--r--launcher/settings/INIFile.cpp85
-rw-r--r--launcher/tasks/ConcurrentTask.cpp3
-rw-r--r--launcher/translations/TranslationsModel.cpp7
-rw-r--r--launcher/ui/MainWindow.cpp70
-rw-r--r--launcher/ui/MainWindow.h7
-rw-r--r--launcher/ui/MainWindow.ui19
-rw-r--r--launcher/ui/dialogs/ExportInstanceDialog.cpp304
-rw-r--r--launcher/ui/dialogs/ExportInstanceDialog.h46
-rw-r--r--launcher/ui/dialogs/ExportMrPackDialog.cpp123
-rw-r--r--launcher/ui/dialogs/ExportMrPackDialog.h45
-rw-r--r--launcher/ui/dialogs/ExportMrPackDialog.ui136
-rw-r--r--launcher/ui/dialogs/ResourceDownloadDialog.cpp6
-rw-r--r--launcher/ui/pages/global/APIPage.cpp2
-rw-r--r--launcher/ui/pages/instance/InstanceSettingsPage.cpp54
-rw-r--r--launcher/ui/pages/instance/InstanceSettingsPage.h3
-rw-r--r--launcher/ui/pages/instance/InstanceSettingsPage.ui9
-rw-r--r--launcher/ui/pages/modplatform/ResourcePage.cpp9
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp2
-rw-r--r--nix/default.nix118
-rw-r--r--nix/dev.nix46
-rw-r--r--nix/distribution.nix29
-rw-r--r--nix/flake-compat.nix9
-rw-r--r--nix/package.nix65
-rw-r--r--program_info/win_install.nsi.in75
-rw-r--r--renovate.json8
-rw-r--r--tests/INIFile_test.cpp56
51 files changed, 1757 insertions, 652 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 691e257b..a6a6ecea 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -86,11 +86,11 @@ jobs:
- os: macos-12
name: macOS
- macosx_deployment_target: 10.15
+ macosx_deployment_target: 11.0
qt_ver: 6
qt_host: mac
qt_arch: ''
- qt_version: '6.5.1'
+ qt_version: '6.5.0'
qt_modules: 'qt5compat qtimageformats'
qt_tools: ''
@@ -375,6 +375,8 @@ jobs:
shell: msys2 {0}
run: |
cmake --install ${{ env.BUILD_DIR }}
+ touch ${{ env.INSTALL_DIR }}/manifest.txt
+ for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_DIR }}/manifest.txt
- name: Package (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == ''
@@ -387,6 +389,10 @@ jobs:
Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll
Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll
}
+ cd ${{ github.workspace }}
+
+ Get-ChildItem ${{ env.INSTALL_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
+
- name: Fetch codesign certificate (Windows)
if: runner.os == 'Windows'
@@ -411,12 +417,15 @@ jobs:
run: |
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
+ for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
- 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
+
+ Get-ChildItem ${{ env.INSTALL_PORTABLE_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_PORTABLE_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
- name: Package (Windows, installer)
if: runner.os == 'Windows'
@@ -437,6 +446,7 @@ jobs:
if: runner.os == 'Linux'
run: |
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_DIR }}
+ for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_DIR }}/manifest.txt
cd ${{ env.INSTALL_DIR }}
tar --owner root --group root -czf ../PrismLauncher.tar.gz *
@@ -446,6 +456,8 @@ jobs:
run: |
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }}
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
+ for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
+
cd ${{ env.INSTALL_PORTABLE_DIR }}
tar -czf ../PrismLauncher-portable.tar.gz *
diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml
index 3c56a38e..f19b8398 100644
--- a/.github/workflows/trigger_release.yml
+++ b/.github/workflows/trigger_release.yml
@@ -47,7 +47,7 @@ jobs:
mv PrismLauncher-macOS-Legacy*/PrismLauncher.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz
mv PrismLauncher-macOS*/PrismLauncher.tar.gz PrismLauncher-macOS-${{ env.VERSION }}.tar.gz
- tar -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
+ tar --exclude='.git' -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
for d in PrismLauncher-Windows-MSVC*; do
cd "${d}" || continue
diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h
index a05d7a9e..8543d724 100644
--- a/buildconfig/BuildConfig.h
+++ b/buildconfig/BuildConfig.h
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,6 +37,7 @@
#pragma once
#include <QString>
+#include <QList>
/**
* \brief The Config class holds all the build-time information passed from the build system.
@@ -160,6 +162,7 @@ class Config {
QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2";
QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2";
+ QStringList MODRINTH_MRPACK_HOSTS{"cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com"};
QString FLAME_BASE_URL = "https://api.curseforge.com/v1";
diff --git a/default.nix b/default.nix
index 146942d5..c7d0c267 100644
--- a/default.nix
+++ b/default.nix
@@ -1 +1,14 @@
-(import nix/flake-compat.nix).defaultNix
+(
+ import
+ (
+ let
+ lock = builtins.fromJSON (builtins.readFile ./flake.lock);
+ in
+ fetchTarball {
+ url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
+ sha256 = lock.nodes.flake-compat.locked.narHash;
+ }
+ )
+ {src = ./.;}
+)
+.defaultNix
diff --git a/flake.lock b/flake.lock
index ad9196a9..87586643 100644
--- a/flake.lock
+++ b/flake.lock
@@ -16,29 +16,31 @@
"type": "github"
}
},
- "flake-compat_2": {
- "flake": false,
+ "flake-parts": {
+ "inputs": {
+ "nixpkgs-lib": "nixpkgs-lib"
+ },
"locked": {
- "lastModified": 1673956053,
- "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
- "owner": "edolstra",
- "repo": "flake-compat",
- "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
+ "lastModified": 1683560683,
+ "narHash": "sha256-XAygPMN5Xnk/W2c1aW0jyEa6lfMDZWlQgiNtmHXytPc=",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "rev": "006c75898cf814ef9497252b022e91c946ba8e17",
"type": "github"
},
"original": {
- "owner": "edolstra",
- "repo": "flake-compat",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"locked": {
- "lastModified": 1676283394,
- "narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
+ "lastModified": 1667395993,
+ "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
- "rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
+ "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
@@ -86,11 +88,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1678693419,
- "narHash": "sha256-bbSv5yqZAW6dz+3f3f3pOUZbxpPN+3OgCljgn7P+nnQ=",
+ "lastModified": 1685012353,
+ "narHash": "sha256-U3oOge4cHnav8OLGdRVhL45xoRj4Ppd+It6nPC9nNIU=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "8e3fad82be64c06fbfb9fd43993aec9ef4623936",
+ "rev": "aeb75dba965e790de427b73315d5addf91a54955",
"type": "github"
},
"original": {
@@ -100,40 +102,44 @@
"type": "github"
}
},
- "nixpkgs-stable": {
+ "nixpkgs-lib": {
"locked": {
- "lastModified": 1673800717,
- "narHash": "sha256-SFHraUqLSu5cC6IxTprex/nTsI81ZQAtDvlBvGDWfnA=",
+ "dir": "lib",
+ "lastModified": 1682879489,
+ "narHash": "sha256-sASwo8gBt7JDnOOstnps90K1wxmVfyhsTPPNTGBPjjg=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "2f9fd351ec37f5d479556cd48be4ca340da59b8f",
+ "rev": "da45bf6ec7bbcc5d1e14d3795c025199f28e0de0",
"type": "github"
},
"original": {
+ "dir": "lib",
"owner": "NixOS",
- "ref": "nixos-22.11",
+ "ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
- "flake-compat": "flake-compat_2",
- "flake-utils": [
- "flake-utils"
+ "flake-compat": [
+ "flake-compat"
],
+ "flake-utils": "flake-utils",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
],
- "nixpkgs-stable": "nixpkgs-stable"
+ "nixpkgs-stable": [
+ "nixpkgs"
+ ]
},
"locked": {
- "lastModified": 1678376203,
- "narHash": "sha256-3tyYGyC8h7fBwncLZy5nCUjTJPrHbmNwp47LlNLOHSM=",
+ "lastModified": 1684842236,
+ "narHash": "sha256-rYWsIXHvNhVQ15RQlBUv67W3YnM+Pd+DuXGMvCBq2IE=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
- "rev": "1a20b9708962096ec2481eeb2ddca29ed747770a",
+ "rev": "61e567d6497bc9556f391faebe5e410e6623217f",
"type": "github"
},
"original": {
@@ -145,7 +151,7 @@
"root": {
"inputs": {
"flake-compat": "flake-compat",
- "flake-utils": "flake-utils",
+ "flake-parts": "flake-parts",
"libnbtplusplus": "libnbtplusplus",
"nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks"
diff --git a/flake.nix b/flake.nix
index f656703c..c3148fe0 100644
--- a/flake.nix
+++ b/flake.nix
@@ -3,11 +3,12 @@
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
- flake-utils.url = "github:numtide/flake-utils";
+ flake-parts.url = "github:hercules-ci/flake-parts";
pre-commit-hooks = {
url = "github:cachix/pre-commit-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
- inputs.flake-utils.follows = "flake-utils";
+ inputs.nixpkgs-stable.follows = "nixpkgs";
+ inputs.flake-compat.follows = "flake-compat";
};
flake-compat = {
url = "github:edolstra/flake-compat";
@@ -19,73 +20,8 @@
};
};
- outputs = {
- self,
- nixpkgs,
- flake-utils,
- pre-commit-hooks,
- libnbtplusplus,
- ...
- }: let
- # User-friendly version number.
- version = builtins.substring 0 8 self.lastModifiedDate;
-
- # Supported systems (qtbase is currently broken for "aarch64-darwin")
- supportedSystems = with flake-utils.lib.system; [
- x86_64-linux
- x86_64-darwin
- aarch64-linux
- ];
-
- packagesFn = pkgs: {
- prismlauncher-qt5 = pkgs.libsForQt5.callPackage ./nix {
- inherit version self libnbtplusplus;
- };
- prismlauncher = pkgs.qt6Packages.callPackage ./nix {
- inherit version self libnbtplusplus;
- };
- };
- in
- flake-utils.lib.eachSystem supportedSystems (system: let
- pkgs = nixpkgs.legacyPackages.${system};
- in {
- checks = {
- pre-commit-check = pre-commit-hooks.lib.${system}.run {
- src = ./.;
- hooks = {
- markdownlint.enable = true;
-
- alejandra.enable = true;
- deadnix.enable = true;
-
- clang-format = {
- enable =
- false; # As most of the codebase is **not** formatted, we don't want clang-format yet
- types_or = ["c" "c++"];
- };
- };
- };
- };
-
- packages = let
- packages = packagesFn pkgs;
- in
- packages // {default = packages.prismlauncher;};
-
- devShells.default = pkgs.mkShell {
- inherit (self.checks.${system}.pre-commit-check) shellHook;
- packages = with pkgs; [
- nodePackages.markdownlint-cli
- alejandra
- deadnix
- clang-tools
- ];
-
- inputsFrom = [self.packages.${system}.default];
- buildInputs = with pkgs; [ccache ninja];
- };
- })
- // {
- overlays.default = final: _: (packagesFn final);
- };
+ outputs = inputs:
+ inputs.flake-parts.lib.mkFlake
+ {inherit inputs;}
+ {imports = [./nix];};
}
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 273b5449..ce2771a4 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -525,6 +525,8 @@ set(MODRINTH_SOURCES
modplatform/modrinth/ModrinthCheckUpdate.h
modplatform/modrinth/ModrinthInstanceCreationTask.cpp
modplatform/modrinth/ModrinthInstanceCreationTask.h
+ modplatform/modrinth/ModrinthPackExportTask.cpp
+ modplatform/modrinth/ModrinthPackExportTask.h
)
set(PACKWIZ_SOURCES
@@ -720,6 +722,10 @@ SET(LAUNCHER_SOURCES
# FIXME: maybe find a better home for this.
SkinUtils.cpp
SkinUtils.h
+ FileIgnoreProxy.cpp
+ FileIgnoreProxy.h
+ FastFileIconProvider.cpp
+ FastFileIconProvider.h
# GUI - setup wizard
ui/setupwizard/SetupWizard.h
@@ -900,6 +906,8 @@ SET(LAUNCHER_SOURCES
ui/dialogs/EditAccountDialog.h
ui/dialogs/ExportInstanceDialog.cpp
ui/dialogs/ExportInstanceDialog.h
+ ui/dialogs/ExportMrPackDialog.cpp
+ ui/dialogs/ExportMrPackDialog.h
ui/dialogs/IconPickerDialog.cpp
ui/dialogs/IconPickerDialog.h
ui/dialogs/ImportResourceDialog.cpp
@@ -1046,6 +1054,7 @@ qt_wrap_ui(LAUNCHER_UI
ui/dialogs/ProfileSelectDialog.ui
ui/dialogs/SkinUploadDialog.ui
ui/dialogs/ExportInstanceDialog.ui
+ ui/dialogs/ExportMrPackDialog.ui
ui/dialogs/IconPickerDialog.ui
ui/dialogs/ImportResourceDialog.ui
ui/dialogs/MSALoginDialog.ui
diff --git a/launcher/FastFileIconProvider.cpp b/launcher/FastFileIconProvider.cpp
new file mode 100644
index 00000000..f2b6f442
--- /dev/null
+++ b/launcher/FastFileIconProvider.cpp
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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 "FastFileIconProvider.h"
+
+#include <QApplication>
+#include <QStyle>
+
+QIcon FastFileIconProvider::icon(const QFileInfo& info) const
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
+ bool link = info.isSymbolicLink() || info.isAlias() || info.isShortcut();
+#else
+ // in versions prior to 6.4 we don't have access to isAlias
+ bool link = info.isSymLink();
+#endif
+ QStyle::StandardPixmap icon;
+
+ if (info.isDir()) {
+ if (link)
+ icon = QStyle::SP_DirLinkIcon;
+ else
+ icon = QStyle::SP_DirIcon;
+ } else {
+ if (link)
+ icon = QStyle::SP_FileLinkIcon;
+ else
+ icon = QStyle::SP_FileIcon;
+ }
+
+ return QApplication::style()->standardIcon(icon);
+} \ No newline at end of file
diff --git a/launcher/FastFileIconProvider.h b/launcher/FastFileIconProvider.h
new file mode 100644
index 00000000..20853404
--- /dev/null
+++ b/launcher/FastFileIconProvider.h
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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 <QFileIconProvider>
+
+class FastFileIconProvider : public QFileIconProvider {
+ public:
+ QIcon icon(const QFileInfo& info) const override;
+}; \ No newline at end of file
diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp
new file mode 100644
index 00000000..a3b7d505
--- /dev/null
+++ b/launcher/FileIgnoreProxy.cpp
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FileIgnoreProxy.h"
+
+#include <QDebug>
+#include <QFileSystemModel>
+#include <QSortFilterProxyModel>
+#include <QStack>
+#include "FileSystem.h"
+#include "SeparatorPrefixTree.h"
+#include "StringUtils.h"
+
+FileIgnoreProxy::FileIgnoreProxy(QString root, QObject* parent) : QSortFilterProxyModel(parent), root(root) {}
+// NOTE: Sadly, we have to do sorting ourselves.
+bool FileIgnoreProxy::lessThan(const QModelIndex& left, const QModelIndex& right) const
+{
+ QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
+ if (!fsm) {
+ return QSortFilterProxyModel::lessThan(left, right);
+ }
+ bool asc = sortOrder() == Qt::AscendingOrder ? true : false;
+
+ QFileInfo leftFileInfo = fsm->fileInfo(left);
+ QFileInfo rightFileInfo = fsm->fileInfo(right);
+
+ if (!leftFileInfo.isDir() && rightFileInfo.isDir()) {
+ return !asc;
+ }
+ if (leftFileInfo.isDir() && !rightFileInfo.isDir()) {
+ return asc;
+ }
+
+ // sort and proxy model breaks the original model...
+ if (sortColumn() == 0) {
+ return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0;
+ }
+ if (sortColumn() == 1) {
+ auto leftSize = leftFileInfo.size();
+ auto rightSize = rightFileInfo.size();
+ if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir())) {
+ return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0 ? asc : !asc;
+ }
+ return leftSize < rightSize;
+ }
+ return QSortFilterProxyModel::lessThan(left, right);
+}
+
+Qt::ItemFlags FileIgnoreProxy::flags(const QModelIndex& index) const
+{
+ if (!index.isValid())
+ return Qt::NoItemFlags;
+
+ auto sourceIndex = mapToSource(index);
+ Qt::ItemFlags flags = sourceIndex.flags();
+ if (index.column() == 0) {
+ flags |= Qt::ItemIsUserCheckable;
+ if (sourceIndex.model()->hasChildren(sourceIndex)) {
+ flags |= Qt::ItemIsAutoTristate;
+ }
+ }
+
+ return fla