Qt: Add 'Clear Cheats' option to cheats page

This commit is contained in:
Stenzek 2024-11-03 17:57:58 +10:00
parent 0fc719c4cf
commit d416ecb324
No known key found for this signature in database
6 changed files with 89 additions and 11 deletions

View File

@ -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())

View File

@ -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:

View File

@ -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">

View File

@ -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)

View File

@ -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);

View File

@ -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;
}; };