// Copyright 2018 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. #include "DolphinQt2/Config/ARCodeWidget.h" #include #include #include #include #include #include "Common/FileUtil.h" #include "Common/IniFile.h" #include "Core/ActionReplay.h" #include "Core/ConfigManager.h" #include "DolphinQt2/Config/CheatCodeEditor.h" #include "DolphinQt2/Config/CheatWarningWidget.h" #include "UICommon/GameFile.h" ARCodeWidget::ARCodeWidget(const UICommon::GameFile& game) : m_game(game), m_game_id(game.GetGameID()), m_game_revision(game.GetRevision()) { 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"); IniFile game_ini_default = SConfig::GetInstance().LoadDefaultGameIni(m_game_id, m_game_revision); m_ar_codes = ActionReplay::LoadCodes(game_ini_default, game_ini_local); UpdateList(); OnSelectionChanged(); } void ARCodeWidget::CreateWidgets() { m_warning = new CheatWarningWidget(m_game_id); 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")); 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_add, &QPushButton::pressed, this, &ARCodeWidget::OnCodeAddPressed); connect(m_code_edit, &QPushButton::pressed, this, &ARCodeWidget::OnCodeEditPressed); connect(m_code_remove, &QPushButton::pressed, this, &ARCodeWidget::OnCodeRemovePressed); } void ARCodeWidget::OnItemChanged(QListWidgetItem* item) { m_ar_codes[m_code_list->row(item)].active = (item->checkState() == Qt::Checked); 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 (const auto& ar : m_ar_codes) { auto* item = new QListWidgetItem(QString::fromStdString(ar.name) .replace(QStringLiteral("<"), QStringLiteral("<")) .replace(QStringLiteral(">"), QStringLiteral(">"))); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); item->setCheckState(ar.active ? Qt::Checked : Qt::Unchecked); m_code_list->addItem(item); } } void ARCodeWidget::SaveCodes() { IniFile game_ini_local; game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); ActionReplay::SaveCodes(&game_ini_local, m_ar_codes); game_ini_local.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); } void ARCodeWidget::OnCodeAddPressed() { ActionReplay::ARCode ar; ar.active = true; CheatCodeEditor ed; ed.SetARCode(&ar); if (ed.exec()) { m_ar_codes.push_back(std::move(ar)); UpdateList(); SaveCodes(); } } void ARCodeWidget::OnCodeEditPressed() { auto items = m_code_list->selectedItems(); if (items.empty()) return; const auto* selected = items[0]; auto& current_ar = m_ar_codes[m_code_list->row(selected)]; bool user_defined = current_ar.user_defined; ActionReplay::ARCode ar = current_ar; CheatCodeEditor ed; ed.SetARCode(user_defined ? ¤t_ar : &ar); ed.exec(); if (!user_defined) m_ar_codes.push_back(ar); SaveCodes(); UpdateList(); } void ARCodeWidget::OnCodeRemovePressed() { 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); }