diff --git a/Source/Core/Core/ActionReplay.cpp b/Source/Core/Core/ActionReplay.cpp index 59dfecdf0b3f..e56f25fffb20 100644 --- a/Source/Core/Core/ActionReplay.cpp +++ b/Source/Core/Core/ActionReplay.cpp @@ -284,7 +284,7 @@ std::vector LoadCodes(const IniFile& global_ini, const IniFile& local_in return codes; } -void SaveCodes(IniFile* local_ini, const std::vector& codes) +void SaveCodes(IniFile& local_ini, const std::vector& codes) { std::vector lines; std::vector enabled_lines; @@ -302,8 +302,8 @@ void SaveCodes(IniFile* local_ini, const std::vector& codes) } } } - local_ini->SetLines("ActionReplay_Enabled", enabled_lines); - local_ini->SetLines("ActionReplay", lines); + local_ini.SetLines("ActionReplay_Enabled", enabled_lines); + local_ini.SetLines("ActionReplay", lines); } static void VLogInfo(std::string_view format, fmt::format_args args) diff --git a/Source/Core/Core/ActionReplay.h b/Source/Core/Core/ActionReplay.h index b42e2f08b066..fc7ac80f0190 100644 --- a/Source/Core/Core/ActionReplay.h +++ b/Source/Core/Core/ActionReplay.h @@ -42,7 +42,7 @@ void AddCode(ARCode new_code); void LoadAndApplyCodes(const IniFile& global_ini, const IniFile& local_ini); std::vector LoadCodes(const IniFile& global_ini, const IniFile& local_ini); -void SaveCodes(IniFile* local_ini, const std::vector& codes); +void SaveCodes(IniFile& local_ini, const std::vector& codes); void EnableSelfLogging(bool enable); std::vector GetSelfLog(); diff --git a/Source/Core/Core/PatchEngine.cpp b/Source/Core/Core/PatchEngine.cpp index 7c8260d661b9..3982ab63b626 100644 --- a/Source/Core/Core/PatchEngine.cpp +++ b/Source/Core/Core/PatchEngine.cpp @@ -53,8 +53,8 @@ const char* PatchTypeAsString(PatchType type) return s_patch_type_strings.at(static_cast(type)); } -void LoadPatchSection(const std::string& section, std::vector& patches, IniFile& globalIni, - IniFile& localIni) +void LoadPatchSection(const std::string& section, std::vector& patches, const IniFile& globalIni, + const IniFile& localIni) { // Load the name of all enabled patches std::string enabledSectionName = section + "_Enabled"; @@ -201,6 +201,32 @@ void LoadPatches() LoadSpeedhacks("Speedhacks", merged); } +void SavePatches(IniFile& inifile, const std::vector& patches) +{ + std::vector lines; + std::vector lines_enabled; + + for (const auto& patch : patches) + { + if (patch.active) + lines_enabled.push_back("$" + patch.name); + + if (!patch.user_defined) + continue; + + lines.push_back("$" + patch.name); + + for (const auto& entry : patch.entries) + { + lines.push_back(StringFromFormat("0x%08X:%s:0x%08X", entry.address, + PatchEngine::PatchTypeAsString(entry.type), entry.value)); + } + } + + inifile.SetLines("OnFrame_Enabled", lines_enabled); + inifile.SetLines("OnFrame", lines); +} + static void ApplyPatches(const std::vector& patches) { for (const Patch& patch : patches) diff --git a/Source/Core/Core/PatchEngine.h b/Source/Core/Core/PatchEngine.h index 6e3c5b6143e3..c3ca0c6e690e 100644 --- a/Source/Core/Core/PatchEngine.h +++ b/Source/Core/Core/PatchEngine.h @@ -48,9 +48,10 @@ const char* PatchTypeAsString(PatchType type); int GetSpeedhackCycles(const u32 addr); std::vector& GetFilePatches(); -void LoadPatchSection(const std::string& section, std::vector& patches, IniFile& globalIni, - IniFile& localIni); +void LoadPatchSection(const std::string& section, std::vector& patches, const IniFile& globalIni, + const IniFile& localIni); void LoadPatches(); +void SavePatches(IniFile& inifile, const std::vector& patches); bool ApplyFramePatches(); void Shutdown(); void Reload(); diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index f0951cb3b5d0..751121295051 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -49,10 +49,12 @@ add_executable(dolphin-emu Translation.h WiiUpdate.cpp WiiUpdate.h - Config/ARCodeWidget.cpp - Config/ARCodeWidget.h Config/CheatCodeEditor.cpp Config/CheatCodeEditor.h + Config/CheatItem.cpp + Config/CheatItem.h + Config/CheatList.cpp + Config/CheatList.h Config/CheatWarningWidget.cpp Config/CheatWarningWidget.h Config/ControllerInterface/DualShockUDPClientWidget.cpp @@ -69,8 +71,6 @@ add_executable(dolphin-emu Config/GameConfigHighlighter.h Config/GameConfigWidget.cpp Config/GameConfigWidget.h - Config/GeckoCodeWidget.cpp - Config/GeckoCodeWidget.h Config/Graphics/AdvancedWidget.cpp Config/Graphics/AdvancedWidget.h Config/Graphics/EnhancementsWidget.cpp @@ -156,8 +156,6 @@ add_executable(dolphin-emu Config/Mapping/WiimoteEmuMotionControlIMU.h Config/NewPatchDialog.cpp Config/NewPatchDialog.h - Config/PatchesWidget.cpp - Config/PatchesWidget.h Config/PropertiesDialog.cpp Config/PropertiesDialog.h Config/SettingsWindow.cpp @@ -450,8 +448,8 @@ if(APPLE) include(DolphinPostprocessBundle) dolphin_postprocess_bundle(dolphin-emu) # Fix rpath - add_custom_command(TARGET dolphin-emu - POST_BUILD COMMAND + add_custom_command(TARGET dolphin-emu + POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/" $) else() diff --git a/Source/Core/DolphinQt/CheatsManager.cpp b/Source/Core/DolphinQt/CheatsManager.cpp index 649fa1e68538..48bb579286ce 100644 --- a/Source/Core/DolphinQt/CheatsManager.cpp +++ b/Source/Core/DolphinQt/CheatsManager.cpp @@ -31,8 +31,7 @@ #include "UICommon/GameFile.h" -#include "DolphinQt/Config/ARCodeWidget.h" -#include "DolphinQt/Config/GeckoCodeWidget.h" +#include "DolphinQt/Config/CheatList.h" #include "DolphinQt/GameList/GameListModel.h" #include "DolphinQt/Settings.h" @@ -195,9 +194,9 @@ void CheatsManager::OnStateChanged(Core::State state) if (m_ar_code) m_ar_code->deleteLater(); - m_ar_code = new ARCodeWidget(*m_game_file, false); + m_ar_code = new CheatList(*m_game_file, CheatType::ARCode, false); m_tab_widget->insertTab(0, m_ar_code, tr("AR Code")); - m_tab_widget->insertTab(1, new GeckoCodeWidget(*m_game_file, false), tr("Gecko Codes")); + m_tab_widget->insertTab(1, new CheatList(*m_game_file, CheatType::GeckoCode, false), tr("Gecko Codes")); } } } diff --git a/Source/Core/DolphinQt/CheatsManager.h b/Source/Core/DolphinQt/CheatsManager.h index 7d0d1297f603..4b9e559d48bc 100644 --- a/Source/Core/DolphinQt/CheatsManager.h +++ b/Source/Core/DolphinQt/CheatsManager.h @@ -12,7 +12,7 @@ #include "Common/CommonTypes.h" -class ARCodeWidget; +class CheatList; class QComboBox; class QDialogButtonBox; class QLabel; @@ -68,7 +68,7 @@ class CheatsManager : public QDialog QTabWidget* m_tab_widget = nullptr; QWidget* m_cheat_search; - ARCodeWidget* m_ar_code = nullptr; + CheatList* m_ar_code = nullptr; QLabel* m_result_label; QTableWidget* m_match_table; diff --git a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp deleted file mode 100644 index eca7ccf7055f..000000000000 --- a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2018 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "DolphinQt/Config/ARCodeWidget.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "Common/FileUtil.h" -#include "Common/IniFile.h" - -#include "Core/ActionReplay.h" -#include "Core/ConfigManager.h" - -#include "DolphinQt/Config/CheatCodeEditor.h" -#include "DolphinQt/Config/CheatWarningWidget.h" - -#include "UICommon/GameFile.h" - -ARCodeWidget::ARCodeWidget(const UICommon::GameFile& game, bool restart_required) - : m_game(game), m_game_id(game.GetGameID()), m_game_revision(game.GetRevision()), - m_restart_required(restart_required) -{ - CreateWidgets(); - ConnectWidgets(); - - IniFile game_ini_local; - - // We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI - // will always be stored in GS/${GAMEID}.ini - game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); - - const IniFile game_ini_default = SConfig::LoadDefaultGameIni(m_game_id, m_game_revision); - m_ar_codes = ActionReplay::LoadCodes(game_ini_default, game_ini_local); - - UpdateList(); - OnSelectionChanged(); -} - -ARCodeWidget::~ARCodeWidget() = default; - -void ARCodeWidget::CreateWidgets() -{ - m_warning = new CheatWarningWidget(m_game_id, m_restart_required, this); - m_code_list = new QListWidget; - m_code_add = new QPushButton(tr("&Add New Code...")); - m_code_edit = new QPushButton(tr("&Edit Code...")); - m_code_remove = new QPushButton(tr("&Remove Code")); - - m_code_list->setContextMenuPolicy(Qt::CustomContextMenu); - - auto* button_layout = new QHBoxLayout; - - button_layout->addWidget(m_code_add); - button_layout->addWidget(m_code_edit); - button_layout->addWidget(m_code_remove); - - QVBoxLayout* layout = new QVBoxLayout; - - layout->addWidget(m_warning); - layout->addWidget(m_code_list); - layout->addLayout(button_layout); - - setLayout(layout); -} - -void ARCodeWidget::ConnectWidgets() -{ - connect(m_warning, &CheatWarningWidget::OpenCheatEnableSettings, this, - &ARCodeWidget::OpenGeneralSettings); - - connect(m_code_list, &QListWidget::itemChanged, this, &ARCodeWidget::OnItemChanged); - connect(m_code_list, &QListWidget::itemSelectionChanged, this, &ARCodeWidget::OnSelectionChanged); - connect(m_code_list->model(), &QAbstractItemModel::rowsMoved, this, - &ARCodeWidget::OnListReordered); - connect(m_code_list, &QListWidget::customContextMenuRequested, this, - &ARCodeWidget::OnContextMenuRequested); - - connect(m_code_add, &QPushButton::clicked, this, &ARCodeWidget::OnCodeAddClicked); - connect(m_code_edit, &QPushButton::clicked, this, &ARCodeWidget::OnCodeEditClicked); - connect(m_code_remove, &QPushButton::clicked, this, &ARCodeWidget::OnCodeRemoveClicked); -} - -void ARCodeWidget::OnItemChanged(QListWidgetItem* item) -{ - m_ar_codes[m_code_list->row(item)].active = (item->checkState() == Qt::Checked); - - if (!m_restart_required) - ActionReplay::ApplyCodes(m_ar_codes); - - UpdateList(); - SaveCodes(); -} - -void ARCodeWidget::OnContextMenuRequested() -{ - QMenu menu; - - menu.addAction(tr("Sort Alphabetically"), this, &ARCodeWidget::SortAlphabetically); - - menu.exec(QCursor::pos()); -} - -void ARCodeWidget::SortAlphabetically() -{ - m_code_list->sortItems(); - OnListReordered(); -} - -void ARCodeWidget::OnListReordered() -{ - // Reorder codes based on the indices of table item - std::vector codes; - codes.reserve(m_ar_codes.size()); - - for (int i = 0; i < m_code_list->count(); i++) - { - const int index = m_code_list->item(i)->data(Qt::UserRole).toInt(); - - codes.push_back(std::move(m_ar_codes[index])); - } - - m_ar_codes = std::move(codes); - - SaveCodes(); -} - -void ARCodeWidget::OnSelectionChanged() -{ - auto items = m_code_list->selectedItems(); - - if (items.empty()) - return; - - const auto* selected = items[0]; - - bool user_defined = m_ar_codes[m_code_list->row(selected)].user_defined; - - m_code_remove->setEnabled(user_defined); - m_code_edit->setText(user_defined ? tr("&Edit Code...") : tr("Clone and &Edit Code...")); -} - -void ARCodeWidget::UpdateList() -{ - m_code_list->clear(); - - for (size_t i = 0; i < m_ar_codes.size(); i++) - { - const auto& ar = m_ar_codes[i]; - auto* item = new QListWidgetItem(QString::fromStdString(ar.name) - .replace(QStringLiteral("<"), QChar::fromLatin1('<')) - .replace(QStringLiteral(">"), QChar::fromLatin1('>'))); - - item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | - Qt::ItemIsDragEnabled); - item->setCheckState(ar.active ? Qt::Checked : Qt::Unchecked); - item->setData(Qt::UserRole, static_cast(i)); - - m_code_list->addItem(item); - } - - m_code_list->setDragDropMode(QAbstractItemView::InternalMove); -} - -void ARCodeWidget::SaveCodes() -{ - const auto ini_path = - std::string(File::GetUserPath(D_GAMESETTINGS_IDX)).append(m_game_id).append(".ini"); - - IniFile game_ini_local; - game_ini_local.Load(ini_path); - ActionReplay::SaveCodes(&game_ini_local, m_ar_codes); - game_ini_local.Save(ini_path); -} - -void ARCodeWidget::AddCode(ActionReplay::ARCode code) -{ - m_ar_codes.push_back(std::move(code)); - - UpdateList(); - SaveCodes(); -} - -void ARCodeWidget::OnCodeAddClicked() -{ - ActionReplay::ARCode ar; - ar.active = true; - - CheatCodeEditor ed(this); - ed.SetARCode(&ar); - if (ed.exec() == QDialog::Rejected) - return; - - m_ar_codes.push_back(std::move(ar)); - - UpdateList(); - SaveCodes(); -} - -void ARCodeWidget::OnCodeEditClicked() -{ - const auto items = m_code_list->selectedItems(); - if (items.empty()) - return; - - const auto* const selected = items[0]; - auto& current_ar = m_ar_codes[m_code_list->row(selected)]; - - CheatCodeEditor ed(this); - if (current_ar.user_defined) - { - ed.SetARCode(¤t_ar); - - if (ed.exec() == QDialog::Rejected) - return; - } - else - { - ActionReplay::ARCode ar = current_ar; - ed.SetARCode(&ar); - - if (ed.exec() == QDialog::Rejected) - return; - - m_ar_codes.push_back(std::move(ar)); - } - - SaveCodes(); - UpdateList(); -} - -void ARCodeWidget::OnCodeRemoveClicked() -{ - auto items = m_code_list->selectedItems(); - - if (items.empty()) - return; - - const auto* selected = items[0]; - - m_ar_codes.erase(m_ar_codes.begin() + m_code_list->row(selected)); - - SaveCodes(); - UpdateList(); - - m_code_remove->setEnabled(false); -} diff --git a/Source/Core/DolphinQt/Config/ARCodeWidget.h b/Source/Core/DolphinQt/Config/ARCodeWidget.h deleted file mode 100644 index 48af85ec224a..000000000000 --- a/Source/Core/DolphinQt/Config/ARCodeWidget.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2018 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include - -#include -#include - -#include "Common/CommonTypes.h" - -namespace ActionReplay -{ -struct ARCode; -} - -namespace UICommon -{ -class GameFile; -} - -class CheatWarningWidget; -class QLabel; -class QListWidget; -class QListWidgetItem; -class QPushButton; - -class ARCodeWidget : public QWidget -{ - Q_OBJECT -public: - explicit ARCodeWidget(const UICommon::GameFile& game, bool restart_required = true); - ~ARCodeWidget() override; - - void AddCode(ActionReplay::ARCode code); - -signals: - void OpenGeneralSettings(); - -private: - void OnSelectionChanged(); - void OnItemChanged(QListWidgetItem* item); - void OnContextMenuRequested(); - - void CreateWidgets(); - void ConnectWidgets(); - void UpdateList(); - void SaveCodes(); - void SortAlphabetically(); - - void OnCodeAddClicked(); - void OnCodeEditClicked(); - void OnCodeRemoveClicked(); - - void OnListReordered(); - - const UICommon::GameFile& m_game; - std::string m_game_id; - u16 m_game_revision; - - CheatWarningWidget* m_warning; - QListWidget* m_code_list; - QPushButton* m_code_add; - QPushButton* m_code_edit; - QPushButton* m_code_remove; - - std::vector m_ar_codes; - bool m_restart_required; -}; diff --git a/Source/Core/DolphinQt/Config/CheatItem.cpp b/Source/Core/DolphinQt/Config/CheatItem.cpp new file mode 100644 index 000000000000..b38ce8f732fe --- /dev/null +++ b/Source/Core/DolphinQt/Config/CheatItem.cpp @@ -0,0 +1,115 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt/Config/CheatItem.h" + +#include "Core/ActionReplay.h" +#include "Core/GeckoCode.h" +#include "Core/PatchEngine.h" + +static QString FormatName(std::string name) { + return QString::fromStdString(name) + .replace(QStringLiteral("<"), QChar::fromLatin1('<')) + .replace(QStringLiteral(">"), QChar::fromLatin1('>')); +} + +void CheatItem::Init(std::string name, bool enabled) { + this->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | + Qt::ItemIsDragEnabled); + this->setCheckState(enabled ? Qt::Checked : Qt::Unchecked); + this->setText(FormatName(name)); +} + +CheatItem::CheatItem(Gecko::GeckoCode code) : QListWidgetItem() { + m_gecko_code = code; + Init(code.name, code.enabled); +} + +CheatItem::CheatItem(ActionReplay::ARCode code) : QListWidgetItem() { + m_ar_code = code; + Init(code.name, code.active); +} + +CheatItem::CheatItem(PatchEngine::Patch patch) : QListWidgetItem(){ + m_patch = patch; + Init(patch.name, patch.active); +} + +template<> +Gecko::GeckoCode* CheatItem::GetRawCode() { + m_gecko_code->enabled = this->checkState() == Qt::CheckState::Checked; + return &(m_gecko_code.value()); +} + +template<> +ActionReplay::ARCode* CheatItem::GetRawCode() { + m_ar_code->active = this->checkState() == Qt::CheckState::Checked; + return &m_ar_code.value(); +} + +template<> +PatchEngine::Patch* CheatItem::GetRawCode() { + m_patch->active = this->checkState() == Qt::CheckState::Checked; + return &m_patch.value(); +} + +QString CheatItem::GetName() const { + if (m_gecko_code) + return QString::fromStdString(m_gecko_code->name); + if (m_ar_code) + return QString::fromStdString(m_ar_code->name); + if (m_patch) + return QString::fromStdString(m_patch->name); + return QStringLiteral(""); +} + +QString CheatItem::GetCreator() const { + if (m_gecko_code) { + // gecko codes have a creator + QString::fromStdString(m_gecko_code->creator); + } + if (m_patch && !m_patch->user_defined) { + // Some dolphin patches are shipped with dolphin + return QStringLiteral("Dolphin Emulator"); + } + // Otherwise, we don't know the creator of AR codes and user defined patches + return QStringLiteral(""); +} + +QString CheatItem::GetNotes() const { + QString notes; + + // Currently, only gecko codes have notes + if (m_gecko_code) { + for (const auto &line : m_gecko_code->notes) { + notes += QString::fromStdString(line); + notes += QStringLiteral("\n"); + } + } + + return notes; +} + +QString CheatItem::GetCode() const { + QString code; + + if (m_gecko_code) { + for (const auto& c : m_gecko_code->codes) + { + code += QStringLiteral("%1 %2") + .arg(c.address, 8, 16, QLatin1Char('0')) + .arg(c.data, 8, 16, QLatin1Char('0')); + } + } + else if (m_ar_code) { + for (const auto& e : m_ar_code->ops) + { + code += QStringLiteral("%1 %2\n") + .arg(e.cmd_addr, 8, 16, QLatin1Char('0')) + .arg(e.value, 8, 16, QLatin1Char('0')); + } + } + + return code; +} \ No newline at end of file diff --git a/Source/Core/DolphinQt/Config/CheatItem.h b/Source/Core/DolphinQt/Config/CheatItem.h new file mode 100644 index 000000000000..19bd333ba564 --- /dev/null +++ b/Source/Core/DolphinQt/Config/CheatItem.h @@ -0,0 +1,34 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include + +#include "Core/ActionReplay.h" +#include "Core/GeckoCode.h" +#include "Core/PatchEngine.h" + +class CheatItem : public QListWidgetItem { +public: + CheatItem(Gecko::GeckoCode code); + CheatItem(ActionReplay::ARCode code); + CheatItem(PatchEngine::Patch patch); + + QString GetName() const; + QString GetCreator() const; + QString GetNotes() const; + QString GetCode() const; + + template + T* GetRawCode(); +private: + void Init(std::string, bool); + + std::optional m_gecko_code; + std::optional m_ar_code; + std::optional m_patch; +}; \ No newline at end of file diff --git a/Source/Core/DolphinQt/Config/CheatList.cpp b/Source/Core/DolphinQt/Config/CheatList.cpp new file mode 100644 index 000000000000..90d27aa34234 --- /dev/null +++ b/Source/Core/DolphinQt/Config/CheatList.cpp @@ -0,0 +1,424 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt/Config/CheatList.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common/FileUtil.h" +#include "Common/IniFile.h" + +#include "Core/ActionReplay.h" +#include "Core/ConfigManager.h" +#include "Core/GeckoCode.h" +#include "Core/GeckoCodeConfig.h" +#include "Core/PatchEngine.h" + +#include "DolphinQt/Config/CheatCodeEditor.h" +#include "DolphinQt/Config/CheatItem.h" +#include "DolphinQt/Config/CheatWarningWidget.h" +#include "DolphinQt/QtUtils/ModalMessageBox.h" + +#include "UICommon/GameFile.h" + + +CheatList::CheatList(const UICommon::GameFile& game, CheatType type, bool restart_required) + : m_game(game), m_game_id(game.GetGameID()), m_gametdb_id(game.GetGameTDBID()), + m_game_revision(game.GetRevision()), m_restart_required(restart_required) +{ + m_cheat_type = type; + + CreateWidgets(); + ConnectWidgets(); + + IniFile game_ini_local; + + // We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI + // will always be stored in GS/${GAMEID}.ini + game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); + + const IniFile game_ini_default = SConfig::LoadDefaultGameIni(m_game_id, m_game_revision); + + switch (m_cheat_type) + { + case CheatType::GeckoCode: + { + auto gecko_codes = Gecko::LoadCodes(game_ini_default, game_ini_local); + for (auto &code : gecko_codes) { + m_code_list->addItem(new CheatItem(code)); + } + } + break; + case CheatType::ARCode: + { + auto ar_codes = ActionReplay::LoadCodes(game_ini_default, game_ini_local); + for (auto &code : ar_codes) { + m_code_list->addItem(new CheatItem(code)); + } + } + break; + case CheatType::DolphinPatch: + { + std::vector frame_patches; + PatchEngine::LoadPatchSection("OnFrame", frame_patches, game_ini_default, game_ini_local); + + for (auto &patch : frame_patches) { + m_code_list->addItem(new CheatItem(patch)); + } + } + break; + } +} + +CheatList::~CheatList() = default; + +void CheatList::CreateWidgets() +{ + // Dolphin's patches aren't considered cheats and can be applid even when cheats are disabled + bool is_cheat = m_cheat_type != CheatType::DolphinPatch; + + m_warning = new CheatWarningWidget(m_game_id, is_cheat, m_restart_required, this); + m_code_list = new QListWidget; + m_name_label = new QLabel; + m_creator_label = new QLabel; + + m_code_list->setContextMenuPolicy(Qt::CustomContextMenu); + + QFont monospace(QFontDatabase::systemFont(QFontDatabase::FixedFont).family()); + + const auto line_height = QFontMetrics(font()).lineSpacing(); + + m_code_description = new QTextEdit; + m_code_description->setFont(monospace); + m_code_description->setReadOnly(true); + m_code_description->setFixedHeight(line_height * 5); + + m_code_view = new QTextEdit; + m_code_view->setFont(monospace); + m_code_view->setReadOnly(true); + m_code_view->setFixedHeight(line_height * 10); + m_code_list->setDragDropMode(QAbstractItemView::InternalMove); + + m_add_code = new QPushButton(tr("&Add New Code...")); + m_edit_code = new QPushButton(tr("&Edit Code...")); + m_remove_code = new QPushButton(tr("&Remove Code")); + + m_download_codes = new QPushButton(tr("Download Codes")); + + m_download_codes->setToolTip(tr("Download Codes from the WiiRD Database")); + + m_download_codes->setEnabled(!m_game_id.empty()); + + m_edit_code->setEnabled(false); + m_remove_code->setEnabled(false); + + auto* layout = new QVBoxLayout; + + layout->addWidget(m_warning); + layout->addWidget(m_code_list); + + auto* info_layout = new QFormLayout; + + info_layout->addRow(tr("Name:"), m_name_label); + info_layout->addRow(tr("Creator:"), m_creator_label); + info_layout->addRow(tr("Description:"), static_cast(nullptr)); + + info_layout->setFormAlignment(Qt::AlignLeft | Qt::AlignTop); + + for (QLabel* label : {m_name_label, m_creator_label}) + { + label->setTextInteractionFlags(Qt::TextSelectableByMouse); + label->setCursor(Qt::IBeamCursor); + } + + layout->addLayout(info_layout); + layout->addWidget(m_code_description); + layout->addWidget(m_code_view); + + QHBoxLayout* btn_layout = new QHBoxLayout; + + btn_layout->addWidget(m_add_code); + btn_layout->addWidget(m_edit_code); + btn_layout->addWidget(m_remove_code); + + if (m_cheat_type == CheatType::GeckoCode) { // Only Gecko codes can be downloaded + btn_layout->addWidget(m_download_codes); + } + + layout->addLayout(btn_layout); + + setLayout(layout); +} + +void CheatList::ConnectWidgets() +{ + connect(m_code_list, &QListWidget::itemSelectionChanged, this, + &CheatList::OnSelectionChanged); + connect(m_code_list, &QListWidget::itemChanged, this, &CheatList::OnItemChanged); + connect(m_code_list->model(), &QAbstractItemModel::rowsMoved, this, + &CheatList::SaveCodes); + connect(m_code_list, &QListWidget::customContextMenuRequested, this, + &CheatList::OnContextMenuRequested); + + connect(m_add_code, &QPushButton::clicked, this, &CheatList::AddCodeClicked); + connect(m_remove_code, &QPushButton::clicked, this, &CheatList::RemoveCode); + connect(m_edit_code, &QPushButton::clicked, this, &CheatList::EditCode); + connect(m_download_codes, &QPushButton::clicked, this, &CheatList::DownloadCodes); + connect(m_warning, &CheatWarningWidget::OpenCheatEnableSettings, this, + &CheatList::OpenGeneralSettings); +} + +void CheatList::OnSelectionChanged() +{ + auto items = m_code_list->selectedItems(); + + const bool empty = items.empty(); + + m_edit_code->setEnabled(!empty); + m_remove_code->setEnabled(!empty); + + if (items.empty()) + return; + + auto code = dynamic_cast(items[0]); + + m_name_label->setText(code->GetName()); + m_creator_label->setText(code->GetCreator()); + m_code_description->setText(code->GetNotes()); + m_code_view->setText(code->GetCode()); +} + +void CheatList::OnItemChanged(QListWidgetItem* item) +{ + if (!m_restart_required) { + switch (m_cheat_type) + { + case CheatType::GeckoCode: + { + auto codes = GetList(); + Gecko::SetActiveCodes(codes); + } + break; + case CheatType::ARCode: + { + auto codes = GetList(); + ActionReplay::ApplyCodes(codes); + } + break; + case CheatType::DolphinPatch: + // Dolphin patches can't be updated at runtime + break; + } + } + + SaveCodes(); +} + +template +void CheatList::AddCode(T code) { + m_code_list->addItem(new CheatItem(code)); + + SaveCodes(); +} + +template void CheatList::AddCode(ActionReplay::ARCode); +template void CheatList::AddCode(Gecko::GeckoCode); +template void CheatList::AddCode(PatchEngine::Patch); + +void CheatList::AddCodeClicked() +{ + CheatItem *new_list_item; + + CheatCodeEditor ed(this); + + switch (m_cheat_type) + { + case CheatType::GeckoCode: + { + Gecko::GeckoCode new_code; + ed.SetGeckoCode(&new_code); + + if (ed.exec() == QDialog::Rejected) + return; + + new_list_item = new CheatItem(new_code); + } + break; + case CheatType::ARCode: + { + ActionReplay::ARCode new_code; + ed.SetARCode(&new_code); + + if (ed.exec() == QDialog::Rejected) + return; + + new_list_item = new CheatItem(new_code); + } + break; + case CheatType::DolphinPatch: + // Dolphin patches can't be updated at runtime + break; + } + + new_list_item->setSelected(true); + m_code_list->addItem(new_list_item); + + SaveCodes(); +} + +void CheatList::EditCode() +{ + auto* item = m_code_list->currentItem(); + if (item == nullptr) + return; + + auto code = dynamic_cast(item); + + CheatCodeEditor ed(this); + + switch (m_cheat_type) + { + case CheatType::GeckoCode: + { + auto gecko_code = code->GetRawCode(); + ed.SetGeckoCode(gecko_code); + } + break; + case CheatType::ARCode: + { + auto ar_code = code->GetRawCode(); + ed.SetARCode(ar_code); + } + break; + case CheatType::DolphinPatch: + // Dolphin patches can't be updated at runtime + break; + } + + if (ed.exec() == QDialog::Rejected) + return; + + SaveCodes(); +} + +void CheatList::RemoveCode() +{ + const auto* item = m_code_list->currentItem(); + + if (item == nullptr) + return; + + SaveCodes(); +} + +void CheatList::SaveCodes() +{ + const auto ini_path = + std::string(File::GetUserPath(D_GAMESETTINGS_IDX)).append(m_game_id).append(".ini"); + + IniFile game_ini_local; + game_ini_local.Load(ini_path); + switch (m_cheat_type) + { + case CheatType::GeckoCode: + { + auto codes = GetList(); + Gecko::SaveCodes(game_ini_local, codes); + } + break; + case CheatType::ARCode: + { + auto codes = GetList(); + ActionReplay::SaveCodes(game_ini_local, codes); + } + break; + case CheatType::DolphinPatch: + { + auto patches = GetList(); + PatchEngine::SavePatches(game_ini_local, patches); + } + break; + } + + game_ini_local.Save(ini_path); +} + +void CheatList::OnContextMenuRequested() +{ + QMenu menu; + + menu.addAction(tr("Sort Alphabetically"), this, &CheatList::SortAlphabetically); + + menu.exec(QCursor::pos()); +} + +void CheatList::SortAlphabetically() +{ + m_code_list->sortItems(); + SaveCodes(); +} + +void CheatList::DownloadCodes() +{ + bool success; + + std::vector codes = Gecko::DownloadCodes(m_gametdb_id, &success); + + if (!success) + { + ModalMessageBox::critical(this, tr("Error"), tr("Failed to download codes.")); + return; + } + + if (codes.empty()) + { + ModalMessageBox::critical(this, tr("Error"), tr("File contained no codes.")); + return; + } + + size_t added_count = 0; + + auto current_codes = GetList(); + + for (const auto& code : codes) + { + auto it = std::find(current_codes.begin(), current_codes.end(), code); + + if (it == current_codes.end()) + { + m_code_list->addItem(new CheatItem(code)); + added_count++; + } + } + + SaveCodes(); + + ModalMessageBox::information( + this, tr("Download complete"), + tr("Downloaded %1 codes. (added %2)") + .arg(QString::number(codes.size()), QString::number(added_count))); +} + +template +std::vector CheatList::GetList() { + int count = m_code_list->count(); + std::vector list; + list.reserve(count); + + for (int i = 0; i < count; i++) { + auto code = dynamic_cast(m_code_list->item(i)); + list.push_back(*code->GetRawCode()); + } + + return list; +} \ No newline at end of file diff --git a/Source/Core/DolphinQt/Config/GeckoCodeWidget.h b/Source/Core/DolphinQt/Config/CheatList.h similarity index 76% rename from Source/Core/DolphinQt/Config/GeckoCodeWidget.h rename to Source/Core/DolphinQt/Config/CheatList.h index 28fa4aeb446b..2b5653f4bbb7 100644 --- a/Source/Core/DolphinQt/Config/GeckoCodeWidget.h +++ b/Source/Core/DolphinQt/Config/CheatList.h @@ -28,12 +28,21 @@ namespace UICommon class GameFile; } -class GeckoCodeWidget : public QWidget +enum CheatType { + DolphinPatch, + ARCode, + GeckoCode +}; + +class CheatList : public QWidget { Q_OBJECT public: - explicit GeckoCodeWidget(const UICommon::GameFile& game, bool restart_required = true); - ~GeckoCodeWidget() override; + explicit CheatList(const UICommon::GameFile& game, CheatType type, bool restart_required = true); + ~CheatList() override; + + template + void AddCode(T code); signals: void OpenGeneralSettings(); @@ -41,19 +50,21 @@ class GeckoCodeWidget : public QWidget private: void OnSelectionChanged(); void OnItemChanged(QListWidgetItem* item); - void OnListReordered(); void OnContextMenuRequested(); void CreateWidgets(); void ConnectWidgets(); - void UpdateList(); - void AddCode(); + void AddCodeClicked(); void EditCode(); void RemoveCode(); void DownloadCodes(); void SaveCodes(); void SortAlphabetically(); + template + std::vector GetList(); + + CheatType m_cheat_type; const UICommon::GameFile& m_game; std::string m_game_id; std::string m_gametdb_id; @@ -69,6 +80,5 @@ class GeckoCodeWidget : public QWidget QPushButton* m_edit_code; QPushButton* m_remove_code; QPushButton* m_download_codes; - std::vector m_gecko_codes; bool m_restart_required; }; diff --git a/Source/Core/DolphinQt/Config/CheatWarningWidget.cpp b/Source/Core/DolphinQt/Config/CheatWarningWidget.cpp index 32fcb33a53a3..3606e0ba5b3b 100644 --- a/Source/Core/DolphinQt/Config/CheatWarningWidget.cpp +++ b/Source/Core/DolphinQt/Config/CheatWarningWidget.cpp @@ -15,9 +15,9 @@ #include "DolphinQt/Settings.h" -CheatWarningWidget::CheatWarningWidget(const std::string& game_id, bool restart_required, +CheatWarningWidget::CheatWarningWidget(const std::string& game_id, bool is_cheat, bool restart_required, QWidget* parent) - : QWidget(parent), m_game_id(game_id), m_restart_required(restart_required) + : QWidget(parent), m_game_id(game_id), m_is_cheat(is_cheat), m_restart_required(restart_required) { CreateWidgets(); ConnectWidgets(); @@ -67,7 +67,7 @@ void CheatWarningWidget::Update(bool running) m_text->setText(tr("Changing cheats will only take effect when the game is restarted.")); } - if (!Settings::Instance().GetCheatsEnabled()) + if (m_is_cheat && !Settings::Instance().GetCheatsEnabled()) { hide_widget = false; hide_config_button = false; diff --git a/Source/Core/DolphinQt/Config/CheatWarningWidget.h b/Source/Core/DolphinQt/Config/CheatWarningWidget.h index 2ae15850f0bd..58879dbe7366 100644 --- a/Source/Core/DolphinQt/Config/CheatWarningWidget.h +++ b/Source/Core/DolphinQt/Config/CheatWarningWidget.h @@ -15,7 +15,7 @@ class CheatWarningWidget : public QWidget { Q_OBJECT public: - explicit CheatWarningWidget(const std::string& game_id, bool restart_required, QWidget* parent); + explicit CheatWarningWidget(const std::string& game_id, bool is_cheat, bool restart_required, QWidget* parent); signals: void OpenCheatEnableSettings(); @@ -30,4 +30,5 @@ class CheatWarningWidget : public QWidget QPushButton* m_config_button; const std::string m_game_id; bool m_restart_required; + bool m_is_cheat; }; diff --git a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp deleted file mode 100644 index 8ff6c0cb7869..000000000000 --- a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp +++ /dev/null @@ -1,337 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "DolphinQt/Config/GeckoCodeWidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Common/FileUtil.h" -#include "Common/IniFile.h" - -#include "Core/ConfigManager.h" -#include "Core/GeckoCode.h" -#include "Core/GeckoCodeConfig.h" - -#include "DolphinQt/Config/CheatCodeEditor.h" -#include "DolphinQt/Config/CheatWarningWidget.h" -#include "DolphinQt/QtUtils/ModalMessageBox.h" - -#include "UICommon/GameFile.h" - -GeckoCodeWidget::GeckoCodeWidget(const UICommon::GameFile& game, bool restart_required) - : m_game(game), m_game_id(game.GetGameID()), m_gametdb_id(game.GetGameTDBID()), - m_game_revision(game.GetRevision()), m_restart_required(restart_required) -{ - CreateWidgets(); - ConnectWidgets(); - - IniFile game_ini_local; - - // We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI - // will always be stored in GS/${GAMEID}.ini - game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); - - const IniFile game_ini_default = SConfig::LoadDefaultGameIni(m_game_id, m_game_revision); - m_gecko_codes = Gecko::LoadCodes(game_ini_default, game_ini_local); - - UpdateList(); -} - -GeckoCodeWidget::~GeckoCodeWidget() = default; - -void GeckoCodeWidget::CreateWidgets() -{ - m_warning = new CheatWarningWidget(m_game_id, m_restart_required, this); - m_code_list = new QListWidget; - m_name_label = new QLabel; - m_creator_label = new QLabel; - - m_code_list->setContextMenuPolicy(Qt::CustomContextMenu); - - QFont monospace(QFontDatabase::systemFont(QFontDatabase::FixedFont).family()); - - const auto line_height = QFontMetrics(font()).lineSpacing(); - - m_code_description = new QTextEdit; - m_code_description->setFont(monospace); - m_code_description->setReadOnly(true); - m_code_description->setFixedHeight(line_height * 5); - - m_code_view = new QTextEdit; - m_code_view->setFont(monospace); - m_code_view->setReadOnly(true); - m_code_view->setFixedHeight(line_height * 10); - - m_add_code = new QPushButton(tr("&Add New Code...")); - m_edit_code = new QPushButton(tr("&Edit Code...")); - m_remove_code = new QPushButton(tr("&Remove Code")); - m_download_codes = new QPushButton(tr("Download Codes")); - - m_download_codes->setToolTip(tr("Download Codes from the WiiRD Database")); - - m_download_codes->setEnabled(!m_game_id.empty()); - m_edit_code->setEnabled(false); - m_remove_code->setEnabled(false); - - auto* layout = new QVBoxLayout; - - layout->addWidget(m_warning); - layout->addWidget(m_code_list); - - auto* info_layout = new QFormLayout; - - info_layout->addRow(tr("Name:"), m_name_label); - info_layout->addRow(tr("Creator:"), m_creator_label); - info_layout->addRow(tr("Description:"), static_cast(nullptr)); - - info_layout->setFormAlignment(Qt::AlignLeft | Qt::AlignTop); - - for (QLabel* label : {m_name_label, m_creator_label}) - { - label->setTextInteractionFlags(Qt::TextSelectableByMouse); - label->setCursor(Qt::IBeamCursor); - } - - layout->addLayout(info_layout); - layout->addWidget(m_code_description); - layout->addWidget(m_code_view); - - QHBoxLayout* btn_layout = new QHBoxLayout; - - btn_layout->addWidget(m_add_code); - btn_layout->addWidget(m_edit_code); - btn_layout->addWidget(m_remove_code); - btn_layout->addWidget(m_download_codes); - - layout->addLayout(btn_layout); - - setLayout(layout); -} - -void GeckoCodeWidget::ConnectWidgets() -{ - connect(m_code_list, &QListWidget::itemSelectionChanged, this, - &GeckoCodeWidget::OnSelectionChanged); - connect(m_code_list, &QListWidget::itemChanged, this, &GeckoCodeWidget::OnItemChanged); - connect(m_code_list->model(), &QAbstractItemModel::rowsMoved, this, - &GeckoCodeWidget::OnListReordered); - connect(m_code_list, &QListWidget::customContextMenuRequested, this, - &GeckoCodeWidget::OnContextMenuRequested); - - connect(m_add_code, &QPushButton::clicked, this, &GeckoCodeWidget::AddCode); - connect(m_remove_code, &QPushButton::clicked, this, &GeckoCodeWidget::RemoveCode); - connect(m_edit_code, &QPushButton::clicked, this, &GeckoCodeWidget::EditCode); - connect(m_download_codes, &QPushButton::clicked, this, &GeckoCodeWidget::DownloadCodes); - connect(m_warning, &CheatWarningWidget::OpenCheatEnableSettings, this, - &GeckoCodeWidget::OpenGeneralSettings); -} - -void GeckoCodeWidget::OnSelectionChanged() -{ - auto items = m_code_list->selectedItems(); - - const bool empty = items.empty(); - - m_edit_code->setEnabled(!empty); - m_remove_code->setEnabled(!empty); - - if (items.empty()) - return; - - auto selected = items[0]; - - const int index = selected->data(Qt::UserRole).toInt(); - - const auto& code = m_gecko_codes[index]; - - m_name_label->setText(QString::fromStdString(code.name)); - m_creator_label->setText(QString::fromStdString(code.creator)); - - m_code_description->clear(); - - for (const auto& line : code.notes) - m_code_description->append(QString::fromStdString(line)); - - m_code_view->clear(); - - for (const auto& c : code.codes) - { - m_code_view->append(QStringLiteral("%1 %2") - .arg(c.address, 8, 16, QLatin1Char('0')) - .arg(c.data, 8, 16, QLatin1Char('0'))); - } -} - -void GeckoCodeWidget::OnItemChanged(QListWidgetItem* item) -{ - const int index = item->data(Qt::UserRole).toInt(); - m_gecko_codes[index].enabled = (item->checkState() == Qt::Checked); - - if (!m_restart_required) - Gecko::SetActiveCodes(m_gecko_codes); - - SaveCodes(); -} - -void GeckoCodeWidget::AddCode() -{ - Gecko::GeckoCode code; - code.enabled = true; - - CheatCodeEditor ed(this); - ed.SetGeckoCode(&code); - if (ed.exec() == QDialog::Rejected) - return; - - m_gecko_codes.push_back(std::move(code)); - SaveCodes(); - UpdateList(); -} - -void GeckoCodeWidget::EditCode() -{ - const auto* item = m_code_list->currentItem(); - if (item == nullptr) - return; - - const int index = item->data(Qt::UserRole).toInt(); - - CheatCodeEditor ed(this); - ed.SetGeckoCode(&m_gecko_codes[index]); - if (ed.exec() == QDialog::Rejected) - return; - - SaveCodes(); - UpdateList(); -} - -void GeckoCodeWidget::RemoveCode() -{ - const auto* item = m_code_list->currentItem(); - - if (item == nullptr) - return; - - m_gecko_codes.erase(m_gecko_codes.begin() + item->data(Qt::UserRole).toInt()); - - UpdateList(); - SaveCodes(); -} - -void GeckoCodeWidget::SaveCodes() -{ - const auto ini_path = - std::string(File::GetUserPath(D_GAMESETTINGS_IDX)).append(m_game_id).append(".ini"); - - IniFile game_ini_local; - game_ini_local.Load(ini_path); - Gecko::SaveCodes(game_ini_local, m_gecko_codes); - game_ini_local.Save(ini_path); -} - -void GeckoCodeWidget::OnContextMenuRequested() -{ - QMenu menu; - - menu.addAction(tr("Sort Alphabetically"), this, &GeckoCodeWidget::SortAlphabetically); - - menu.exec(QCursor::pos()); -} - -void GeckoCodeWidget::SortAlphabetically() -{ - m_code_list->sortItems(); - OnListReordered(); -} - -void GeckoCodeWidget::OnListReordered() -{ - // Reorder codes based on the indices of table item - std::vector codes; - codes.reserve(m_gecko_codes.size()); - - for (int i = 0; i < m_code_list->count(); i++) - { - const int index = m_code_list->item(i)->data(Qt::UserRole).toInt(); - - codes.push_back(std::move(m_gecko_codes[index])); - } - - m_gecko_codes = std::move(codes); - - UpdateList(); - SaveCodes(); -} - -void GeckoCodeWidget::UpdateList() -{ - m_code_list->clear(); - - for (size_t i = 0; i < m_gecko_codes.size(); i++) - { - const auto& code = m_gecko_codes[i]; - - auto* item = new QListWidgetItem(QString::fromStdString(code.name) - .replace(QStringLiteral("<"), QChar::fromLatin1('<')) - .replace(QStringLiteral(">"), QChar::fromLatin1('>'))); - - item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | - Qt::ItemIsDragEnabled); - item->setCheckState(code.enabled ? Qt::Checked : Qt::Unchecked); - item->setData(Qt::UserRole, static_cast(i)); - - m_code_list->addItem(item); - } - - m_code_list->setDragDropMode(QAbstractItemView::InternalMove); -} - -void GeckoCodeWidget::DownloadCodes() -{ - bool success; - - std::vector codes = Gecko::DownloadCodes(m_gametdb_id, &success); - - if (!success) - { - ModalMessageBox::critical(this, tr("Error"), tr("Failed to download codes.")); - return; - } - - if (codes.empty()) - { - ModalMessageBox::critical(this, tr("Error"), tr("File contained no codes.")); - return; - } - - size_t added_count = 0; - - for (const auto& code : codes) - { - auto it = std::find(m_gecko_codes.begin(), m_gecko_codes.end(), code); - - if (it == m_gecko_codes.end()) - { - m_gecko_codes.push_back(code); - added_count++; - } - } - - UpdateList(); - SaveCodes(); - - ModalMessageBox::information( - this, tr("Download complete"), - tr("Downloaded %1 codes. (added %2)") - .arg(QString::number(codes.size()), QString::number(added_count))); -} diff --git a/Source/Core/DolphinQt/Config/PropertiesDialog.cpp b/Source/Core/DolphinQt/Config/PropertiesDialog.cpp index e84ddc558a18..ce231a240bfb 100644 --- a/Source/Core/DolphinQt/Config/PropertiesDialog.cpp +++ b/Source/Core/DolphinQt/Config/PropertiesDialog.cpp @@ -12,10 +12,9 @@ #include "DiscIO/Enums.h" #include "DiscIO/Volume.h" -#include "DolphinQt/Config/ARCodeWidget.h" +#include "DolphinQt/Config/CheatList.h" #include "DolphinQt/Config/FilesystemWidget.h" #include "DolphinQt/Config/GameConfigWidget.h" -#include "DolphinQt/Config/GeckoCodeWidget.h" #include "DolphinQt/Config/InfoWidget.h" #include "DolphinQt/Config/PatchesWidget.h" #include "DolphinQt/Config/PropertiesDialog.h" @@ -38,15 +37,15 @@ PropertiesDialog::PropertiesDialog(QWidget* parent, const UICommon::GameFile& ga QTabWidget* tab_widget = new QTabWidget(this); InfoWidget* info = new InfoWidget(game); - ARCodeWidget* ar = new ARCodeWidget(game); - GeckoCodeWidget* gecko = new GeckoCodeWidget(game); - PatchesWidget* patches = new PatchesWidget(game); + CheatList* ar = new CheatList(game, CheatType::ARCode); + CheatList* gecko = new CheatList(game, CheatType::GeckoCode); + CheatList* patches = new CheatList(game, CheatType::DolphinPatch); GameConfigWidget* game_config = new GameConfigWidget(game); - connect(gecko, &GeckoCodeWidget::OpenGeneralSettings, this, + connect(gecko, &CheatList::OpenGeneralSettings, this, &PropertiesDialog::OpenGeneralSettings); - connect(ar, &ARCodeWidget::OpenGeneralSettings, this, &PropertiesDialog::OpenGeneralSettings); + connect(ar, &CheatList::OpenGeneralSettings, this, &PropertiesDialog::OpenGeneralSettings); const int padding_width = 120; const int padding_height = 100;