citra_qt: Implement UI for adding/editing/deleting cheats
The UI file is rewritten, to better make use of Qt's layouts (instead of depending on abstract geometry). "Add Cheat", "Save", "Delete" buttons are also added. The UI logic should be rather easy and usable (IMO), but the code may seem a bit dirty. If anyone has a better idea regarding UI logic design or code implementation, feel free to tell me about it.
This commit is contained in:
parent
573036b38e
commit
433176a9b9
3 changed files with 395 additions and 180 deletions
|
@ -3,10 +3,12 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QMessageBox>
|
||||
#include <QTableWidgetItem>
|
||||
#include "citra_qt/cheats.h"
|
||||
#include "core/cheats/cheat_base.h"
|
||||
#include "core/cheats/cheats.h"
|
||||
#include "core/cheats/gateway_cheat.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "ui_cheats.h"
|
||||
|
@ -21,14 +23,23 @@ CheatDialog::CheatDialog(QWidget* parent)
|
|||
ui->tableCheats->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
|
||||
ui->tableCheats->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
ui->tableCheats->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Fixed);
|
||||
ui->textDetails->setEnabled(false);
|
||||
ui->lineName->setEnabled(false);
|
||||
ui->textCode->setEnabled(false);
|
||||
ui->textNotes->setEnabled(false);
|
||||
const auto game_id = fmt::format(
|
||||
"{:016X}", Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id);
|
||||
ui->labelTitle->setText(tr("Title ID: %1").arg(QString::fromStdString(game_id)));
|
||||
|
||||
connect(ui->buttonClose, &QPushButton::released, this, &CheatDialog::OnCancel);
|
||||
connect(ui->buttonAddCheat, &QPushButton::released, this, &CheatDialog::OnAddCheat);
|
||||
connect(ui->tableCheats, &QTableWidget::cellClicked, this, &CheatDialog::OnRowSelected);
|
||||
connect(ui->lineName, &QLineEdit::textEdited, this, &CheatDialog::OnTextEdited);
|
||||
connect(ui->textNotes, &QPlainTextEdit::textChanged, this, &CheatDialog::OnTextEdited);
|
||||
connect(ui->textCode, &QPlainTextEdit::textChanged, this, &CheatDialog::OnTextEdited);
|
||||
|
||||
connect(ui->buttonSave, &QPushButton::released,
|
||||
[this] { SaveCheat(ui->tableCheats->currentRow()); });
|
||||
connect(ui->buttonDelete, &QPushButton::released, this, &CheatDialog::OnDeleteCheat);
|
||||
|
||||
LoadCheats();
|
||||
}
|
||||
|
@ -36,7 +47,7 @@ CheatDialog::CheatDialog(QWidget* parent)
|
|||
CheatDialog::~CheatDialog() = default;
|
||||
|
||||
void CheatDialog::LoadCheats() {
|
||||
const auto& cheats = Core::System::GetInstance().CheatEngine().GetCheats();
|
||||
cheats = Core::System::GetInstance().CheatEngine().GetCheats();
|
||||
|
||||
ui->tableCheats->setRowCount(cheats.size());
|
||||
|
||||
|
@ -56,20 +67,184 @@ void CheatDialog::LoadCheats() {
|
|||
}
|
||||
}
|
||||
|
||||
bool CheatDialog::CheckSaveCheat() {
|
||||
auto answer = QMessageBox::warning(
|
||||
this, tr("Cheats"), tr("Would you like to save the current cheat?"),
|
||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Cancel);
|
||||
|
||||
if (answer == QMessageBox::Yes) {
|
||||
return SaveCheat(last_row);
|
||||
} else {
|
||||
return answer != QMessageBox::Cancel;
|
||||
}
|
||||
}
|
||||
|
||||
bool CheatDialog::SaveCheat(int row) {
|
||||
if (ui->lineName->text().isEmpty()) {
|
||||
QMessageBox::critical(this, tr("Save Cheat"), tr("Please enter a cheat name."));
|
||||
return false;
|
||||
}
|
||||
if (ui->textCode->toPlainText().isEmpty()) {
|
||||
QMessageBox::critical(this, tr("Save Cheat"), tr("Please enter the cheat code."));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the cheat lines are valid
|
||||
auto code_lines = ui->textCode->toPlainText().split("\n", QString::SkipEmptyParts);
|
||||
for (int i = 0; i < code_lines.size(); ++i) {
|
||||
Cheats::GatewayCheat::CheatLine cheat_line(code_lines[i].toStdString());
|
||||
if (cheat_line.valid)
|
||||
continue;
|
||||
|
||||
auto answer = QMessageBox::warning(
|
||||
this, tr("Save Cheat"),
|
||||
tr("Cheat code line %1 is not valid.\nWould you like to ignore the error and continue?")
|
||||
.arg(i + 1),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
if (answer == QMessageBox::No)
|
||||
return false;
|
||||
}
|
||||
|
||||
auto cheat = std::make_shared<Cheats::GatewayCheat>(ui->lineName->text().toStdString(),
|
||||
ui->textCode->toPlainText().toStdString(),
|
||||
ui->textNotes->toPlainText().toStdString());
|
||||
|
||||
if (newly_created) {
|
||||
Core::System::GetInstance().CheatEngine().AddCheat(cheat);
|
||||
newly_created = false;
|
||||
} else {
|
||||
Core::System::GetInstance().CheatEngine().UpdateCheat(row, cheat);
|
||||
}
|
||||
Core::System::GetInstance().CheatEngine().SaveCheatFile();
|
||||
|
||||
int previous_row = ui->tableCheats->currentRow();
|
||||
int previous_col = ui->tableCheats->currentColumn();
|
||||
LoadCheats();
|
||||
ui->tableCheats->setCurrentCell(previous_row, previous_col);
|
||||
|
||||
edited = false;
|
||||
ui->buttonSave->setEnabled(false);
|
||||
ui->buttonAddCheat->setEnabled(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CheatDialog::closeEvent(QCloseEvent* event) {
|
||||
if (edited && !CheckSaveCheat()) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void CheatDialog::OnCancel() {
|
||||
close();
|
||||
}
|
||||
|
||||
void CheatDialog::OnRowSelected(int row, int column) {
|
||||
ui->textDetails->setEnabled(true);
|
||||
if (row == last_row) {
|
||||
return;
|
||||
}
|
||||
if (edited && !CheckSaveCheat()) {
|
||||
ui->tableCheats->setCurrentCell(last_row, last_col);
|
||||
return;
|
||||
}
|
||||
if (row < cheats.size()) {
|
||||
if (newly_created) {
|
||||
// Remove the newly created dummy item
|
||||
newly_created = false;
|
||||
ui->tableCheats->setRowCount(ui->tableCheats->rowCount() - 1);
|
||||
}
|
||||
|
||||
const auto& current_cheat = cheats[row];
|
||||
ui->lineName->setText(QString::fromStdString(current_cheat->GetName()));
|
||||
ui->textNotes->setPlainText(QString::fromStdString(current_cheat->GetComments()));
|
||||
ui->textCode->setPlainText(QString::fromStdString(current_cheat->GetCode()));
|
||||
}
|
||||
|
||||
edited = false;
|
||||
ui->buttonSave->setEnabled(false);
|
||||
ui->buttonDelete->setEnabled(true);
|
||||
ui->buttonAddCheat->setEnabled(true);
|
||||
ui->lineName->setEnabled(true);
|
||||
ui->textCode->setEnabled(true);
|
||||
ui->textNotes->setEnabled(true);
|
||||
const auto& current_cheat = Core::System::GetInstance().CheatEngine().GetCheats()[row];
|
||||
ui->textNotes->setPlainText(QString::fromStdString(current_cheat->GetComments()));
|
||||
ui->textDetails->setPlainText(QString::fromStdString(current_cheat->ToString()));
|
||||
|
||||
last_row = row;
|
||||
last_col = column;
|
||||
}
|
||||
|
||||
void CheatDialog::OnCheckChanged(int state) {
|
||||
const QCheckBox* checkbox = qobject_cast<QCheckBox*>(sender());
|
||||
int row = static_cast<int>(checkbox->property("row").toInt());
|
||||
Core::System::GetInstance().CheatEngine().GetCheats()[row]->SetEnabled(state);
|
||||
cheats[row]->SetEnabled(state);
|
||||
Core::System::GetInstance().CheatEngine().SaveCheatFile();
|
||||
}
|
||||
|
||||
void CheatDialog::OnTextEdited() {
|
||||
edited = true;
|
||||
ui->buttonSave->setEnabled(true);
|
||||
}
|
||||
|
||||
void CheatDialog::OnDeleteCheat() {
|
||||
if (newly_created) {
|
||||
newly_created = false;
|
||||
} else {
|
||||
Core::System::GetInstance().CheatEngine().RemoveCheat(ui->tableCheats->currentRow());
|
||||
Core::System::GetInstance().CheatEngine().SaveCheatFile();
|
||||
}
|
||||
|
||||
LoadCheats();
|
||||
if (cheats.empty()) {
|
||||
ui->lineName->setText("");
|
||||
ui->textCode->setPlainText("");
|
||||
ui->textNotes->setPlainText("");
|
||||
ui->lineName->setEnabled(false);
|
||||
ui->textCode->setEnabled(false);
|
||||
ui->textNotes->setEnabled(false);
|
||||
ui->buttonDelete->setEnabled(false);
|
||||
last_row = last_col = -1;
|
||||
} else {
|
||||
if (last_row >= ui->tableCheats->rowCount()) {
|
||||
last_row = ui->tableCheats->rowCount() - 1;
|
||||
}
|
||||
ui->tableCheats->setCurrentCell(last_row, last_col);
|
||||
|
||||
const auto& current_cheat = cheats[last_row];
|
||||
ui->lineName->setText(QString::fromStdString(current_cheat->GetName()));
|
||||
ui->textNotes->setPlainText(QString::fromStdString(current_cheat->GetComments()));
|
||||
ui->textCode->setPlainText(QString::fromStdString(current_cheat->GetCode()));
|
||||
}
|
||||
|
||||
edited = false;
|
||||
ui->buttonSave->setEnabled(false);
|
||||
ui->buttonAddCheat->setEnabled(true);
|
||||
}
|
||||
|
||||
void CheatDialog::OnAddCheat() {
|
||||
if (edited && !CheckSaveCheat()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int row = ui->tableCheats->rowCount();
|
||||
ui->tableCheats->setRowCount(row + 1);
|
||||
ui->tableCheats->setCurrentCell(row, 1);
|
||||
|
||||
// create a dummy item
|
||||
ui->tableCheats->setItem(row, 1, new QTableWidgetItem(tr("[new cheat]")));
|
||||
ui->tableCheats->setItem(row, 2, new QTableWidgetItem(""));
|
||||
ui->lineName->setText("");
|
||||
ui->lineName->setPlaceholderText(tr("[new cheat]"));
|
||||
ui->textCode->setPlainText("");
|
||||
ui->textNotes->setPlainText("");
|
||||
ui->lineName->setEnabled(true);
|
||||
ui->textCode->setEnabled(true);
|
||||
ui->textNotes->setEnabled(true);
|
||||
ui->buttonSave->setEnabled(true);
|
||||
ui->buttonDelete->setEnabled(true);
|
||||
ui->buttonAddCheat->setEnabled(false);
|
||||
|
||||
edited = false;
|
||||
newly_created = true;
|
||||
last_row = row;
|
||||
last_col = 1;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue