Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into skin_selector

This commit is contained in:
Trial97 2023-09-05 00:18:45 +03:00
commit ab648e58ce
No known key found for this signature in database
GPG Key ID: 55EF5DA53DB36318
22 changed files with 254 additions and 98 deletions

View File

@ -20,7 +20,7 @@ jobs:
if: github.repository_owner == 'PrismLauncher' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Create backport PRs

View File

@ -125,7 +125,7 @@ jobs:
# PREPARE
##
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: 'true'
@ -620,7 +620,7 @@ jobs:
options: --privileged
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
if: inputs.build_type == 'Debug'
with:
submodules: 'true'

View File

@ -8,7 +8,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: 'true'

View File

@ -26,7 +26,7 @@ jobs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: 'true'
path: 'PrismLauncher-source'

View File

@ -16,8 +16,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23
- uses: DeterminateSystems/update-flake-lock@v20
with:

View File

@ -75,7 +75,6 @@ function(
set(CLANG_WARNINGS
-Wall
-Wextra # reasonable and standard
-Wextra-semi # Warn about semicolon after in-class function definition.
-Wshadow # warn the user if a variable declaration shadows one from a parent context
-Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps
# catch hard to track down memory errors

18
flake.lock generated
View File

@ -21,11 +21,11 @@
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1690933134,
"narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=",
"lastModified": 1693611461,
"narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb",
"rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca",
"type": "github"
},
"original": {
@ -91,11 +91,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1693145325,
"narHash": "sha256-Gat9xskErH1zOcLjYMhSDBo0JTBZKfGS0xJlIRnj6Rc=",
"lastModified": 1693626178,
"narHash": "sha256-Rpiy6lIOu4zny8tfGuIeN1ji9eSz9nPmm9yBhh/4IOM=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "cddebdb60de376c1bdb7a4e6ee3d98355453fe56",
"rev": "bfb7dfec93f3b5d7274db109f2990bc889861caf",
"type": "github"
},
"original": {
@ -108,11 +108,11 @@
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1690881714,
"narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=",
"lastModified": 1693471703,
"narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9e1960bc196baf6881340d53dccb203a951745a2",
"rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85",
"type": "github"
},
"original": {

View File

@ -23,5 +23,19 @@
outputs = inputs:
inputs.flake-parts.lib.mkFlake
{inherit inputs;}
{imports = [./nix];};
{
imports = [
inputs.pre-commit-hooks.flakeModule
./nix/dev.nix
./nix/distribution.nix
];
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
};
}

View File

@ -132,15 +132,21 @@ auto Mod::destroy(QDir& index_dir, bool preserve_metadata, bool attempt_trash) -
if (!preserve_metadata) {
qDebug() << QString("Destroying metadata for '%1' on purpose").arg(name());
destroyMetadata(index_dir);
}
return Resource::destroy(attempt_trash);
}
void Mod::destroyMetadata(QDir& index_dir)
{
if (metadata()) {
Metadata::remove(index_dir, metadata()->slug);
} else {
auto n = name();
Metadata::remove(index_dir, n);
}
}
return Resource::destroy(attempt_trash);
m_local_details.metadata = nullptr;
}
auto Mod::details() const -> const ModDetails&
@ -246,7 +252,8 @@ void Mod::setIcon(QImage new_image) const
PixmapCache::remove(m_pack_image_cache_key.key);
// scale the image to avoid flooding the pixmapcache
auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding));
auto pixmap =
QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
m_pack_image_cache_key.key = PixmapCache::insert(pixmap);
m_pack_image_cache_key.was_ever_used = true;
@ -259,7 +266,7 @@ QPixmap Mod::icon(QSize size, Qt::AspectRatioMode mode) const
if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) {
if (size.isNull())
return cached_image;
return cached_image.scaled(size, mode);
return cached_image.scaled(size, mode, Qt::SmoothTransformation);
}
// No valid image we can get

View File

@ -93,6 +93,8 @@ class Mod : public Resource {
// Delete all the files of this mod
auto destroy(QDir& index_dir, bool preserve_metadata = false, bool attempt_trash = true) -> bool;
// Delete the metadata only
void destroyMetadata(QDir& index_dir);
void finishResolvingWithDetails(ModDetails&& details);

View File

@ -233,6 +233,25 @@ bool ModFolderModel::deleteMods(const QModelIndexList& indexes)
return true;
}
bool ModFolderModel::deleteModsMetadata(const QModelIndexList& indexes)
{
if (indexes.isEmpty())
return true;
for (auto i : indexes) {
if (i.column() != 0) {
continue;
}
auto m = at(i.row());
auto index_dir = indexDir();
m->destroyMetadata(index_dir);
}
update();
return true;
}
bool ModFolderModel::isValid()
{
return m_dir.exists() && m_dir.isReadable();

View File

@ -81,6 +81,7 @@ class ModFolderModel : public ResourceFolderModel {
/// Deletes all the selected mods
bool deleteMods(const QModelIndexList& indexes);
bool deleteModsMetadata(const QModelIndexList& indexes);
bool isValid();

View File

@ -50,7 +50,8 @@ void ResourcePack::setImage(QImage new_image) const
PixmapCache::instance().remove(m_pack_image_cache_key.key);
// scale the image to avoid flooding the pixmapcache
auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding));
auto pixmap =
QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
m_pack_image_cache_key.key = PixmapCache::instance().insert(pixmap);
m_pack_image_cache_key.was_ever_used = true;
@ -68,7 +69,7 @@ QPixmap ResourcePack::image(QSize size, Qt::AspectRatioMode mode) const
if (PixmapCache::instance().find(m_pack_image_cache_key.key, &cached_image)) {
if (size.isNull())
return cached_image;
return cached_image.scaled(size, mode);
return cached_image.scaled(size, mode, Qt::SmoothTransformation);
}
// No valid image we can get

View File

@ -44,7 +44,8 @@ void TexturePack::setImage(QImage new_image) const
PixmapCache::remove(m_pack_image_cache_key.key);
// scale the image to avoid flooding the pixmapcache
auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding));
auto pixmap =
QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
m_pack_image_cache_key.key = PixmapCache::insert(pixmap);
m_pack_image_cache_key.was_ever_used = true;
@ -56,7 +57,7 @@ QPixmap TexturePack::image(QSize size, Qt::AspectRatioMode mode) const
if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) {
if (size.isNull())
return cached_image;
return cached_image.scaled(size, mode);
return cached_image.scaled(size, mode, Qt::SmoothTransformation);
}
// No valid image we can get

View File

@ -168,6 +168,17 @@
<string>Go to mods home page</string>
</property>
</action>
<action name="actionRemoveItemMetadata">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove metadata</string>
</property>
<property name="toolTip">
<string>Remove mod's metadata</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -92,6 +92,10 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr<ModFolderModel>
ui->actionsToolbar->addAction(ui->actionVisitItemPage);
connect(ui->actionVisitItemPage, &QAction::triggered, this, &ModFolderPage::visitModPages);
ui->actionRemoveItemMetadata->setToolTip(tr("Remove mod's metadata"));
ui->actionsToolbar->insertActionAfter(ui->actionRemoveItem, ui->actionRemoveItemMetadata);
connect(ui->actionRemoveItemMetadata, &QAction::triggered, this, &ModFolderPage::deleteModMetadata);
auto check_allow_update = [this] { return ui->treeView->selectionModel()->hasSelection() || !m_model->empty(); };
connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this, check_allow_update] {
@ -104,11 +108,16 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr<ModFolderModel>
if (selected <= 1) {
ui->actionVisitItemPage->setText(tr("Visit mod's page"));
ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page"));
ui->actionRemoveItemMetadata->setToolTip(tr("Remove mod's metadata"));
} else {
ui->actionVisitItemPage->setText(tr("Visit mods' pages"));
ui->actionVisitItemPage->setToolTip(tr("Go to the pages of the selected mods"));
ui->actionRemoveItemMetadata->setToolTip(tr("Remove mods' metadata"));
}
ui->actionVisitItemPage->setEnabled(selected != 0);
ui->actionRemoveItemMetadata->setEnabled(selected != 0);
});
connect(mods.get(), &ModFolderModel::rowsInserted, this,
@ -297,3 +306,24 @@ void ModFolderPage::visitModPages()
DesktopServices::openUrl(url);
}
}
void ModFolderPage::deleteModMetadata()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selectionCount = m_model->selectedMods(selection).length();
if (selectionCount == 0)
return;
if (selectionCount > 1) {
auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"),
tr("You are about to remove the metadata for %1 mods.\n"
"Are you sure?")
.arg(selectionCount),
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
->exec();
if (response != QMessageBox::Yes)
return;
}
m_model->deleteModsMetadata(selection);
}

View File

@ -61,6 +61,7 @@ class ModFolderPage : public ExternalResourcesPage {
private slots:
void removeItems(const QItemSelection& selection) override;
void deleteModMetadata();
void installMods();
void updateMods();

View File

@ -1,31 +0,0 @@
{
inputs,
self,
...
}: {
imports = [
./dev.nix
./distribution.nix
];
_module.args = {
# User-friendly version number.
version = builtins.substring 0 8 self.lastModifiedDate;
};
perSystem = {system, ...}: {
# Nixpkgs instantiated for supported systems with our overlay.
_module.args.pkgs = import inputs.nixpkgs {
inherit system;
overlays = [self.overlays.default];
};
};
# Supported systems.
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
}

View File

@ -1,16 +1,11 @@
{
inputs,
self,
...
}: {
perSystem = {
system,
config,
lib,
pkgs,
...
}: {
checks = {
pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run {
src = self;
pre-commit.settings = {
hooks = {
markdownlint.enable = true;
@ -24,14 +19,15 @@
};
};
tools.clang-tools = pkgs.clang-tools_16;
};
tools.clang-tools = lib.mkForce pkgs.clang-tools_16;
};
devShells.default = pkgs.mkShell {
inherit (self.checks.${system}.pre-commit-check) shellHook;
shellHook = ''
${config.pre-commit.installationScript}
'';
inputsFrom = [self.packages.${system}.prismlauncher-unwrapped];
inputsFrom = [config.packages.prismlauncher-unwrapped];
buildInputs = with pkgs; [ccache ninja];
};

View File

@ -1,30 +1,44 @@
{
inputs,
self,
version,
...
}: {
perSystem = {pkgs, ...}: {
packages = {
inherit (pkgs) prismlauncher-qt5-unwrapped prismlauncher-qt5 prismlauncher-unwrapped prismlauncher;
default = pkgs.prismlauncher;
perSystem = {
lib,
pkgs,
...
}: {
packages = let
ourPackages = lib.fix (final: self.overlays.default ({inherit (pkgs) darwin;} // final) pkgs);
in {
inherit
(ourPackages)
prismlauncher-qt5-unwrapped
prismlauncher-qt5
prismlauncher-unwrapped
prismlauncher
;
default = ourPackages.prismlauncher;
};
};
flake = {
overlays.default = final: prev: let
# Helper function to build prism against different versions of Qt.
mkPrism = qt:
qt.callPackage ./package.nix {
version = builtins.substring 0 8 self.lastModifiedDate or "dirty";
# common args for prismlauncher evaluations
unwrappedArgs = {
inherit (inputs) libnbtplusplus;
inherit (prev.darwin.apple_sdk.frameworks) Cocoa;
inherit (final.darwin.apple_sdk.frameworks) Cocoa;
inherit self version;
};
in {
prismlauncher-qt5-unwrapped = mkPrism final.libsForQt5;
prismlauncher-qt5 = prev.prismlauncher-qt5.override {prismlauncher-unwrapped = final.prismlauncher-qt5-unwrapped;};
prismlauncher-unwrapped = mkPrism final.qt6Packages;
prismlauncher = prev.prismlauncher.override {inherit (final) prismlauncher-unwrapped;};
prismlauncher-qt5-unwrapped = prev.libsForQt5.callPackage ./pkg unwrappedArgs;
prismlauncher-qt5 = prev.libsForQt5.callPackage ./pkg/wrapper.nix {
prismlauncher-unwrapped = final.prismlauncher-qt5-unwrapped;
};
prismlauncher-unwrapped = prev.qt6Packages.callPackage ./pkg unwrappedArgs;
prismlauncher = prev.qt6Packages.callPackage ./pkg/wrapper.nix {inherit (final) prismlauncher-unwrapped;};
};
};
}

91
nix/pkg/wrapper.nix Normal file
View File

@ -0,0 +1,91 @@
{
lib,
stdenv,
symlinkJoin,
prismlauncher-unwrapped,
wrapQtAppsHook,
qtbase, # needed for wrapQtAppsHook
qtsvg,
qtwayland,
xorg,
libpulseaudio,
libGL,
glfw,
openal,
jdk8,
jdk17,
gamemode,
flite,
mesa-demos,
udev,
msaClientID ? null,
gamemodeSupport ? stdenv.isLinux,
textToSpeechSupport ? stdenv.isLinux,
jdks ? [jdk17 jdk8],
additionalLibs ? [],
additionalPrograms ? [],
}: let
prismlauncherFinal = prismlauncher-unwrapped.override {
inherit msaClientID gamemodeSupport;
};
in
symlinkJoin {
name = "prismlauncher-${prismlauncherFinal.version}";
paths = [prismlauncherFinal];
nativeBuildInputs = [
wrapQtAppsHook
];
buildInputs =
[
qtbase
qtsvg
]
++ lib.optional (lib.versionAtLeast qtbase.version "6" && stdenv.isLinux) qtwayland;
postBuild = ''
wrapQtAppsHook
'';
qtWrapperArgs = let
runtimeLibs =
(with xorg; [
libX11
libXext
libXcursor
libXrandr
libXxf86vm
])
++ [
# lwjgl
libpulseaudio
libGL
glfw
openal
stdenv.cc.cc.lib
# oshi
udev
]
++ lib.optional gamemodeSupport gamemode.lib
++ lib.optional textToSpeechSupport flite
++ additionalLibs;
runtimePrograms =
[
xorg.xrandr
mesa-demos # need glxinfo
]
++ additionalPrograms;
in
["--prefix PRISMLAUNCHER_JAVA_PATHS : ${lib.makeSearchPath "bin/java" jdks}"]
++ lib.optionals stdenv.isLinux [
"--set LD_LIBRARY_PATH /run/opengl-driver/lib:${lib.makeLibraryPath runtimeLibs}"
# xorg.xrandr needed for LWJGL [2.9.2, 3) https://github.com/LWJGL/lwjgl/issues/128
"--prefix PATH : ${lib.makeBinPath runtimePrograms}"
];
inherit (prismlauncherFinal) meta;
}