mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-03 22:31:22 +01:00
fdb7328c73
At the end of each frame automatically update the Current Value for visible table rows in the selected and visible CheatSearchWidget (if any). Also update all Current Values in all CheatSearchWidgets when the State changes to Paused. Only updating visible table rows serves to minimize the performance cost of this feature. If the user scrolls to an un-updated cell it will promptly be updated by either the next VIEndFieldEvent or the State transitioning to Paused.
190 lines
5.7 KiB
C++
190 lines
5.7 KiB
C++
// Copyright 2018 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "DolphinQt/CheatsManager.h"
|
|
|
|
#include <functional>
|
|
|
|
#include <QDialogButtonBox>
|
|
#include <QVBoxLayout>
|
|
|
|
#include "Core/ActionReplay.h"
|
|
#include "Core/CheatSearch.h"
|
|
#include "Core/ConfigManager.h"
|
|
#include "Core/Core.h"
|
|
|
|
#include "UICommon/GameFile.h"
|
|
|
|
#include "DolphinQt/CheatSearchFactoryWidget.h"
|
|
#include "DolphinQt/CheatSearchWidget.h"
|
|
#include "DolphinQt/Config/ARCodeWidget.h"
|
|
#include "DolphinQt/Config/GeckoCodeWidget.h"
|
|
#include "DolphinQt/QtUtils/PartiallyClosableTabWidget.h"
|
|
#include "DolphinQt/Settings.h"
|
|
|
|
#include "VideoCommon/VideoEvents.h"
|
|
|
|
CheatsManager::CheatsManager(QWidget* parent) : QDialog(parent)
|
|
{
|
|
setWindowTitle(tr("Cheats Manager"));
|
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
|
|
|
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
|
&CheatsManager::OnStateChanged);
|
|
|
|
CreateWidgets();
|
|
ConnectWidgets();
|
|
|
|
RefreshCodeTabs(Core::GetState(), true);
|
|
|
|
auto& settings = Settings::GetQSettings();
|
|
restoreGeometry(settings.value(QStringLiteral("cheatsmanager/geometry")).toByteArray());
|
|
}
|
|
|
|
CheatsManager::~CheatsManager()
|
|
{
|
|
auto& settings = Settings::GetQSettings();
|
|
settings.setValue(QStringLiteral("cheatsmanager/geometry"), saveGeometry());
|
|
}
|
|
|
|
void CheatsManager::OnStateChanged(Core::State state)
|
|
{
|
|
RefreshCodeTabs(state, false);
|
|
if (state == Core::State::Paused)
|
|
UpdateAllCheatSearchWidgetCurrentValues();
|
|
}
|
|
|
|
void CheatsManager::OnFrameEnd()
|
|
{
|
|
if (!isVisible())
|
|
return;
|
|
|
|
auto* const selected_cheat_search_widget =
|
|
qobject_cast<CheatSearchWidget*>(m_tab_widget->currentWidget());
|
|
if (selected_cheat_search_widget != nullptr)
|
|
selected_cheat_search_widget->UpdateTableVisibleCurrentValues();
|
|
}
|
|
|
|
void CheatsManager::UpdateAllCheatSearchWidgetCurrentValues()
|
|
{
|
|
for (int i = 0; i < m_tab_widget->count(); ++i)
|
|
{
|
|
auto* const cheat_search_widget = qobject_cast<CheatSearchWidget*>(m_tab_widget->widget(i));
|
|
if (cheat_search_widget != nullptr)
|
|
cheat_search_widget->UpdateTableAllCurrentValues();
|
|
}
|
|
}
|
|
|
|
void CheatsManager::RegisterAfterFrameEventCallback()
|
|
{
|
|
m_VI_end_field_event = VIEndFieldEvent::Register([this] { OnFrameEnd(); }, "CheatsManager");
|
|
}
|
|
|
|
void CheatsManager::RemoveAfterFrameEventCallback()
|
|
{
|
|
m_VI_end_field_event.reset();
|
|
}
|
|
|
|
void CheatsManager::hideEvent(QHideEvent* event)
|
|
{
|
|
RemoveAfterFrameEventCallback();
|
|
}
|
|
|
|
void CheatsManager::showEvent(QShowEvent* event)
|
|
{
|
|
RegisterAfterFrameEventCallback();
|
|
}
|
|
|
|
void CheatsManager::RefreshCodeTabs(Core::State state, bool force)
|
|
{
|
|
if (!force && (state == Core::State::Starting || state == Core::State::Stopping))
|
|
return;
|
|
|
|
const auto& game_id =
|
|
state != Core::State::Uninitialized ? SConfig::GetInstance().GetGameID() : std::string();
|
|
const auto& game_tdb_id = SConfig::GetInstance().GetGameTDBID();
|
|
const u16 revision = SConfig::GetInstance().GetRevision();
|
|
|
|
if (!force && m_game_id == game_id && m_game_tdb_id == game_tdb_id && m_revision == revision)
|
|
return;
|
|
|
|
m_game_id = game_id;
|
|
m_game_tdb_id = game_tdb_id;
|
|
m_revision = revision;
|
|
|
|
if (m_ar_code)
|
|
{
|
|
const int tab_index = m_tab_widget->indexOf(m_ar_code);
|
|
if (tab_index != -1)
|
|
m_tab_widget->removeTab(tab_index);
|
|
m_ar_code->deleteLater();
|
|
m_ar_code = nullptr;
|
|
}
|
|
|
|
if (m_gecko_code)
|
|
{
|
|
const int tab_index = m_tab_widget->indexOf(m_gecko_code);
|
|
if (tab_index != -1)
|
|
m_tab_widget->removeTab(tab_index);
|
|
m_gecko_code->deleteLater();
|
|
m_gecko_code = nullptr;
|
|
}
|
|
|
|
m_ar_code = new ARCodeWidget(m_game_id, m_revision, false);
|
|
m_gecko_code = new GeckoCodeWidget(m_game_id, m_game_tdb_id, m_revision, false);
|
|
m_tab_widget->insertTab(0, m_ar_code, tr("AR Code"));
|
|
m_tab_widget->insertTab(1, m_gecko_code, tr("Gecko Codes"));
|
|
m_tab_widget->setTabUnclosable(0);
|
|
m_tab_widget->setTabUnclosable(1);
|
|
|
|
connect(m_ar_code, &ARCodeWidget::OpenGeneralSettings, this, &CheatsManager::OpenGeneralSettings);
|
|
connect(m_gecko_code, &GeckoCodeWidget::OpenGeneralSettings, this,
|
|
&CheatsManager::OpenGeneralSettings);
|
|
}
|
|
|
|
void CheatsManager::CreateWidgets()
|
|
{
|
|
m_tab_widget = new PartiallyClosableTabWidget;
|
|
m_button_box = new QDialogButtonBox(QDialogButtonBox::Close);
|
|
|
|
m_cheat_search_new = new CheatSearchFactoryWidget();
|
|
m_tab_widget->addTab(m_cheat_search_new, tr("Start New Cheat Search"));
|
|
m_tab_widget->setTabUnclosable(0);
|
|
|
|
auto* layout = new QVBoxLayout;
|
|
layout->addWidget(m_tab_widget);
|
|
layout->addWidget(m_button_box);
|
|
|
|
setLayout(layout);
|
|
}
|
|
|
|
void CheatsManager::OnNewSessionCreated(const Cheats::CheatSearchSessionBase& session)
|
|
{
|
|
auto* w = new CheatSearchWidget(session.Clone());
|
|
const int tab_index = m_tab_widget->addTab(w, tr("Cheat Search"));
|
|
w->connect(w, &CheatSearchWidget::ActionReplayCodeGenerated, this,
|
|
[this](const ActionReplay::ARCode& ar_code) {
|
|
if (m_ar_code)
|
|
m_ar_code->AddCode(ar_code);
|
|
});
|
|
w->connect(w, &CheatSearchWidget::ShowMemory, [this](u32 address) { emit ShowMemory(address); });
|
|
w->connect(w, &CheatSearchWidget::RequestWatch,
|
|
[this](QString name, u32 address) { emit RequestWatch(name, address); });
|
|
m_tab_widget->setCurrentIndex(tab_index);
|
|
}
|
|
|
|
void CheatsManager::OnTabCloseRequested(int index)
|
|
{
|
|
auto* w = m_tab_widget->widget(index);
|
|
if (w)
|
|
w->deleteLater();
|
|
}
|
|
|
|
void CheatsManager::ConnectWidgets()
|
|
{
|
|
connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
|
connect(m_cheat_search_new, &CheatSearchFactoryWidget::NewSessionCreated, this,
|
|
&CheatsManager::OnNewSessionCreated);
|
|
connect(m_tab_widget, &QTabWidget::tabCloseRequested, this, &CheatsManager::OnTabCloseRequested);
|
|
}
|