Merge pull request #6322 from spycrab/qt_gecko_input
Qt/GeckoCodeWidget: Add option to add/remove gecko codes from UI
This commit is contained in:
commit
0eaf3deb1e
|
@ -32,7 +32,7 @@ set(SRCS
|
||||||
Translation.cpp
|
Translation.cpp
|
||||||
WiiUpdate.cpp
|
WiiUpdate.cpp
|
||||||
WiiUpdate.h
|
WiiUpdate.h
|
||||||
Config/ARCodeEditor.cpp
|
Config/CheatCodeEditor.cpp
|
||||||
Config/ARCodeWidget.cpp
|
Config/ARCodeWidget.cpp
|
||||||
Config/CheatWarningWidget.cpp
|
Config/CheatWarningWidget.cpp
|
||||||
Config/ControllersWindow.cpp
|
Config/ControllersWindow.cpp
|
||||||
|
|
|
@ -1,170 +0,0 @@
|
||||||
// Copyright 2018 Dolphin Emulator Project
|
|
||||||
// Licensed under GPLv2+
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#include "DolphinQt2/Config/ARCodeEditor.h"
|
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
|
||||||
#include <QFontDatabase>
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QTextEdit>
|
|
||||||
|
|
||||||
#include "Core/ARDecrypt.h"
|
|
||||||
|
|
||||||
ARCodeEditor::ARCodeEditor(ActionReplay::ARCode& ar) : m_code(ar)
|
|
||||||
{
|
|
||||||
CreateWidgets();
|
|
||||||
ConnectWidgets();
|
|
||||||
|
|
||||||
m_name_edit->setText(QString::fromStdString(ar.name));
|
|
||||||
|
|
||||||
QString s;
|
|
||||||
|
|
||||||
for (ActionReplay::AREntry& e : ar.ops)
|
|
||||||
{
|
|
||||||
s += QStringLiteral("%1 %2\n")
|
|
||||||
.arg(e.cmd_addr, 8, 16, QLatin1Char('0'))
|
|
||||||
.arg(e.value, 8, 16, QLatin1Char('0'));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_code_edit->setText(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ARCodeEditor::CreateWidgets()
|
|
||||||
{
|
|
||||||
m_name_edit = new QLineEdit;
|
|
||||||
m_code_edit = new QTextEdit;
|
|
||||||
m_button_box = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Save);
|
|
||||||
|
|
||||||
QGridLayout* grid_layout = new QGridLayout;
|
|
||||||
|
|
||||||
grid_layout->addWidget(new QLabel(tr("Name:")), 0, 0);
|
|
||||||
grid_layout->addWidget(m_name_edit, 0, 1);
|
|
||||||
grid_layout->addWidget(new QLabel(tr("Code:")), 1, 0);
|
|
||||||
grid_layout->addWidget(m_code_edit, 1, 1);
|
|
||||||
grid_layout->addWidget(m_button_box, 2, 1);
|
|
||||||
|
|
||||||
QFont monospace(QFontDatabase::systemFont(QFontDatabase::FixedFont).family());
|
|
||||||
|
|
||||||
m_code_edit->setFont(monospace);
|
|
||||||
|
|
||||||
setLayout(grid_layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ARCodeEditor::ConnectWidgets()
|
|
||||||
{
|
|
||||||
connect(m_button_box, &QDialogButtonBox::accepted, this, &ARCodeEditor::accept);
|
|
||||||
connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ARCodeEditor::accept()
|
|
||||||
{
|
|
||||||
std::vector<ActionReplay::AREntry> entries;
|
|
||||||
std::vector<std::string> encrypted_lines;
|
|
||||||
|
|
||||||
QStringList lines = m_code_edit->toPlainText().split(QStringLiteral("\n"));
|
|
||||||
|
|
||||||
for (int i = 0; i < lines.size(); i++)
|
|
||||||
{
|
|
||||||
QString line = lines[i];
|
|
||||||
|
|
||||||
if (line.isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QStringList values = line.split(QStringLiteral(" "));
|
|
||||||
|
|
||||||
bool good = true;
|
|
||||||
|
|
||||||
u32 addr = 0;
|
|
||||||
u32 value = 0;
|
|
||||||
|
|
||||||
if (values.size() == 2)
|
|
||||||
{
|
|
||||||
addr = values[0].toUInt(&good, 16);
|
|
||||||
|
|
||||||
if (good)
|
|
||||||
value = values[1].toUInt(&good, 16);
|
|
||||||
|
|
||||||
if (good)
|
|
||||||
entries.push_back(ActionReplay::AREntry(addr, value));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QStringList blocks = line.split(QStringLiteral("-"));
|
|
||||||
|
|
||||||
if (blocks.size() == 3 && blocks[0].size() == 4 && blocks[1].size() == 4 &&
|
|
||||||
blocks[2].size() == 4)
|
|
||||||
{
|
|
||||||
encrypted_lines.emplace_back(blocks[0].toStdString() + blocks[1].toStdString() +
|
|
||||||
blocks[2].toStdString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!good)
|
|
||||||
{
|
|
||||||
auto result = QMessageBox::warning(
|
|
||||||
this, tr("Parsing Error"),
|
|
||||||
tr("Unable to parse line %1 of the entered AR code as a valid "
|
|
||||||
"encrypted or decrypted code. Make sure you typed it correctly.\n\n"
|
|
||||||
"Would you like to ignore this line and continue parsing?")
|
|
||||||
.arg(i + 1),
|
|
||||||
QMessageBox::Ok | QMessageBox::Abort);
|
|
||||||
|
|
||||||
if (result == QMessageBox::Abort)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!encrypted_lines.empty())
|
|
||||||
{
|
|
||||||
if (!entries.empty())
|
|
||||||
{
|
|
||||||
auto result = QMessageBox::warning(
|
|
||||||
this, tr("Invalid Mixed Code"),
|
|
||||||
tr("This Action Replay code contains both encrypted and unencrypted lines; "
|
|
||||||
"you should check that you have entered it correctly.\n\n"
|
|
||||||
"Do you want to discard all unencrypted lines?"),
|
|
||||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
|
||||||
|
|
||||||
// YES = Discard the unencrypted lines then decrypt the encrypted ones instead.
|
|
||||||
// NO = Discard the encrypted lines, keep the unencrypted ones
|
|
||||||
// CANCEL = Stop and let the user go back to editing
|
|
||||||
switch (result)
|
|
||||||
{
|
|
||||||
case QMessageBox::Yes:
|
|
||||||
entries.clear();
|
|
||||||
break;
|
|
||||||
case QMessageBox::No:
|
|
||||||
encrypted_lines.clear();
|
|
||||||
break;
|
|
||||||
case QMessageBox::Cancel:
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ActionReplay::DecryptARCode(encrypted_lines, &entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entries.empty())
|
|
||||||
{
|
|
||||||
QMessageBox::critical(this, tr("Error"),
|
|
||||||
tr("The resulting decrypted AR code doesn't contain any lines."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_code.name = m_name_edit->text().toStdString();
|
|
||||||
m_code.ops = std::move(entries);
|
|
||||||
m_code.active = true;
|
|
||||||
m_code.user_defined = true;
|
|
||||||
|
|
||||||
QDialog::accept();
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
// Copyright 2018 Dolphin Emulator Project
|
|
||||||
// Licensed under GPLv2+
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#include "Core/ActionReplay.h"
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
class QDialogButtonBox;
|
|
||||||
class QLineEdit;
|
|
||||||
class QTextEdit;
|
|
||||||
|
|
||||||
class ARCodeEditor : public QDialog
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit ARCodeEditor(ActionReplay::ARCode& ar);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void CreateWidgets();
|
|
||||||
void ConnectWidgets();
|
|
||||||
|
|
||||||
void accept() override;
|
|
||||||
|
|
||||||
QLineEdit* m_name_edit;
|
|
||||||
QTextEdit* m_code_edit;
|
|
||||||
QDialogButtonBox* m_button_box;
|
|
||||||
|
|
||||||
ActionReplay::ARCode& m_code;
|
|
||||||
};
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
#include "Core/ActionReplay.h"
|
#include "Core/ActionReplay.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "DolphinQt2/Config/ARCodeEditor.h"
|
#include "DolphinQt2/Config/CheatCodeEditor.h"
|
||||||
#include "DolphinQt2/Config/CheatWarningWidget.h"
|
#include "DolphinQt2/Config/CheatWarningWidget.h"
|
||||||
#include "DolphinQt2/GameList/GameFile.h"
|
#include "DolphinQt2/GameList/GameFile.h"
|
||||||
|
|
||||||
|
@ -122,15 +122,19 @@ void ARCodeWidget::SaveCodes()
|
||||||
void ARCodeWidget::OnCodeAddPressed()
|
void ARCodeWidget::OnCodeAddPressed()
|
||||||
{
|
{
|
||||||
ActionReplay::ARCode ar;
|
ActionReplay::ARCode ar;
|
||||||
|
ar.active = true;
|
||||||
|
|
||||||
ARCodeEditor ed(ar);
|
CheatCodeEditor ed;
|
||||||
|
|
||||||
ed.exec();
|
ed.SetARCode(&ar);
|
||||||
|
|
||||||
|
if (ed.exec())
|
||||||
|
{
|
||||||
m_ar_codes.push_back(std::move(ar));
|
m_ar_codes.push_back(std::move(ar));
|
||||||
|
|
||||||
UpdateList();
|
UpdateList();
|
||||||
SaveCodes();
|
SaveCodes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARCodeWidget::OnCodeEditPressed()
|
void ARCodeWidget::OnCodeEditPressed()
|
||||||
|
@ -148,8 +152,9 @@ void ARCodeWidget::OnCodeEditPressed()
|
||||||
|
|
||||||
ActionReplay::ARCode ar = current_ar;
|
ActionReplay::ARCode ar = current_ar;
|
||||||
|
|
||||||
ARCodeEditor ed(user_defined ? current_ar : ar);
|
CheatCodeEditor ed;
|
||||||
|
|
||||||
|
ed.SetARCode(user_defined ? ¤t_ar : &ar);
|
||||||
ed.exec();
|
ed.exec();
|
||||||
|
|
||||||
if (!user_defined)
|
if (!user_defined)
|
||||||
|
|
|
@ -0,0 +1,298 @@
|
||||||
|
// Copyright 2018 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "DolphinQt2/Config/CheatCodeEditor.h"
|
||||||
|
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QFontDatabase>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QTextEdit>
|
||||||
|
|
||||||
|
#include "Core/ARDecrypt.h"
|
||||||
|
#include "Core/ActionReplay.h"
|
||||||
|
#include "Core/GeckoCodeConfig.h"
|
||||||
|
|
||||||
|
CheatCodeEditor::CheatCodeEditor()
|
||||||
|
{
|
||||||
|
CreateWidgets();
|
||||||
|
ConnectWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatCodeEditor::SetARCode(ActionReplay::ARCode* code)
|
||||||
|
{
|
||||||
|
m_name_edit->setText(QString::fromStdString(code->name));
|
||||||
|
|
||||||
|
QString s;
|
||||||
|
|
||||||
|
for (ActionReplay::AREntry& e : code->ops)
|
||||||
|
{
|
||||||
|
s += QStringLiteral("%1 %2\n")
|
||||||
|
.arg(e.cmd_addr, 8, 16, QLatin1Char('0'))
|
||||||
|
.arg(e.value, 8, 16, QLatin1Char('0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_code_edit->setText(s);
|
||||||
|
|
||||||
|
m_creator_label->setHidden(true);
|
||||||
|
m_creator_edit->setHidden(true);
|
||||||
|
m_notes_label->setHidden(true);
|
||||||
|
m_notes_edit->setHidden(true);
|
||||||
|
|
||||||
|
m_ar_code = code;
|
||||||
|
m_gecko_code = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatCodeEditor::SetGeckoCode(Gecko::GeckoCode* code)
|
||||||
|
{
|
||||||
|
m_name_edit->setText(QString::fromStdString(code->name));
|
||||||
|
m_creator_edit->setText(QString::fromStdString(code->creator));
|
||||||
|
|
||||||
|
QString code_string;
|
||||||
|
|
||||||
|
for (const auto& c : code->codes)
|
||||||
|
code_string += QStringLiteral("%1 %2\n")
|
||||||
|
.arg(c.address, 8, 16, QLatin1Char('0'))
|
||||||
|
.arg(c.data, 8, 16, QLatin1Char('0'));
|
||||||
|
|
||||||
|
m_code_edit->setText(code_string);
|
||||||
|
|
||||||
|
QString notes_string;
|
||||||
|
for (const auto& line : code->notes)
|
||||||
|
notes_string += QStringLiteral("%1\n").arg(QString::fromStdString(line));
|
||||||
|
|
||||||
|
m_notes_edit->setText(notes_string);
|
||||||
|
|
||||||
|
m_creator_label->setHidden(false);
|
||||||
|
m_creator_edit->setHidden(false);
|
||||||
|
m_notes_label->setHidden(false);
|
||||||
|
m_notes_edit->setHidden(false);
|
||||||
|
|
||||||
|
m_gecko_code = code;
|
||||||
|
m_ar_code = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatCodeEditor::CreateWidgets()
|
||||||
|
{
|
||||||
|
m_name_edit = new QLineEdit;
|
||||||
|
m_creator_edit = new QLineEdit;
|
||||||
|
m_notes_edit = new QTextEdit;
|
||||||
|
m_code_edit = new QTextEdit;
|
||||||
|
m_button_box = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Save);
|
||||||
|
|
||||||
|
m_creator_label = new QLabel(tr("Creator:"));
|
||||||
|
m_notes_label = new QLabel(tr("Notes:"));
|
||||||
|
|
||||||
|
QGridLayout* grid_layout = new QGridLayout;
|
||||||
|
|
||||||
|
grid_layout->addWidget(new QLabel(tr("Name:")), 0, 0);
|
||||||
|
grid_layout->addWidget(m_name_edit, 0, 1);
|
||||||
|
grid_layout->addWidget(m_creator_label, 1, 0);
|
||||||
|
grid_layout->addWidget(m_creator_edit, 1, 1);
|
||||||
|
grid_layout->addWidget(m_notes_label, 2, 0);
|
||||||
|
grid_layout->addWidget(m_notes_edit, 2, 1);
|
||||||
|
grid_layout->addWidget(new QLabel(tr("Code:")), 3, 0);
|
||||||
|
grid_layout->addWidget(m_code_edit, 3, 1);
|
||||||
|
grid_layout->addWidget(m_button_box, 4, 1);
|
||||||
|
|
||||||
|
QFont monospace(QFontDatabase::systemFont(QFontDatabase::FixedFont).family());
|
||||||
|
|
||||||
|
m_code_edit->setFont(monospace);
|
||||||
|
|
||||||
|
setLayout(grid_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatCodeEditor::ConnectWidgets()
|
||||||
|
{
|
||||||
|
connect(m_button_box, &QDialogButtonBox::accepted, this, &CheatCodeEditor::accept);
|
||||||
|
connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheatCodeEditor::AcceptAR()
|
||||||
|
{
|
||||||
|
std::vector<ActionReplay::AREntry> entries;
|
||||||
|
std::vector<std::string> encrypted_lines;
|
||||||
|
|
||||||
|
QStringList lines = m_code_edit->toPlainText().split(QStringLiteral("\n"));
|
||||||
|
|
||||||
|
for (int i = 0; i < lines.size(); i++)
|
||||||
|
{
|
||||||
|
QString line = lines[i];
|
||||||
|
|
||||||
|
if (line.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QStringList values = line.split(QStringLiteral(" "));
|
||||||
|
|
||||||
|
bool good = true;
|
||||||
|
|
||||||
|
u32 addr = 0;
|
||||||
|
u32 value = 0;
|
||||||
|
|
||||||
|
if (values.size() == 2)
|
||||||
|
{
|
||||||
|
addr = values[0].toUInt(&good, 16);
|
||||||
|
|
||||||
|
if (good)
|
||||||
|
value = values[1].toUInt(&good, 16);
|
||||||
|
|
||||||
|
if (good)
|
||||||
|
entries.push_back(ActionReplay::AREntry(addr, value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QStringList blocks = line.split(QStringLiteral("-"));
|
||||||
|
|
||||||
|
if (blocks.size() == 3 && blocks[0].size() == 4 && blocks[1].size() == 4 &&
|
||||||
|
blocks[2].size() == 4)
|
||||||
|
{
|
||||||
|
encrypted_lines.emplace_back(blocks[0].toStdString() + blocks[1].toStdString() +
|
||||||
|
blocks[2].toStdString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
good = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!good)
|
||||||
|
{
|
||||||
|
auto result = QMessageBox::warning(
|
||||||
|
this, tr("Parsing Error"),
|
||||||
|
tr("Unable to parse line %1 of the entered AR code as a valid "
|
||||||
|
"encrypted or decrypted code. Make sure you typed it correctly.\n\n"
|
||||||
|
"Would you like to ignore this line and continue parsing?")
|
||||||
|
.arg(i + 1),
|
||||||
|
QMessageBox::Ok | QMessageBox::Abort);
|
||||||
|
|
||||||
|
if (result == QMessageBox::Abort)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!encrypted_lines.empty())
|
||||||
|
{
|
||||||
|
if (!entries.empty())
|
||||||
|
{
|
||||||
|
auto result = QMessageBox::warning(
|
||||||
|
this, tr("Invalid Mixed Code"),
|
||||||
|
tr("This Action Replay code contains both encrypted and unencrypted lines; "
|
||||||
|
"you should check that you have entered it correctly.\n\n"
|
||||||
|
"Do you want to discard all unencrypted lines?"),
|
||||||
|
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
||||||
|
|
||||||
|
// YES = Discard the unencrypted lines then decrypt the encrypted ones instead.
|
||||||
|
// NO = Discard the encrypted lines, keep the unencrypted ones
|
||||||
|
// CANCEL = Stop and let the user go back to editing
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case QMessageBox::Yes:
|
||||||
|
entries.clear();
|
||||||
|
break;
|
||||||
|
case QMessageBox::No:
|
||||||
|
encrypted_lines.clear();
|
||||||
|
break;
|
||||||
|
case QMessageBox::Cancel:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ActionReplay::DecryptARCode(encrypted_lines, &entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries.empty())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Error"),
|
||||||
|
tr("The resulting decrypted AR code doesn't contain any lines."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ar_code->name = m_name_edit->text().toStdString();
|
||||||
|
m_ar_code->ops = std::move(entries);
|
||||||
|
m_ar_code->user_defined = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheatCodeEditor::AcceptGecko()
|
||||||
|
{
|
||||||
|
std::vector<Gecko::GeckoCode::Code> entries;
|
||||||
|
|
||||||
|
QStringList lines = m_code_edit->toPlainText().split(QStringLiteral("\n"));
|
||||||
|
|
||||||
|
for (int i = 0; i < lines.size(); i++)
|
||||||
|
{
|
||||||
|
QString line = lines[i];
|
||||||
|
|
||||||
|
if (line.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QStringList values = line.split(QStringLiteral(" "));
|
||||||
|
|
||||||
|
bool good = true;
|
||||||
|
|
||||||
|
u32 addr = 0;
|
||||||
|
u32 value = 0;
|
||||||
|
|
||||||
|
addr = values[0].toUInt(&good, 16);
|
||||||
|
|
||||||
|
if (good)
|
||||||
|
value = values[1].toUInt(&good, 16);
|
||||||
|
|
||||||
|
if (!good)
|
||||||
|
{
|
||||||
|
auto result =
|
||||||
|
QMessageBox::warning(this, tr("Parsing Error"),
|
||||||
|
tr("Unable to parse line %1 of the entered Gecko code as a valid "
|
||||||
|
"code. Make sure you typed it correctly.\n\n"
|
||||||
|
"Would you like to ignore this line and continue parsing?")
|
||||||
|
.arg(i + 1),
|
||||||
|
QMessageBox::Ok | QMessageBox::Abort);
|
||||||
|
|
||||||
|
if (result == QMessageBox::Abort)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Gecko::GeckoCode::Code c;
|
||||||
|
c.address = addr;
|
||||||
|
c.data = value;
|
||||||
|
c.original_line = line.toStdString();
|
||||||
|
|
||||||
|
entries.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries.empty())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Error"),
|
||||||
|
tr("The resulting decrypted AR code doesn't contain any lines."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_gecko_code->name = m_name_edit->text().toStdString();
|
||||||
|
m_gecko_code->creator = m_creator_edit->text().toStdString();
|
||||||
|
m_gecko_code->codes = std::move(entries);
|
||||||
|
m_gecko_code->user_defined = true;
|
||||||
|
|
||||||
|
std::vector<std::string> note_lines;
|
||||||
|
for (QString line : m_notes_edit->toPlainText().split(QStringLiteral("\n")))
|
||||||
|
note_lines.push_back(line.toStdString());
|
||||||
|
|
||||||
|
m_gecko_code->notes = std::move(note_lines);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatCodeEditor::accept()
|
||||||
|
{
|
||||||
|
bool success = m_gecko_code != nullptr ? AcceptGecko() : AcceptAR();
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright 2018 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
class QDialogButtonBox;
|
||||||
|
class QLabel;
|
||||||
|
class QLineEdit;
|
||||||
|
class QTextEdit;
|
||||||
|
|
||||||
|
namespace ActionReplay
|
||||||
|
{
|
||||||
|
struct ARCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Gecko
|
||||||
|
{
|
||||||
|
class GeckoCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CheatCodeEditor : public QDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit CheatCodeEditor();
|
||||||
|
|
||||||
|
void SetARCode(ActionReplay::ARCode* code);
|
||||||
|
void SetGeckoCode(Gecko::GeckoCode* code);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateWidgets();
|
||||||
|
void ConnectWidgets();
|
||||||
|
|
||||||
|
bool AcceptAR();
|
||||||
|
bool AcceptGecko();
|
||||||
|
|
||||||
|
void accept() override;
|
||||||
|
|
||||||
|
QLabel* m_creator_label;
|
||||||
|
QLabel* m_notes_label;
|
||||||
|
|
||||||
|
QLineEdit* m_name_edit;
|
||||||
|
QLineEdit* m_creator_edit;
|
||||||
|
QTextEdit* m_notes_edit;
|
||||||
|
QTextEdit* m_code_edit;
|
||||||
|
QDialogButtonBox* m_button_box;
|
||||||
|
|
||||||
|
ActionReplay::ARCode* m_ar_code = nullptr;
|
||||||
|
Gecko::GeckoCode* m_gecko_code = nullptr;
|
||||||
|
};
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <QFontDatabase>
|
#include <QFontDatabase>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/GeckoCodeConfig.h"
|
#include "Core/GeckoCodeConfig.h"
|
||||||
|
#include "DolphinQt2/Config/CheatCodeEditor.h"
|
||||||
#include "DolphinQt2/Config/CheatWarningWidget.h"
|
#include "DolphinQt2/Config/CheatWarningWidget.h"
|
||||||
#include "DolphinQt2/GameList/GameFile.h"
|
#include "DolphinQt2/GameList/GameFile.h"
|
||||||
|
|
||||||
|
@ -59,9 +61,14 @@ void GeckoCodeWidget::CreateWidgets()
|
||||||
m_code_view->setReadOnly(true);
|
m_code_view->setReadOnly(true);
|
||||||
m_code_view->setFixedHeight(line_height * 10);
|
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 (WiiRD Database)"));
|
m_download_codes = new QPushButton(tr("Download Codes (WiiRD Database)"));
|
||||||
|
|
||||||
m_download_codes->setEnabled(!m_game_id.empty());
|
m_download_codes->setEnabled(!m_game_id.empty());
|
||||||
m_download_codes->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
m_edit_code->setEnabled(false);
|
||||||
|
m_remove_code->setEnabled(false);
|
||||||
|
|
||||||
auto* layout = new QVBoxLayout;
|
auto* layout = new QVBoxLayout;
|
||||||
|
|
||||||
|
@ -85,7 +92,15 @@ void GeckoCodeWidget::CreateWidgets()
|
||||||
layout->addLayout(info_layout);
|
layout->addLayout(info_layout);
|
||||||
layout->addWidget(m_code_description);
|
layout->addWidget(m_code_description);
|
||||||
layout->addWidget(m_code_view);
|
layout->addWidget(m_code_view);
|
||||||
layout->addWidget(m_download_codes, 0, Qt::AlignRight);
|
|
||||||
|
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);
|
setLayout(layout);
|
||||||
}
|
}
|
||||||
|
@ -96,6 +111,8 @@ void GeckoCodeWidget::ConnectWidgets()
|
||||||
&GeckoCodeWidget::OnSelectionChanged);
|
&GeckoCodeWidget::OnSelectionChanged);
|
||||||
connect(m_code_list, &QListWidget::itemChanged, this, &GeckoCodeWidget::OnItemChanged);
|
connect(m_code_list, &QListWidget::itemChanged, this, &GeckoCodeWidget::OnItemChanged);
|
||||||
|
|
||||||
|
connect(m_add_code, &QPushButton::pressed, this, &GeckoCodeWidget::AddCode);
|
||||||
|
connect(m_edit_code, &QPushButton::pressed, this, &GeckoCodeWidget::EditCode);
|
||||||
connect(m_download_codes, &QPushButton::pressed, this, &GeckoCodeWidget::DownloadCodes);
|
connect(m_download_codes, &QPushButton::pressed, this, &GeckoCodeWidget::DownloadCodes);
|
||||||
|
|
||||||
connect(m_warning, &CheatWarningWidget::OpenCheatEnableSettings, this,
|
connect(m_warning, &CheatWarningWidget::OpenCheatEnableSettings, this,
|
||||||
|
@ -106,6 +123,9 @@ void GeckoCodeWidget::OnSelectionChanged()
|
||||||
{
|
{
|
||||||
auto items = m_code_list->selectedItems();
|
auto items = m_code_list->selectedItems();
|
||||||
|
|
||||||
|
m_edit_code->setEnabled(!items.empty());
|
||||||
|
m_remove_code->setEnabled(!items.empty());
|
||||||
|
|
||||||
if (items.empty())
|
if (items.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -136,6 +156,55 @@ void GeckoCodeWidget::OnItemChanged(QListWidgetItem* item)
|
||||||
SaveCodes();
|
SaveCodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GeckoCodeWidget::AddCode()
|
||||||
|
{
|
||||||
|
Gecko::GeckoCode code;
|
||||||
|
code.enabled = true;
|
||||||
|
|
||||||
|
CheatCodeEditor ed;
|
||||||
|
ed.SetGeckoCode(&code);
|
||||||
|
|
||||||
|
if (ed.exec())
|
||||||
|
{
|
||||||
|
m_gecko_codes.push_back(std::move(code));
|
||||||
|
SaveCodes();
|
||||||
|
UpdateList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeckoCodeWidget::EditCode()
|
||||||
|
{
|
||||||
|
const auto* item = m_code_list->currentItem();
|
||||||
|
|
||||||
|
if (item == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int row = m_code_list->row(item);
|
||||||
|
|
||||||
|
CheatCodeEditor ed;
|
||||||
|
|
||||||
|
ed.SetGeckoCode(&m_gecko_codes[row]);
|
||||||
|
|
||||||
|
if (ed.exec())
|
||||||
|
{
|
||||||
|
SaveCodes();
|
||||||
|
UpdateList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeckoCodeWidget::RemoveCode()
|
||||||
|
{
|
||||||
|
const auto* item = m_code_list->currentItem();
|
||||||
|
|
||||||
|
if (item == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_gecko_codes.erase(m_gecko_codes.begin() + m_code_list->row(item));
|
||||||
|
|
||||||
|
UpdateList();
|
||||||
|
SaveCodes();
|
||||||
|
}
|
||||||
|
|
||||||
void GeckoCodeWidget::SaveCodes()
|
void GeckoCodeWidget::SaveCodes()
|
||||||
{
|
{
|
||||||
IniFile game_ini_local;
|
IniFile game_ini_local;
|
||||||
|
|
|
@ -32,10 +32,14 @@ signals:
|
||||||
private:
|
private:
|
||||||
void OnSelectionChanged();
|
void OnSelectionChanged();
|
||||||
void OnItemChanged(QListWidgetItem* item);
|
void OnItemChanged(QListWidgetItem* item);
|
||||||
|
void OnDelete();
|
||||||
|
|
||||||
void CreateWidgets();
|
void CreateWidgets();
|
||||||
void ConnectWidgets();
|
void ConnectWidgets();
|
||||||
void UpdateList();
|
void UpdateList();
|
||||||
|
void AddCode();
|
||||||
|
void EditCode();
|
||||||
|
void RemoveCode();
|
||||||
void DownloadCodes();
|
void DownloadCodes();
|
||||||
void SaveCodes();
|
void SaveCodes();
|
||||||
|
|
||||||
|
@ -49,6 +53,9 @@ private:
|
||||||
QLabel* m_creator_label;
|
QLabel* m_creator_label;
|
||||||
QTextEdit* m_code_description;
|
QTextEdit* m_code_description;
|
||||||
QTextEdit* m_code_view;
|
QTextEdit* m_code_view;
|
||||||
|
QPushButton* m_add_code;
|
||||||
|
QPushButton* m_edit_code;
|
||||||
|
QPushButton* m_remove_code;
|
||||||
QPushButton* m_download_codes;
|
QPushButton* m_download_codes;
|
||||||
std::vector<Gecko::GeckoCode> m_gecko_codes;
|
std::vector<Gecko::GeckoCode> m_gecko_codes;
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
<!--NOTE: When adding moc'd files, you must list outputs in the ClCompile ItemGroup too!-->
|
<!--NOTE: When adding moc'd files, you must list outputs in the ClCompile ItemGroup too!-->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="AboutDialog.h" />
|
<QtMoc Include="AboutDialog.h" />
|
||||||
<QtMoc Include="Config\ARCodeEditor.h" />
|
<QtMoc Include="Config\CheatCodeEditor.h" />
|
||||||
<QtMoc Include="Config\ARCodeWidget.h" />
|
<QtMoc Include="Config\ARCodeWidget.h" />
|
||||||
<QtMoc Include="Config\CheatWarningWidget.h" />
|
<QtMoc Include="Config\CheatWarningWidget.h" />
|
||||||
<QtMoc Include="Config\ControllersWindow.h" />
|
<QtMoc Include="Config\ControllersWindow.h" />
|
||||||
|
@ -118,7 +118,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!--TODO figure out how to get QtMoc to add outputs to ClCompile's inputs...-->
|
<!--TODO figure out how to get QtMoc to add outputs to ClCompile's inputs...-->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="$(QtMocOutPrefix)ARCodeEditor.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)CheatCodeEditor.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)ARCodeWidget.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)ARCodeWidget.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)AboutDialog.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)AboutDialog.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)AdvancedPane.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)AdvancedPane.cpp" />
|
||||||
|
@ -174,7 +174,7 @@
|
||||||
<ClCompile Include="$(QtMocOutPrefix)ToolBar.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)ToolBar.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)WatchWidget.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)WatchWidget.cpp" />
|
||||||
<ClCompile Include="AboutDialog.cpp" />
|
<ClCompile Include="AboutDialog.cpp" />
|
||||||
<ClCompile Include="Config\ARCodeEditor.cpp" />
|
<ClCompile Include="Config\CheatCodeEditor.cpp" />
|
||||||
<ClCompile Include="Config\ARCodeWidget.cpp" />
|
<ClCompile Include="Config\ARCodeWidget.cpp" />
|
||||||
<ClCompile Include="Config\CheatWarningWidget.cpp" />
|
<ClCompile Include="Config\CheatWarningWidget.cpp" />
|
||||||
<ClCompile Include="Config\ControllersWindow.cpp" />
|
<ClCompile Include="Config\ControllersWindow.cpp" />
|
||||||
|
|
Loading…
Reference in New Issue