aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml2
-rw-r--r--CMakeLists.txt2
-rw-r--r--launcher/CMakeLists.txt18
-rw-r--r--launcher/FileSystem.cpp5
-rw-r--r--launcher/FileSystem.h5
-rw-r--r--launcher/minecraft/World.cpp7
-rw-r--r--launcher/minecraft/auth/Parsers.cpp25
-rw-r--r--launcher/minecraft/auth/steps/EntitlementsStep.cpp5
-rw-r--r--launcher/minecraft/auth/steps/LauncherLoginStep.cpp15
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.cpp7
-rw-r--r--launcher/minecraft/auth/steps/MinecraftProfileStep.cpp5
-rw-r--r--launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp5
-rw-r--r--launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp5
-rw-r--r--launcher/minecraft/auth/steps/XboxProfileStep.cpp10
-rw-r--r--launcher/minecraft/mod/Mod.cpp14
-rw-r--r--launcher/minecraft/mod/Mod.h3
-rw-r--r--launcher/minecraft/mod/ModFolderModel.cpp15
-rw-r--r--launcher/minecraft/mod/ModFolderModel.h1
-rw-r--r--launcher/minecraft/mod/Resource.cpp4
-rw-r--r--launcher/minecraft/mod/Resource.h3
-rw-r--r--launcher/ui/GuiUtil.cpp28
-rw-r--r--launcher/ui/GuiUtil.h3
-rw-r--r--launcher/ui/MainWindow.cpp39
-rw-r--r--launcher/ui/pages/instance/ExternalResourcesPage.cpp49
-rw-r--r--launcher/ui/pages/instance/ExternalResourcesPage.h3
-rw-r--r--launcher/ui/pages/instance/LogPage.cpp29
-rw-r--r--launcher/ui/pages/instance/ModFolderPage.cpp10
-rw-r--r--launcher/ui/pages/instance/ModFolderPage.h5
-rw-r--r--launcher/ui/pages/instance/OtherLogsPage.cpp31
-rw-r--r--launcher/ui/pages/instance/ScreenshotsPage.cpp48
-rw-r--r--launcher/ui/pages/instance/ServersPage.cpp15
-rw-r--r--launcher/ui/pages/instance/VersionPage.cpp41
-rw-r--r--launcher/ui/pages/instance/WorldListPage.cpp18
-rw-r--r--launcher/ui/pages/instance/WorldListPage.ui2
-rw-r--r--launcher/ui/widgets/ModListView.cpp16
-rw-r--r--libraries/katabasis/CMakeLists.txt9
-rw-r--r--libraries/katabasis/include/katabasis/DeviceFlow.h1
-rw-r--r--libraries/katabasis/src/DeviceFlow.cpp6
-rw-r--r--program_info/org.prismlauncher.PrismLauncher.metainfo.xml.in29
39 files changed, 384 insertions, 154 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9f286014..b6e179e1 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -165,7 +165,7 @@ jobs:
- name: Retrieve ccache cache (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
- uses: actions/cache@v3.2.1
+ uses: actions/cache@v3.2.2
with:
path: '${{ github.workspace }}\.ccache'
key: ${{ matrix.os }}-mingw-w64
diff --git a/CMakeLists.txt b/CMakeLists.txt
index de9b6fe1..c7ba9e9f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -268,6 +268,8 @@ if(NOT Launcher_FORCE_BUNDLED_LIBS)
find_package(ghc_filesystem QUIET)
endif()
+include(ECMQtDeclareLoggingCategory)
+
####################################### Program Info #######################################
set(Launcher_APP_BINARY_NAME "prismlauncher" CACHE STRING "Name of the Launcher binary")
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index a0d92b6e..6ca88ec6 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -551,6 +551,24 @@ set(ATLAUNCHER_SOURCES
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 ################################
set(LOGIC_SOURCES
diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp
index 3e8e10a5..b3af4f4e 100644
--- a/launcher/FileSystem.cpp
+++ b/launcher/FileSystem.cpp
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022 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
@@ -226,7 +227,7 @@ bool deletePath(QString path)
return err.value() == 0;
}
-bool trash(QString path, QString *pathInTrash = nullptr)
+bool trash(QString path, QString *pathInTrash)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
return false;
diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h
index ac893725..15233b66 100644
--- a/launcher/FileSystem.h
+++ b/launcher/FileSystem.h
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022 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
@@ -129,7 +130,7 @@ bool deletePath(QString path);
/**
* Trash a folder / file
*/
-bool trash(QString path, QString *pathInTrash);
+bool trash(QString path, QString *pathInTrash = nullptr);
QString PathCombine(const QString& path1, const QString& path2);
QString PathCombine(const QString& path1, const QString& path2, const QString& path3);
diff --git a/launcher/minecraft/World.cpp b/launcher/minecraft/World.cpp
index 90fcf337..d310f8b9 100644
--- a/launcher/minecraft/World.cpp
+++ b/launcher/minecraft/World.cpp
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022 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
@@ -545,6 +546,10 @@ bool World::replace(World &with)
bool World::destroy()
{
if(!is_valid) return false;
+
+ if (FS::trash(m_containerFile.filePath()))
+ return true;
+
if (m_containerFile.isDir())
{
QDir d(m_containerFile.filePath());
diff --git a/launcher/minecraft/auth/Parsers.cpp b/launcher/minecraft/auth/Parsers.cpp
index 47473899..f3d9ad56 100644
--- a/launcher/minecraft/auth/Parsers.cpp
+++ b/launcher/minecraft/auth/Parsers.cpp
@@ -1,5 +1,6 @@
#include "Parsers.h"
#include "Json.h"
+#include "Logging.h"
#include <QJsonDocument>
#include <QJsonArray>
@@ -75,9 +76,7 @@ bool getBool(QJsonValue value, bool & out) {
bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString name) {
qDebug() << "Parsing" << name <<":";
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
if(jsonError.error) {
@@ -137,9 +136,7 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na
bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
qDebug() << "Parsing Minecraft profile...";
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
@@ -275,9 +272,7 @@ decoded base64 "value":
bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
qDebug() << "Parsing Minecraft profile...";
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
@@ -389,9 +384,7 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) {
qDebug() << "Parsing Minecraft entitlements...";
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
@@ -424,9 +417,7 @@ bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output)
bool parseRolloutResponse(QByteArray & data, bool& result) {
qDebug() << "Parsing Rollout response...";
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
@@ -455,9 +446,7 @@ bool parseRolloutResponse(QByteArray & data, bool& result) {
bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) {
QJsonParseError jsonError;
qDebug() << "Parsing Mojang response...";
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
if(jsonError.error) {
qWarning() << "Failed to parse response from api.minecraftservices.com/launcher/login as JSON: " << jsonError.errorString();
diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.cpp b/launcher/minecraft/auth/steps/EntitlementsStep.cpp
index f726244f..bd604292 100644
--- a/launcher/minecraft/auth/steps/EntitlementsStep.cpp
+++ b/launcher/minecraft/auth/steps/EntitlementsStep.cpp
@@ -3,6 +3,7 @@
#include <QNetworkRequest>
#include <QUuid>
+#include "Logging.h"
#include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h"
@@ -41,9 +42,7 @@ void EntitlementsStep::onRequestDone(
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
requestor->deleteLater();
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
// TODO: check presence of same entitlementsRequestId?
// TODO: validate JWTs?
diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp
index 8c53f037..8a26cbe7 100644
--- a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp
+++ b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp
@@ -2,9 +2,10 @@
#include <QNetworkRequest>
+#include "Logging.h"
+#include "minecraft/auth/AccountTask.h"
#include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h"
-#include "minecraft/auth/AccountTask.h"
#include "net/NetUtils.h"
LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) {
@@ -51,14 +52,10 @@ void LauncherLoginStep::onRequestDone(
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
requestor->deleteLater();
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
if (error != QNetworkReply::NoError) {
qWarning() << "Reply error:" << error;
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
if (Net::isApplicationError(error)) {
emit finished(
AccountTaskState::STATE_FAILED_SOFT,
@@ -76,9 +73,7 @@ void LauncherLoginStep::onRequestDone(
if(!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) {
qWarning() << "Could not parse login_with_xbox response...";
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
emit finished(
AccountTaskState::STATE_FAILED_SOFT,
tr("Failed to parse the Minecraft access token response.")
diff --git a/launcher/minecraft/auth/steps/MSAStep.cpp b/launcher/minecraft/auth/steps/MSAStep.cpp
index 16afcb42..6fc8d468 100644
--- a/launcher/minecraft/auth/steps/MSAStep.cpp
+++ b/launcher/minecraft/auth/steps/MSAStep.cpp
@@ -42,6 +42,7 @@
#include "minecraft/auth/Parsers.h"
#include "Application.h"
+#include "Logging.h"
using OAuth2 = Katabasis::DeviceFlow;
using Activity = Katabasis::Activity;
@@ -117,14 +118,12 @@ void MSAStep::onOAuthActivityChanged(Katabasis::Activity activity) {
// Succeeded or did not invalidate tokens
emit hideVerificationUriAndCode();
QVariantMap extraTokens = m_oauth2->extraTokens();
-#ifndef NDEBUG
if (!extraTokens.isEmpty()) {
- qDebug() << "Extra tokens in response:";
+ qCDebug(authCredentials()) << "Extra tokens in response:";
foreach (QString key, extraTokens.keys()) {
- qDebug() << "\t" << key << ":" << extraTokens.value(key);
+ qCDebug(authCredentials()) << "\t" << key << ":" << extraTokens.value(key);
}
}
-#endif
emit finished(AccountTaskState::STATE_WORKING, tr("Got "));
return;
}
diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp
index b39b9326..6cfa7c1c 100644
--- a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp
+++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp
@@ -2,6 +2,7 @@
#include <QNetworkRequest>
+#include "Logging.h"
#include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h"
@@ -40,9 +41,7 @@ void MinecraftProfileStep::onRequestDone(
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
requestor->deleteLater();
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
if (error == QNetworkReply::ContentNotFoundError) {
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
if(m_data->type == AccountType::Mojang) {
diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp
index 6a1eb7a0..8c378588 100644
--- a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp
+++ b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp
@@ -2,6 +2,7 @@
#include <QNetworkRequest>
+#include "Logging.h"
#include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h"
@@ -43,9 +44,7 @@ void MinecraftProfileStepMojang::onRequestDone(
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
requestor->deleteLater();
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
if (error == QNetworkReply::ContentNotFoundError) {
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
if(m_data->type == AccountType::Mojang) {
diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp
index 14bde47e..b397b734 100644
--- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp
+++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp
@@ -4,6 +4,7 @@
#include <QJsonParseError>
#include <QJsonDocument>
+#include "Logging.h"
#include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h"
@@ -58,9 +59,7 @@ void XboxAuthorizationStep::onRequestDone(
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
requestor->deleteLater();
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
if (error != QNetworkReply::NoError) {
qWarning() << "Reply error:" << error;
if (Net::isApplicationError(error)) {
diff --git a/launcher/minecraft/auth/steps/XboxProfileStep.cpp b/launcher/minecraft/auth/steps/XboxProfileStep.cpp
index 738fe1db..644c419b 100644
--- a/launcher/minecraft/auth/steps/XboxProfileStep.cpp
+++ b/launcher/minecraft/auth/steps/XboxProfileStep.cpp
@@ -3,7 +3,7 @@
#include <QNetworkRequest>
#include <QUrlQuery>
-
+#include "Logging.h"
#include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h"
@@ -56,9 +56,7 @@ void XboxProfileStep::onRequestDone(
if (error != QNetworkReply::NoError) {
qWarning() << "Reply error:" << error;
-#ifndef NDEBUG
- qDebug() << data;
-#endif
+ qCDebug(authCredentials()) << data;
if (Net::isApplicationError(error)) {
emit finished(
AccountTaskState::STATE_FAILED_SOFT,
@@ -74,9 +72,7 @@ void XboxProfileStep::onRequestDone(
return;
}
-#ifndef NDEBUG
- qDebug() << "XBox profile: " << data;
-#endif
+ qCDebug(authCredentials()) << "XBox profile: " << data;
emit finished(AccountTaskState::STATE_WORKING, tr("Got Xbox profile"));
}
diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp
index 39023f69..9cd0056c 100644
--- a/launcher/minecraft/mod/Mod.cpp
+++ b/launcher/minecraft/mod/Mod.cpp
@@ -44,6 +44,8 @@
#include "MetadataHandler.h"
#include "Version.h"
+static ModPlatform::ProviderCapabilities ProviderCaps;
+
Mod::Mod(const QFileInfo& file) : Resource(file), m_local_details()
{
m_enabled = (file.suffix() != "disabled");
@@ -91,6 +93,11 @@ std::pair<int, bool> Mod::compare(const Resource& other, SortType type) const
if (this_ver < other_ver)
return { -1, type == SortType::VERSION };
}
+ case SortType::PROVIDER: {
+ auto compare_result = QString::compare(provider().value_or("Unknown"), cast_other->provider().value_or("Unknown"), Qt::CaseInsensitive);
+ if (compare_result != 0)
+ return { compare_result, type == SortType::PROVIDER };
+ }
}
return { 0, false };
}
@@ -189,4 +196,11 @@ void Mod::finishResolvingWithDetails(ModDetails&& details)
m_local_details = std::move(details);
if (metadata)
setMetadata(std::move(metadata));
+};
+
+auto Mod::provider() const -> std::optional<QString>
+{
+ if (metadata())
+ return ProviderCaps.readableName(metadata()->provider);
+ return {};
}
diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h
index f336bec4..8185c8fc 100644
--- a/launcher/minecraft/mod/Mod.h
+++ b/launcher/minecraft/mod/Mod.h
@@ -39,6 +39,8 @@
#include <QFileInfo>
#include <QList>
+#include <optional>
+
#include "Resource.h"
#include "ModDetails.h"
@@ -61,6 +63,7 @@ public:
auto description() const -> QString;
auto authors() const -> QStringList;
auto status() const -> ModStatus;
+ auto provider() const -> std::optional<QString>;
auto metadata() -> std::shared_ptr<Metadata::ModStruct>;
auto metadata() const -> const std::shared_ptr<Metadata::ModStruct>;
diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index 4ccc5d4d..f258ad69 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -48,10 +48,11 @@
#include "minecraft/mod/tasks/LocalModParseTask.h"
#include "minecraft/mod/tasks/ModFolderLoadTask.h"
+#include "modplatform/ModIndex.h"
ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed) : ResourceFolderModel(QDir(dir)), m_is_indexed(is_indexed)
{
- m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE };
+ m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER };
}
QVariant ModFolderModel::data(const QModelIndex &index, int role) const
@@ -82,7 +83,15 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const
}
case DateColumn:
return m_resources[row]->dateTimeChanged();
+ case ProviderColumn: {
+ auto provider = at(row)->provider();
+ if (!provider.has_value()) {
+ //: Unknown mod provider (i.e. not Modrinth, CurseForge, etc...)
+ return tr("Unknown");
+ }
+ return provider.value();
+ }
default:
return QVariant();
}
@@ -118,6 +127,8 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in
return tr("Version");
case DateColumn:
return tr("Last changed");
+ case ProviderColumn:
+ return tr("Provider");
default:
return QVariant();
}
@@ -133,6 +144,8 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in
return tr("The version of the mod.");
case DateColumn:
return tr("The date and time this mod was last changed (or added).");
+ case ProviderColumn:
+ return tr("Where the mod was downloaded from.");
default:
return QVariant();
}
diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h
index 93980319..6898f6eb 100644
--- a/launcher/minecraft/mod/ModFolderModel.h
+++ b/launcher/minecraft/mod/ModFolderModel.h
@@ -67,6 +67,7 @@ public:
NameColumn,
VersionColumn,
DateColumn,
+ ProviderColumn,
NUM_COLUMNS
};
enum ModStatusAction {
diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp
index 0fbcfd7c..7c572d92 100644
--- a/launcher/minecraft/mod/Resource.cpp
+++ b/launcher/minecraft/mod/Resource.cpp
@@ -143,5 +143,9 @@ bool Resource::enable(EnableAction action)
bool Resource::destroy()
{
m_type = ResourceType::UNKNOWN;
+
+ if (FS::trash(m_file_info.filePath()))
+ return true;
+
return FS::deletePath(m_file_info.filePath());
}
diff --git a/launcher/minecraft/mod/Resource.h b/launcher/minecraft/mod/Resource.h
index f9bd811e..0c37f3a3 100644
--- a/launcher/minecraft/mod/Resource.h
+++ b/launcher/minecraft/mod/Resource.h
@@ -20,7 +20,8 @@ enum class SortType {
DATE,
VERSION,
ENABLED,
- PACK_FORMAT
+ PACK_FORMAT,
+ PROVIDER
};
enum class EnableAction {
diff --git a/launcher/ui/GuiUtil.cpp b/launcher/ui/GuiUtil.cpp
index 5a62e4d0..29467c3c 100644
--- a/launcher/ui/GuiUtil.cpp
+++ b/launcher/ui/GuiUtil.cpp
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Lenny McLennington <lenny@sneed.church>
* 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
* it under the terms of the GNU General Public License as published by
@@ -49,11 +50,34 @@
#include <DesktopServices.h>
#include <BuildConfig.h>
-QString GuiUtil::uploadPaste(const QString &text, QWidget *parentWidget)
+std::optional<QString> GuiUtil::uploadPaste(const QString &name, const QString &text, QWidget *parentWidget)
{
ProgressDialog dialog(parentWidget);
auto pasteTypeSetting = static_cast<PasteUpload::PasteType>(APPLICATION->settings()->get("PastebinType").toInt());
auto pasteCustomAPIBaseSetting = APPLICATION->settings()->get("PastebinCustomAPIBase").toString();
+
+ {
+ QUrl baseUrl;
+ if (pasteCustomAPIBaseSetting.isEmpty())
+ baseUrl = PasteUpload::PasteTypes[pasteTypeSetting].defaultBase;
+ else
+ baseUrl = pasteCustomAPIBaseSetting;
+
+ if (baseUrl.isValid())
+ {
+ auto response = CustomMessageBox::selectable(parentWidget, QObject::tr("Confirm Upload"),
+ QObject::tr("You are about to upload \"%1\" to %2.\n"
+ "You should double-check for personal information.\n\n"
+ "Are you sure?")
+ .arg(name, baseUrl.host()),
+ QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
+ ->exec();
+
+ if (response != QMessageBox::Yes)
+ return {};
+ }
+ }
+
std::unique_ptr<PasteUpload> paste(new PasteUpload(parentWidget, text, pasteCustomAPIBaseSetting, pasteTypeSetting));
dialog.execWithTask(paste.get());
diff --git a/launcher/ui/GuiUtil.h b/launcher/ui/GuiUtil.h
index 5e109383..96ebd9a2 100644
--- a/launcher/ui/GuiUtil.h
+++ b/launcher/ui/GuiUtil.h
@@ -1,10 +1,11 @@
#pragma once
#include <QWidget>
+#include <optional>
namespace GuiUtil
{
-QString uploadPaste(const QString &text, QWidget *parentWidget);
+std::optional<QString> uploadPaste(const QString &name, const QString &text, QWidget *parentWidget);
void setClipboardText(const QString &text);
QStringList BrowseForFiles(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget);
QString BrowseForFile(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget);
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp
index 3651aa15..e913849d 100644
--- a/launcher/ui/MainWindow.cpp
+++ b/launcher/ui/MainWindow.cpp
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022 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
@@ -490,7 +491,7 @@ public:
if (!BuildConfig.BUG_TRACKER_URL.isEmpty()) {
helpMenu->addAction(actionReportBug);
}
-
+
if(!BuildConfig.MATRIX_URL.isEmpty()) {
helpMenu->addAction(actionMATRIX);
}
@@ -2093,21 +2094,23 @@ void MainWindow::on_actionDeleteInstance_triggered()
auto id = m_selectedInstance->id();
- auto response =
- CustomMessageBox::selectable(this, tr("CAREFUL!"),
- tr("About to delete: %1\nThis may be permanent and will completely delete the instance.\n\nAre you sure?")
- .arg(m_selectedInstance->name()),
- QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
- ->exec();
+ auto response = CustomMessageBox::selectable(this, tr("Confirm Deletion"),
+ tr("You are about to delete \"%1\".\n"
+ "This may be permanent and will completely delete the instance.\n\n"
+ "Are you sure?")
+ .arg(m_selectedInstance->name()),
+ QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
+ ->exec();
- if (response == QMessageBox::Yes) {
- if (APPLICATION->instances()->trashInstance(id)) {
- ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething());
- return;
- }
+ if (response != QMessageBox::Yes)
+ return;
- APPLICATION->instances()->deleteInstance(id);
+ if (APPLICATION->instances()->trashInstance(id)) {
+ ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething());
+ return;
}
+
+ APPLICATION->instances()->deleteInstance(id);
}
void MainWindow::on_actionExportInstance_triggered()
@@ -2252,7 +2255,7 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered()
}
QString iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.png");
-
+
QFile iconFile(iconPath);
if (!iconFile.open(QFile::WriteOnly))
{
@@ -2261,7 +2264,7 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered()
}
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "PNG");
iconFile.close();
-
+
if (!success)
{
iconFile.remove();
@@ -2302,7 +2305,7 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered()
}
QString iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.ico");
-
+
// part of fix for weird bug involving the window icon being replaced
// dunno why it happens, but this 2-line fix seems to be enough, so w/e
auto appIcon = APPLICATION->getThemedIcon("logo");
@@ -2325,7 +2328,7 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered()
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
return;
}
-
+
if (FS::createShortcut(FS::PathCombine(desktopPath, m_selectedInstance->name()),
QApplication::applicationFilePath(), { "--launch", m_selectedInstance->id() },
m_selectedInstance->name(), iconPath)) {
diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
index c66d1368..1115ddc3 100644
--- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp
+++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
@@ -1,4 +1,5 @@
#include "ExternalResourcesPage.h"
+#include "ui/dialogs/CustomMessageBox.h"
#include "ui_ExternalResourcesPage.h"
#include "DesktopServices.h"
@@ -128,7 +129,7 @@ bool ExternalResourcesPage::eventFilter(QObject* obj, QEvent* ev)
{
if (ev->type() != QEvent::KeyPress)
return QWidget::eventFilter(obj, ev);
-
+
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(ev);
if (obj == ui->treeView)
return listFilter(keyEvent);
@@ -140,7 +141,6 @@ void ExternalResourcesPage::addItem()
{
if (!m_controlsEnabled)
return;
-
auto list = GuiUtil::BrowseForFiles(
helpPage(), tr("Select %1", "Select whatever type of files the page contains. Example: 'Loader Mods'").arg(displayName()),
@@ -157,8 +157,50 @@ void ExternalResourcesPage::removeItem()
{
if (!m_controlsEnabled)
return;
-
+
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
+
+ int count = 0;
+ bool folder = false;
+ for (auto& i : selection.indexes()) {
+ if (i.column() == 0) {
+ count++;
+
+ // if a folder is selected, show the confirmation dialog
+ if (m_model->at(i.row()).fileinfo().isDir())
+ folder = true;
+ }
+ }
+
+ QString text;
+ bool multiple = count > 1;
+
+ if (multiple) {
+ text = tr("You are about to remove %1 items.\n"
+ "This may be permanent and they will be gone from the folder.\n\n"
+ "Are you sure?")
+ .arg(count);
+ } else if (folder) {
+ text = tr("You are about to remove the folder \"%1\".\n"
+ "This may be permanent and it will be gone from the parent folder.\n\n"
+ "Are you sure?")
+ .arg(m_model->at(selection.indexes().at(0).row()).fileinfo().fileName());
+ }
+
+ if (!text.isEmpty()) {
+ auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), text, QMessageBox::Warning,
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
+ ->exec();
+
+ if (response != QMessageBox::Yes)
+ return;
+ }
+
+ removeItems(selection);
+}
+
+void ExternalResourcesPage::removeItems(const QItemSelection& selection)
+{
m_model->deleteResources(selection.indexes());
}
@@ -209,4 +251,3 @@ bool ExternalResourcesPage::onSelectionChanged(const QModelIndex& current, const
return true;
}
-
diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.h b/launcher/ui/pages/instance/ExternalResourcesPage.h
index 2d1a5b51..d17fbb7f 100644
--- a/launcher/ui/pages/instance/ExternalResourcesPage.h
+++ b/launcher/ui/pages/instance/ExternalResourcesPage.h
@@ -50,7 +50,8 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
void filterTextChanged(const QString& newContents);
virtual void addItem();
- virtual void removeItem();
+ void removeItem();
+ virtual void removeItems(const QItemSelection &selection);
virtual void enableItem();
virtual void disableItem();
diff --git a/launcher/ui/pages/instance/LogPage.cpp b/launcher/ui/pages/instance/LogPage.cpp
index 31c3e925..8f9e569e 100644
--- a/launcher/ui/pages/instance/LogPage.cpp
+++ b/launcher/ui/pages/instance/LogPage.cpp
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022 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
@@ -277,28 +278,22 @@ void LogPage::on_btnPaste_clicked()
//FIXME: turn this into a proper task and move the upload logic out of GuiUtil!
m_model->append(
MessageLevel::Launcher,
- QString("%2: Log upload triggered at: %1").arg(
- QDateTime::currentDateTime().toString(Qt::RFC2822Date),
- BuildConfig.LAUNCHER_DISPLAYNAME
+ QString("Log upload triggered at: %1").arg(
+ QDateTime::currentDateTime().toString(Qt::RFC2822Date)
)
);
- auto url = GuiUtil::uploadPaste(m_model->toPlainText(), this);
- if(!url.isEmpty())
+ auto url = GuiUtil::uploadPaste(tr("Minecraft Log"), m_model->toPlainText(), this);
+ if(!url.has_value())
{
- m_model->append(
- MessageLevel::Launcher,
- QString("%2: Log uploaded to: %1").arg(
- url,
- BuildConfig.LAUNCHER_DISPLAYNAME
- )
- );
+ m_model->append(MessageLevel::Error, QString("Log upload canceled"));
+ }
+ else if (url->isNull())
+ {
+ m_model->append(MessageLevel::Error, QString("Log upload failed!"));
}
else
{
- m_model->append(
- MessageLevel::Error,
- QString("%1: Log upload failed!").arg(BuildConfig.LAUNCHER_DISPLAYNAME)
- );
+ m_model->append(MessageLevel::Launcher, QString("Log uploaded to: %1").arg(url.value()));
}
}
diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp
index 0a2e6155..627e71e5 100644
--- a/launcher/ui/pages/instance/ModFolderPage.cpp
+++ b/launcher/ui/pages/instance/ModFolderPage.cpp
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022 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
@@ -139,13 +140,8 @@ bool ModFolderPage::onSelectionChanged(const QModelIndex& current, const QModelI
return true;
}
-void ModFolderPage::removeItem()
+void ModFolderPage::removeItems(const QItemSelection &selection)
{
-
- if (!m_controlsEnabled)
- return;
-
- auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
m_model->deleteMods(selection.indexes());
}
diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h
index f20adf34..ff58b38a 100644
--- a/launcher/ui/pages/instance/ModFolderPage.h
+++ b/launcher/ui/pages/instance/ModFolderPage.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) 2022 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
@@ -59,7 +60,7 @@ class ModFolderPage : public ExternalResourcesPage {
private slots:
void runningStateChanged(bool running);
- void removeItem() override;
+ void removeItems(const QItemSelection &selection) override;
void installMods();
void updateMods();
diff --git a/launcher/ui/pages/instance/OtherLogsPage.cpp b/launcher/ui/pages/instance/OtherLogsPage.cpp
index 0c1939c6..bbdd7324 100644
--- a/launcher/ui/pages/instance/OtherLogsPage.cpp
+++ b/launcher/ui/pages/instance/OtherLogsPage.cpp
@@ -1,7 +1,8 @@
// 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 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
@@ -204,7 +205,7 @@ void OtherLogsPage::on_btnReload_clicked()
void OtherLogsPage::on_btnPaste_clicked()
{
- GuiUtil::uploadPaste(ui->text->toPlainText(), this);
+ GuiUtil::uploadPaste(m_currentFile, ui->text->toPlainText(), this);
}
void OtherLogsPage::on_btnCopy_clicked()
@@ -219,13 +220,21 @@ void OtherLogsPage::on_btnDelete_clicked()
setControlsEnabled(false);
return;
}
- if (QMessageBox::question(this, tr("Delete"),
- tr("Do you really want to delete %1?").arg(m_currentFile),
- QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
- {
+ if (QMessageBox::question(this, tr("Confirm Deletion"),
+ tr("You are about to delete \"%1\".\n"
+ "This may be permanent and it will be gone from the logs folder.\n\n"
+ "Are you sure?")
+ .arg(m_currentFile),
+ QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) {
return;
}
QFile file(FS::PathCombine(m_path, m_currentFile));
+
+ if (FS::trash(file.fileName()))
+ {
+ return;
+ }
+
if (!file.remove())
{
QMessageBox::critical(this, tr("Error"), tr("Unable to delete %1: %2")
@@ -243,15 +252,15 @@ void OtherLogsPage::on_btnClean_clicked()
return;
}
QMessageBox *messageBox = new QMessageBox(this);
- messageBox->setWindowTitle(tr("Clean up"));
+ messageBox->setWindowTitle(tr("Confirm Cleanup"));
if(toDelete.size() > 5)
{
- messageBox->setText(tr("Do you really want to delete all log files?"));
+ messageBox->setText(tr("Are you sure you want to delete all log files?"));
messageBox->setDetailedText(toDelete.join('\n'));
}
else
{
- messageBox->setText(tr("Do you really want to delete these files?\n%1").arg(toDelete.join('\n')));
+ messageBox->setText(tr("Are you sure you want to delete all these files?\n%1").arg(toDelete.join('\n')));
}
messageBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
messageBox->setDefaultButton(QMessageBox::Ok);
@@ -267,6 +276,10 @@ void OtherLogsPage::on_btnClean_clicked()
for(auto item: toDelete)
{
QFile file(FS::PathCombine(m_path, item));
+ if (FS::trash(file.fileName()))
+ {
+ continue;
+ }
if (!file.remove())
{
failed.push_back(item);
diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp
index 0092aef3..ca368d3b 100644
--- a/launcher/ui/pages/instance/ScreenshotsPage.cpp
+++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022 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
@@ -379,6 +380,24 @@ void ScreenshotsPage::on_actionUpload_triggered()
if (selection.isEmpty())
return;
+
+ QString text;
+ if (selection.size() > 1)
+ text = tr("You are about to upload %1 screenshots.\n\n"
+ "Are you sure?")
+ .arg(selection.size());
+ else
+ text =
+ tr("You are about to upload the selected screenshot.\n\n"
+ "Are you sure?");
+
+ auto response = CustomMessageBox::selectable(this, "Confirm Upload", text, QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No,
+ QMessageBox::No)
+ ->exec();
+
+ if (response != QMessageBox::Yes)
+ return;
+
QList<ScreenShot::Ptr> uploaded;
auto job = NetJob::Ptr(new NetJob("Screenshot Upload", APPLICATION->network()));
if(selection.size() < 2)
@@ -491,17 +510,32 @@ void ScreenshotsPage::on_actionCopy_File_s_triggered()
void ScreenshotsPage::on_actionDelete_triggered()
{
- auto mbox = CustomMessageBox::selectable(
- this, tr("Are you sure?"), tr("This will delete all selected screenshots."),
- QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No);
- std::unique_ptr<QMessageBox> box(mbox);
+ auto selected = ui->listView->selectionModel()->selectedIndexes();
+
+ int count = ui->listView->selectionModel()->selectedRows().size();
+ QString text;
+ if (count > 1)
+ text = tr("You are about to delete %1 screenshots.\n"
+ "This may be permanent and they will be gone from the folder.\n\n"
+ "Are you sure?")
+ .arg(count);
+ else
+ text = tr("You are about to delete the selected screenshot.\n"
+ "This may be permanent and it will be gone from the folder.\n\n"
+ "Are you sure?")
+ .arg(count);
- if (box->exec() != QMessageBox::Yes)
+ auto response =
+ CustomMessageBox::selectable(this, tr("Confirm Deletion"), text, QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No)->exec();
+
+ if (response != QMessageBox::Yes)
return;
- auto selected = ui->listView->selectionModel()->selectedIndexes();
for (auto item : selected)
{
+ if (FS::trash(m_model->filePath(item)))
+ continue;
+
m_model->remove(item);
}
}
diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp
index a625e20b..6f8591a1 100644
--- a/launcher/ui/pages/instance/ServersPage.cpp
+++ b/launcher/ui/pages/instance/ServersPage.cpp
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022 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
@@ -35,6 +36,7 @@
*/
#include "ServersPage.h"
+#include "ui/dialogs/CustomMessageBox.h"
#include "ui_ServersPage.h"
#include <FileSystem.h>
@@ -799,6 +801,17 @@ void ServersPage::on_actionAdd_triggered()
void ServersPage::on_actionRemove_triggered()
{
+ auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"),
+ tr("You are about to remove \"%1\".\n"
+ "This is permanent and the server will be gone from your list forever (A LONG TIME).\n\n"
+ "Are you sure?")
+ .arg(m_model->at(currentServer)->m_name),
+ QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
+ ->exec();
+
+ if (response != QMessageBox::Yes)
+ return;
+
m_model->removeRow(currentServer);
}
diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp
index c8a65f10..d200652a 100644
--- a/launcher/ui/pages/instance/VersionPage.cpp
+++ b/launcher/ui/pages/instance/VersionPage.cpp
@@ -318,13 +318,29 @@ void VersionPage::on_actionReload_triggered()
void VersionPage::on_actionRemove_triggered()
{
- if (ui->packageView->currentIndex().isValid())
+ if (!ui->packageView->currentIndex().isValid())
{
- // FIXME: use actual model, not reloading.
- if (!m_profile->remove(ui->packageView->currentIndex().row()))
- {
- QMessageBox::critical(this, tr("Error"), tr("Couldn't remove file"));
- }
+ return;
+ }
+ int index = ui->packageView->currentIndex().row();
+ auto component = m_profile->getComponent(index);
+ if (component->isCustom())
+ {
+ auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"),
+ tr("You are about to remove \"%1\".\n"
+ "This is permanent and will completely remove the custom component.\n\n"
+ "Are you sure?")
+ .arg(component->getName()),
+ QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
+ ->exec();
+
+ if (response != QMessageBox::Yes)
+ return;
+ }
+ // FIXME: use actual model, not reloading.
+ if (!m_profile->remove(index))
+ {
+ QMessageBox::critical(this, tr("Error"), tr("Couldn't remove file"));
}
updateButtons();
reloadPackProfile();
@@ -707,6 +723,19 @@ void VersionPage::on_actionRevert_triggered()
{
return;
}
+ auto component = m_profile->getComponent(version);
+
+ auto response = CustomMessageBox::selectable(this, tr("Confirm Reversion"),
+ tr("You are about to revert \"%1\".\n"
+ "This is permanent and will completely revert your customizations.\n\n"
+ "Are you sure?")
+ .arg(component->getName()),
+ QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
+ ->exec();
+
+ if (response != QMessageBox::Yes)
+ return;
+
if(!m_profile->revertToBase(version))
{
// TODO: some error box here
diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp
index 93458ce4..0020c461 100644
--- a/launcher/ui/pages/instance/WorldListPage.cpp
+++ b/launcher/ui/pages/instance/WorldListPage.cpp
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
- * PolyMC - Minecraft Launcher
+ * Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022 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
@@ -35,6 +36,7 @@
*/
#include "WorldListPage.h"
+#include "ui/dialogs/CustomMessageBox.h"
#include "ui_WorldListPage.h"
#include "minecraft/WorldList.h"
@@ -192,12 +194,14 @@ void WorldListPage::on_actionRemove_triggered()
if(!proxiedIndex.isValid())
return;
- auto result = QMessageBox::question(this,
- tr("Are you sure?"),
- tr("This will remove the selected world permenantly.\n"
- "The world will be gone forever (A LONG TIME).\n"
- "\n"
- "Do you want to continue?"));
+ auto result = CustomMessageBox::selectable(this, tr("Confirm Deletion"),
+ tr("You are about to delete \"%1\".\n"
+ "The world may be gone forever (A LONG TIME).\n\n"
+ "Are you sure?")
+ .arg(m_worlds->allWorlds().at(proxiedIndex.row()).name()),
+ QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
+ ->exec();
+
if(result != QMessageBox::Yes)
{
return;
diff --git a/launcher/ui/pages/instance/WorldListPage.ui b/launcher/ui/pages/instance/WorldListPage.ui
index 7c68bfae..d74dd079 100644
--- a/launcher/ui/pages/instance/WorldListPage.ui
+++ b/launcher/ui/pages/instance/WorldListPage.ui
@@ -109,7 +109,7 @@
</action>
<action name="actionRemove">
<property name="text">
- <string>Remove</string>
+ <string>Delete</string>
</property>
</action>
<action name="actionMCEdit">
diff --git a/launcher/ui/widgets/ModListView.cpp b/launcher/ui/widgets/ModListView.cpp
index d1860f57..09b03a76 100644
--- a/launcher/ui/widgets/ModListView.cpp
+++ b/launcher/ui/widgets/ModListView.cpp
@@ -14,6 +14,9 @@
*/
#include "ModListView.h"
+
+#include "minecraft/mod/ModFolderModel.h"
+
#include <QHeaderView>
#include <QMouseEvent>
#include <QPainter>
@@ -62,4 +65,17 @@ void ModListView::setModel ( QAbstractItemModel* model )
for(int i = 1; i < head->count(); i++)
head->setSectionResizeMode(i, QHeaderView::ResizeToContents);
}
+
+ auto real_model = model;
+ if (auto proxy_model = dynamic_cast<QSortFilterProxyModel*>(model); proxy_model)
+ real_model = proxy_model->sourceModel();
+
+ if (auto mod_model = dynamic_cast<ModFolderModel*>(real_model); mod_model) {
+ connect(mod_model, &ModFolderModel::updateFinished, this, [this, mod_model]{
+ auto mods = mod_model->allMods();
+ // Hide the 'Provider' column if no mod has a defined provider!
+ setColumnHidden(ModFolderModel::Columns::ProviderColumn,
+ std::none_of(mods.constBegin(), mods.constEnd(), [](auto const mod){ return mod->provider().has_value(); }));
+ });
+ }
}
diff --git a/libraries/katabasis/CMakeLists.txt b/libraries/katabasis/CMakeLists.txt
index f764feb6..643244ed 100644
--- a/libraries/katabasis/CMakeLists.txt
+++ b/libraries/katabasis/CMakeLists.txt
@@ -38,6 +38,15 @@ set( katabasis_PUBLIC
include/katabasis/RequestParameter.h
)
+ecm_qt_declare_logging_category(katabasis_PRIVATE
+ HEADER KatabasisLogging.h # NOTE: this won't be in src/, but CMAKE_BINARY_DIR/src isn't included by default so this should be fine
+ IDENTIFIER katabasisCredentials
+ CATEGORY_NAME "katabasis.credentials"
+ DEFAULT_SEVERITY Warning
+ DESCRIPTION "Secrets and credentials from Katabasis"
+ EXPORT "Katabasis"
+)
+
add_library( Katabasis STATIC ${katabasis_PRIVATE} ${katabasis_PUBLIC} )
target_link_libraries(Katabasis Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network)
diff --git a/libraries/katabasis/include/katabasis/DeviceFlow.h b/libraries/katabasis/include/katabasis/DeviceFlow.h
index b68c92e0..0401df3c 100644
--- a/libraries/katabasis/include/katabasis/DeviceFlow.h
+++ b/libraries/katabasis/include/katabasis/DeviceFlow.h
@@ -1,5 +1,6 @@
#pragma once
+#include <QLoggingCategory>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
diff --git a/libraries/katabasis/src/DeviceFlow.cpp b/libraries/katabasis/src/DeviceFlow.cpp
index f78fd620..f49fcb7d 100644
--- a/libraries/katabasis/src/DeviceFlow.cpp
+++ b/libraries/katabasis/src/DeviceFlow.cpp
@@ -19,9 +19,11 @@
#include "katabasis/PollServer.h"
#include "katabasis/Globals.h"
+#include "KatabasisLogging.h"
#include "JsonResponse.h"
namespace {
+
// ref: https://tools.ietf.org/html/rfc8628#section-3.2
// Exception: Google sign-in uses "verification_url" instead of "*_uri" - we'll accept both.
bool hasMandatoryDeviceAuthParams(const QVariantMap& params)
@@ -333,9 +335,7 @@ QString DeviceFlow::refreshToken() {
}
void DeviceFlow::setRefreshToken(const QString &v) {
-#ifndef NDEBUG
- qDebug() << "DeviceFlow::setRefreshToken" << v << "...";
-#endif
+ qCDebug(katabasisCredentials) << "new refresh token:" << v;
token_.refresh_token = v;
}
diff --git a/program_info/org.prismlauncher.PrismLauncher.metainfo.xml.in b/program_info/org.prismlauncher.PrismLauncher.metainfo.xml.in
index 13a860d9..96708960 100644
--- a/program_info/org.prismlauncher.PrismLauncher.metainfo.xml.in
+++ b/program_info/org.prismlauncher.PrismLauncher.metainfo.xml.in
@@ -19,38 +19,49 @@
<p>Features:</p>
<ul>
<li>Easily install game modifications, such as Fabric, Forge and Quilt</li>
- <li>Control your Java settings</li>
+ <li>Easily install and update modpacks from the Launcher</li>
+ <li>Control your Java settings, and enable Mangohud or Gamemode with a toggle</li>
<li>Manage worlds and resource packs from the launcher</li>
- <li>See logs and other details easily</li>
+ <li>See logs and other details easily through a dashboard</li>
<li>Kill Minecraft in case of a crash/freeze</li>
<li>Isolate Minecraft instances to keep everything clean</li>
<li>Install and update mods directly from the launcher</li>
+ <li>Customize the launcher with themes, and more</li>
+ <li>And cat :3</li>
</ul>
</description>
<screenshots>
<screenshot type="default">
<caption>The main Prism Launcher window</caption>
- <image type="source" width="976" height="764">https://prismlauncher.org/img/screenshots/LauncherDark.png</image>
+ <image type="source" width="1030" height="764">https://prismlauncher.org/img/screenshots/LauncherDark.png</image>
</screenshot>
<screenshot>
<caption>Modpack installation</caption>
- <image type="source" width="1103" height="954">https://prismlauncher.org/img/screenshots/ModpackInstallDark.png</image>
+ <image type="source" width="1126" height="850">https://prismlauncher.org/img/screenshots/ModpackInstallDark.png</image>
+ </screenshot>
+ <screenshot>
+ <caption>Modpack updating</caption>
+ <image type="source" width="930" height="677">https://prismlauncher.org/img/screenshots/ModpackUpdateDark.png</image>
</screenshot>
<screenshot>
<caption>Mod installation</caption>
- <image type="source" width="1036" height="700">https://prismlauncher.org/img/screenshots/ModInstallDark.png</image>
+ <image type="source" width="848" height="558">https://prismlauncher.org/img/screenshots/ModInstallDark.png</image>
</screenshot>
<screenshot>
<caption>Mod updating</caption>
- <image type="source" width="930" height="858">https://prismlauncher.org/img/screenshots/ModUpdateDark.png</image>
+ <image type="source" width="860" height="748">https://prismlauncher.org/img/screenshots/ModUpdateDark.png</image>
</screenshot>
<screenshot>
<caption>Instance management</caption>
- <image type="source" width="1083" height="735">https://prismlauncher.org/img/screenshots/PropertiesDark.png</image>
+ <image type="source" width="960" height="659">https://prismlauncher.org/img/screenshots/PropertiesDark.png</image>
+ </screenshot>
+ <screenshot>
+ <caption>Cat :3</caption>
+ <image type="source" width="1042" height="754">https://prismlauncher.org/img/screenshots/LauncherCatDark.png</image>
</screenshot>
<screenshot>
- <caption>Cat :)</caption>
- <image type="source" width="931" height="759">https://prismlauncher.org/img/screenshots/LauncherCatDark.png</image>
+ <caption>Customization</caption>
+ <image type="source" width="1040" height="752">https://prismlauncher.org/img/screenshots/CustomizeDark.png</image>
</screenshot>
</screenshots>
<releases>