mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-07 20:15:32 +00:00
Qt: Add 'Clear Cheats' option to cheats page
This commit is contained in:
parent
0fc719c4cf
commit
d416ecb324
@ -11,6 +11,7 @@
|
|||||||
#include "core/cheats.h"
|
#include "core/cheats.h"
|
||||||
|
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
|
#include "common/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
@ -20,6 +21,8 @@
|
|||||||
#include <QtWidgets/QInputDialog>
|
#include <QtWidgets/QInputDialog>
|
||||||
#include <QtWidgets/QStyledItemDelegate>
|
#include <QtWidgets/QStyledItemDelegate>
|
||||||
|
|
||||||
|
LOG_CHANNEL(Cheats);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class CheatListOptionDelegate : public QStyledItemDelegate
|
class CheatListOptionDelegate : public QStyledItemDelegate
|
||||||
{
|
{
|
||||||
@ -195,6 +198,7 @@ GameCheatSettingsWidget::GameCheatSettingsWidget(SettingsWindow* dialog, QWidget
|
|||||||
connect(m_ui.reloadCheats, &QToolButton::clicked, this, &GameCheatSettingsWidget::onReloadClicked);
|
connect(m_ui.reloadCheats, &QToolButton::clicked, this, &GameCheatSettingsWidget::onReloadClicked);
|
||||||
connect(m_ui.importCheats, &QPushButton::clicked, this, &GameCheatSettingsWidget::onImportClicked);
|
connect(m_ui.importCheats, &QPushButton::clicked, this, &GameCheatSettingsWidget::onImportClicked);
|
||||||
connect(m_ui.exportCheats, &QPushButton::clicked, this, &GameCheatSettingsWidget::onExportClicked);
|
connect(m_ui.exportCheats, &QPushButton::clicked, this, &GameCheatSettingsWidget::onExportClicked);
|
||||||
|
connect(m_ui.clearCheats, &QPushButton::clicked, this, &GameCheatSettingsWidget::onClearClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameCheatSettingsWidget::~GameCheatSettingsWidget() = default;
|
GameCheatSettingsWidget::~GameCheatSettingsWidget() = default;
|
||||||
@ -578,6 +582,49 @@ void GameCheatSettingsWidget::onExportClicked()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameCheatSettingsWidget::onClearClicked()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, tr("Confirm Removal"),
|
||||||
|
tr("You are removing all cheats manually added for this game. This action cannot be "
|
||||||
|
"reversed.\n\nAny database cheats will still be loaded and present unless you uncheck "
|
||||||
|
"the \"Load Database Cheats\" option.\n\nAre you sure you want to continue?")) !=
|
||||||
|
QMessageBox::Yes)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
disableAllCheats();
|
||||||
|
|
||||||
|
Error error;
|
||||||
|
std::string path = Cheats::GetChtFilename(m_dialog->getGameSerial(), std::nullopt, true);
|
||||||
|
if (FileSystem::FileExists(path.c_str()))
|
||||||
|
{
|
||||||
|
if (!FileSystem::DeleteFile(path.c_str(), &error))
|
||||||
|
ERROR_LOG("Failed to remove cht file '{}': {}", Path::GetFileName(path), error.GetDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for a non-hashed path and remove that too
|
||||||
|
path = Cheats::GetChtFilename(m_dialog->getGameSerial(), m_dialog->getGameHash(), true);
|
||||||
|
if (FileSystem::FileExists(path.c_str()))
|
||||||
|
{
|
||||||
|
if (!FileSystem::DeleteFile(path.c_str(), &error))
|
||||||
|
ERROR_LOG("Failed to remove cht file '{}': {}", Path::GetFileName(path), error.GetDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
// and a legacy cht file with the game title
|
||||||
|
if (const std::string& title = m_dialog->getGameTitle(); !title.empty())
|
||||||
|
{
|
||||||
|
path = Path::Combine(EmuFolders::Cheats, Path::SanitizeFileName(title));
|
||||||
|
if (FileSystem::FileExists(path.c_str()))
|
||||||
|
{
|
||||||
|
if (!FileSystem::DeleteFile(path.c_str(), &error))
|
||||||
|
ERROR_LOG("Failed to remove cht file '{}': {}", Path::GetFileName(path), error.GetDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadList();
|
||||||
|
}
|
||||||
|
|
||||||
QTreeWidgetItem* GameCheatSettingsWidget::getTreeWidgetParent(const std::string_view parent)
|
QTreeWidgetItem* GameCheatSettingsWidget::getTreeWidgetParent(const std::string_view parent)
|
||||||
{
|
{
|
||||||
if (parent.empty())
|
if (parent.empty())
|
||||||
|
@ -55,6 +55,7 @@ private Q_SLOTS:
|
|||||||
void onImportFromFileTriggered();
|
void onImportFromFileTriggered();
|
||||||
void onImportFromTextTriggered();
|
void onImportFromTextTriggered();
|
||||||
void onExportClicked();
|
void onExportClicked();
|
||||||
|
void onClearClicked();
|
||||||
void reloadList();
|
void reloadList();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -146,6 +146,22 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="clearCheats">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear List</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="trash-fill"/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="importCheats">
|
<widget class="QPushButton" name="importCheats">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -218,8 +218,7 @@ void GameSummaryWidget::populateCustomAttributes()
|
|||||||
|
|
||||||
void GameSummaryWidget::updateWindowTitle()
|
void GameSummaryWidget::updateWindowTitle()
|
||||||
{
|
{
|
||||||
const QString window_title = tr("%1 [%2]").arg(m_ui.title->text()).arg(m_ui.serial->text());
|
m_dialog->setGameTitle(m_ui.title->text().toStdString());
|
||||||
m_dialog->setWindowTitle(window_title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameSummaryWidget::setCustomTitle(const std::string& text)
|
void GameSummaryWidget::setCustomTitle(const std::string& text)
|
||||||
|
@ -48,14 +48,17 @@ SettingsWindow::SettingsWindow() : QWidget()
|
|||||||
connectUi();
|
connectUi();
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsWindow::SettingsWindow(const std::string& path, std::string serial, GameHash hash, DiscRegion region,
|
SettingsWindow::SettingsWindow(const std::string& path, std::string title, std::string serial, GameHash hash,
|
||||||
const GameDatabase::Entry* entry, std::unique_ptr<INISettingsInterface> sif)
|
DiscRegion region, const GameDatabase::Entry* entry,
|
||||||
: QWidget(), m_sif(std::move(sif)), m_database_entry(entry), m_serial(serial), m_hash(hash)
|
std::unique_ptr<INISettingsInterface> sif)
|
||||||
|
: QWidget(), m_sif(std::move(sif)), m_database_entry(entry), m_title(std::move(title)), m_serial(std::move(serial)),
|
||||||
|
m_hash(hash)
|
||||||
{
|
{
|
||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
|
setGameTitle(std::move(title));
|
||||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
addWidget(m_game_summary = new GameSummaryWidget(path, serial, region, entry, this, m_ui.settingsContainer),
|
addWidget(m_game_summary = new GameSummaryWidget(path, m_serial, region, entry, this, m_ui.settingsContainer),
|
||||||
tr("Summary"), QStringLiteral("file-list-line"),
|
tr("Summary"), QStringLiteral("file-list-line"),
|
||||||
tr("<strong>Summary</strong><hr>This page shows information about the selected game, and allows you to "
|
tr("<strong>Summary</strong><hr>This page shows information about the selected game, and allows you to "
|
||||||
"validate your disc was dumped correctly."));
|
"validate your disc was dumped correctly."));
|
||||||
@ -655,14 +658,22 @@ void SettingsWindow::saveAndReloadGameSettings()
|
|||||||
g_emu_thread->reloadGameSettings(false);
|
g_emu_thread->reloadGameSettings(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsWindow::setGameTitle(std::string title)
|
||||||
|
{
|
||||||
|
m_title = std::move(title);
|
||||||
|
|
||||||
|
const QString window_title = tr("%1 [%2]").arg(QString::fromStdString(m_title)).arg(QString::fromStdString(m_serial));
|
||||||
|
setWindowTitle(window_title);
|
||||||
|
}
|
||||||
|
|
||||||
bool SettingsWindow::hasGameTrait(GameDatabase::Trait trait)
|
bool SettingsWindow::hasGameTrait(GameDatabase::Trait trait)
|
||||||
{
|
{
|
||||||
return (m_database_entry && m_database_entry->HasTrait(trait) &&
|
return (m_database_entry && m_database_entry->HasTrait(trait) &&
|
||||||
m_sif->GetBoolValue("Main", "ApplyCompatibilitySettings", true));
|
m_sif->GetBoolValue("Main", "ApplyCompatibilitySettings", true));
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsWindow* SettingsWindow::openGamePropertiesDialog(const std::string& path, const std::string& title,
|
SettingsWindow* SettingsWindow::openGamePropertiesDialog(const std::string& path, std::string title, std::string serial,
|
||||||
std::string serial, GameHash hash, DiscRegion region,
|
GameHash hash, DiscRegion region,
|
||||||
const char* category /* = nullptr */)
|
const char* category /* = nullptr */)
|
||||||
{
|
{
|
||||||
const GameDatabase::Entry* dentry = nullptr;
|
const GameDatabase::Entry* dentry = nullptr;
|
||||||
@ -706,7 +717,8 @@ SettingsWindow* SettingsWindow::openGamePropertiesDialog(const std::string& path
|
|||||||
if (FileSystem::FileExists(sif->GetFileName().c_str()))
|
if (FileSystem::FileExists(sif->GetFileName().c_str()))
|
||||||
sif->Load();
|
sif->Load();
|
||||||
|
|
||||||
SettingsWindow* dialog = new SettingsWindow(path, std::move(real_serial), hash, region, dentry, std::move(sif));
|
SettingsWindow* dialog =
|
||||||
|
new SettingsWindow(path, std::move(title), std::move(real_serial), hash, region, dentry, std::move(sif));
|
||||||
dialog->show();
|
dialog->show();
|
||||||
if (category)
|
if (category)
|
||||||
dialog->setCategory(category);
|
dialog->setCategory(category);
|
||||||
|
@ -45,11 +45,11 @@ class SettingsWindow final : public QWidget
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
SettingsWindow();
|
SettingsWindow();
|
||||||
SettingsWindow(const std::string& path, std::string serial, GameHash hash, DiscRegion region,
|
SettingsWindow(const std::string& path, std::string title, std::string serial, GameHash hash, DiscRegion region,
|
||||||
const GameDatabase::Entry* entry, std::unique_ptr<INISettingsInterface> sif);
|
const GameDatabase::Entry* entry, std::unique_ptr<INISettingsInterface> sif);
|
||||||
~SettingsWindow();
|
~SettingsWindow();
|
||||||
|
|
||||||
static SettingsWindow* openGamePropertiesDialog(const std::string& path, const std::string& title, std::string serial,
|
static SettingsWindow* openGamePropertiesDialog(const std::string& path, std::string title, std::string serial,
|
||||||
GameHash hash, DiscRegion region, const char* category = nullptr);
|
GameHash hash, DiscRegion region, const char* category = nullptr);
|
||||||
static void closeGamePropertiesDialogs();
|
static void closeGamePropertiesDialogs();
|
||||||
|
|
||||||
@ -60,6 +60,7 @@ public:
|
|||||||
|
|
||||||
ALWAYS_INLINE bool isPerGameSettings() const { return static_cast<bool>(m_sif); }
|
ALWAYS_INLINE bool isPerGameSettings() const { return static_cast<bool>(m_sif); }
|
||||||
ALWAYS_INLINE INISettingsInterface* getSettingsInterface() const { return m_sif.get(); }
|
ALWAYS_INLINE INISettingsInterface* getSettingsInterface() const { return m_sif.get(); }
|
||||||
|
ALWAYS_INLINE const std::string& getGameTitle() const { return m_title; }
|
||||||
ALWAYS_INLINE const std::string& getGameSerial() const { return m_serial; }
|
ALWAYS_INLINE const std::string& getGameSerial() const { return m_serial; }
|
||||||
ALWAYS_INLINE const std::optional<GameHash>& getGameHash() const { return m_hash; }
|
ALWAYS_INLINE const std::optional<GameHash>& getGameHash() const { return m_hash; }
|
||||||
|
|
||||||
@ -100,6 +101,7 @@ public:
|
|||||||
void removeSettingValue(const char* section, const char* key);
|
void removeSettingValue(const char* section, const char* key);
|
||||||
void saveAndReloadGameSettings();
|
void saveAndReloadGameSettings();
|
||||||
|
|
||||||
|
void setGameTitle(std::string title);
|
||||||
bool hasGameTrait(GameDatabase::Trait trait);
|
bool hasGameTrait(GameDatabase::Trait trait);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
@ -158,6 +160,7 @@ private:
|
|||||||
QObject* m_current_help_widget = nullptr;
|
QObject* m_current_help_widget = nullptr;
|
||||||
QMap<QObject*, QString> m_widget_help_text_map;
|
QMap<QObject*, QString> m_widget_help_text_map;
|
||||||
|
|
||||||
|
std::string m_title;
|
||||||
std::string m_serial;
|
std::string m_serial;
|
||||||
std::optional<GameHash> m_hash;
|
std::optional<GameHash> m_hash;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user