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 "common/error.h"
#include "common/log.h"
#include "common/string_util.h"
#include "fmt/format.h"
@ -20,6 +21,8 @@
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QStyledItemDelegate>
LOG_CHANNEL(Cheats);
namespace {
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.importCheats, &QPushButton::clicked, this, &GameCheatSettingsWidget::onImportClicked);
connect(m_ui.exportCheats, &QPushButton::clicked, this, &GameCheatSettingsWidget::onExportClicked);
connect(m_ui.clearCheats, &QPushButton::clicked, this, &GameCheatSettingsWidget::onClearClicked);
}
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)
{
if (parent.empty())

View File

@ -55,6 +55,7 @@ private Q_SLOTS:
void onImportFromFileTriggered();
void onImportFromTextTriggered();
void onExportClicked();
void onClearClicked();
void reloadList();
private:

View File

@ -146,6 +146,22 @@
</property>
</spacer>
</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>
<widget class="QPushButton" name="importCheats">
<property name="text">

View File

@ -218,8 +218,7 @@ void GameSummaryWidget::populateCustomAttributes()
void GameSummaryWidget::updateWindowTitle()
{
const QString window_title = tr("%1 [%2]").arg(m_ui.title->text()).arg(m_ui.serial->text());
m_dialog->setWindowTitle(window_title);
m_dialog->setGameTitle(m_ui.title->text().toStdString());
}
void GameSummaryWidget::setCustomTitle(const std::string& text)

View File

@ -48,14 +48,17 @@ SettingsWindow::SettingsWindow() : QWidget()
connectUi();
}
SettingsWindow::SettingsWindow(const std::string& path, std::string serial, GameHash hash, DiscRegion region,
const GameDatabase::Entry* entry, std::unique_ptr<INISettingsInterface> sif)
: QWidget(), m_sif(std::move(sif)), m_database_entry(entry), m_serial(serial), m_hash(hash)
SettingsWindow::SettingsWindow(const std::string& path, std::string title, std::string serial, GameHash hash,
DiscRegion region, const GameDatabase::Entry* entry,
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);
setGameTitle(std::move(title));
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("<strong>Summary</strong><hr>This page shows information about the selected game, and allows you to "
"validate your disc was dumped correctly."));
@ -655,14 +658,22 @@ void SettingsWindow::saveAndReloadGameSettings()
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)
{
return (m_database_entry && m_database_entry->HasTrait(trait) &&
m_sif->GetBoolValue("Main", "ApplyCompatibilitySettings", true));
}
SettingsWindow* SettingsWindow::openGamePropertiesDialog(const std::string& path, const std::string& title,
std::string serial, GameHash hash, DiscRegion region,
SettingsWindow* SettingsWindow::openGamePropertiesDialog(const std::string& path, std::string title, std::string serial,
GameHash hash, DiscRegion region,
const char* category /* = nullptr */)
{
const GameDatabase::Entry* dentry = nullptr;
@ -706,7 +717,8 @@ SettingsWindow* SettingsWindow::openGamePropertiesDialog(const std::string& path
if (FileSystem::FileExists(sif->GetFileName().c_str()))
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();
if (category)
dialog->setCategory(category);

View File

@ -45,11 +45,11 @@ class SettingsWindow final : public QWidget
public:
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);
~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);
static void closeGamePropertiesDialogs();
@ -60,6 +60,7 @@ public:
ALWAYS_INLINE bool isPerGameSettings() const { return static_cast<bool>(m_sif); }
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::optional<GameHash>& getGameHash() const { return m_hash; }
@ -100,6 +101,7 @@ public:
void removeSettingValue(const char* section, const char* key);
void saveAndReloadGameSettings();
void setGameTitle(std::string title);
bool hasGameTrait(GameDatabase::Trait trait);
Q_SIGNALS:
@ -158,6 +160,7 @@ private:
QObject* m_current_help_widget = nullptr;
QMap<QObject*, QString> m_widget_help_text_map;
std::string m_title;
std::string m_serial;
std::optional<GameHash> m_hash;
};