mirror of https://github.com/stenzek/duckstation
Qt: Add new cheat manager
parent
9f0f24a5e5
commit
b694577c38
@ -0,0 +1,88 @@
|
||||
#include "cheatcodeeditordialog.h"
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
CheatCodeEditorDialog::CheatCodeEditorDialog(CheatList* list, CheatCode* code, QWidget* parent)
|
||||
: m_code(code), QDialog(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
setupAdditionalUi(list);
|
||||
fillUi();
|
||||
connectUi();
|
||||
}
|
||||
|
||||
CheatCodeEditorDialog::~CheatCodeEditorDialog() = default;
|
||||
|
||||
void CheatCodeEditorDialog::saveClicked()
|
||||
{
|
||||
std::string new_description = m_ui.description->text().toStdString();
|
||||
if (new_description.empty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Description cannot be empty."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_code->SetInstructionsFromString(m_ui.instructions->toPlainText().toStdString()))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Instructions are invalid."));
|
||||
return;
|
||||
}
|
||||
|
||||
m_code->description = std::move(new_description);
|
||||
m_code->type = static_cast<CheatCode::Type>(m_ui.type->currentIndex());
|
||||
m_code->activation = static_cast<CheatCode::Activation>(m_ui.activation->currentIndex());
|
||||
m_code->group = m_ui.group->currentText().toStdString();
|
||||
|
||||
done(1);
|
||||
}
|
||||
|
||||
void CheatCodeEditorDialog::cancelClicked()
|
||||
{
|
||||
done(0);
|
||||
}
|
||||
|
||||
void CheatCodeEditorDialog::setupAdditionalUi(CheatList* list)
|
||||
{
|
||||
for (u32 i = 0; i < static_cast<u32>(CheatCode::Type::Count); i++)
|
||||
{
|
||||
m_ui.type->addItem(qApp->translate("Cheats", CheatCode::GetTypeDisplayName(static_cast<CheatCode::Type>(i))));
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < static_cast<u32>(CheatCode::Activation::Count); i++)
|
||||
{
|
||||
m_ui.activation->addItem(
|
||||
qApp->translate("Cheats", CheatCode::GetActivationDisplayName(static_cast<CheatCode::Activation>(i))));
|
||||
}
|
||||
|
||||
const auto groups = list->GetCodeGroups();
|
||||
if (!groups.empty())
|
||||
{
|
||||
for (const std::string& group_name : groups)
|
||||
m_ui.group->addItem(QString::fromStdString(group_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui.group->addItem(QStringLiteral("Ungrouped"));
|
||||
}
|
||||
}
|
||||
|
||||
void CheatCodeEditorDialog::fillUi()
|
||||
{
|
||||
m_ui.description->setText(QString::fromStdString(m_code->description));
|
||||
|
||||
int index = m_ui.group->findText(QString::fromStdString(m_code->group));
|
||||
if (index >= 0)
|
||||
m_ui.group->setCurrentIndex(index);
|
||||
else
|
||||
m_ui.group->setCurrentIndex(0);
|
||||
|
||||
m_ui.type->setCurrentIndex(static_cast<int>(m_code->type));
|
||||
m_ui.activation->setCurrentIndex(static_cast<int>(m_code->activation));
|
||||
|
||||
m_ui.instructions->setPlainText(QString::fromStdString(m_code->GetInstructionsAsString()));
|
||||
}
|
||||
|
||||
void CheatCodeEditorDialog::connectUi()
|
||||
{
|
||||
connect(m_ui.save, &QPushButton::clicked, this, &CheatCodeEditorDialog::saveClicked);
|
||||
connect(m_ui.cancel, &QPushButton::clicked, this, &CheatCodeEditorDialog::cancelClicked);
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "core/cheats.h"
|
||||
#include "ui_cheatcodeeditordialog.h"
|
||||
|
||||
class CheatCodeEditorDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheatCodeEditorDialog(CheatList* list, CheatCode* code, QWidget* parent);
|
||||
~CheatCodeEditorDialog();
|
||||
|
||||
private Q_SLOTS:
|
||||
void saveClicked();
|
||||
void cancelClicked();
|
||||
|
||||
private:
|
||||
void setupAdditionalUi(CheatList* list);
|
||||
void fillUi();
|
||||
void connectUi();
|
||||
|
||||
CheatCode* m_code;
|
||||
|
||||
Ui::CheatCodeEditorDialog m_ui;
|
||||
};
|
||||
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CheatCodeEditorDialog</class>
|
||||
<widget class="QDialog" name="CheatCodeEditorDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>491</width>
|
||||
<height>284</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Cheat Code Editor</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="description"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Group:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="group"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="type"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Activation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="activation"/>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QPlainTextEdit" name="instructions"/>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="save">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancel">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -0,0 +1,689 @@
|
||||
#include "cheatmanagerdialog.h"
|
||||
#include "cheatcodeeditordialog.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/system.h"
|
||||
#include "qthostinterface.h"
|
||||
#include "qtutils.h"
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtGui/QColor>
|
||||
#include <QtWidgets/QFileDialog>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QTreeWidgetItemIterator>
|
||||
#include <array>
|
||||
|
||||
static QString formatHexValue(u32 value)
|
||||
{
|
||||
return QStringLiteral("0x%1").arg(static_cast<uint>(value), 8, 16, QChar('0'));
|
||||
}
|
||||
|
||||
static QString formatValue(u32 value, bool is_signed)
|
||||
{
|
||||
if (is_signed)
|
||||
return QStringLiteral("%1").arg(static_cast<int>(value));
|
||||
else
|
||||
return QStringLiteral("%1").arg(static_cast<uint>(value));
|
||||
}
|
||||
|
||||
CheatManagerDialog::CheatManagerDialog(QWidget* parent) : QDialog(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
setupAdditionalUi();
|
||||
connectUi();
|
||||
|
||||
updateCheatList();
|
||||
}
|
||||
|
||||
CheatManagerDialog::~CheatManagerDialog() = default;
|
||||
|
||||
void CheatManagerDialog::setupAdditionalUi()
|
||||
{
|
||||
m_ui.scanStartAddress->setText(formatHexValue(m_scanner.GetStartAddress()));
|
||||
m_ui.scanEndAddress->setText(formatHexValue(m_scanner.GetEndAddress()));
|
||||
}
|
||||
|
||||
void CheatManagerDialog::connectUi()
|
||||
{
|
||||
connect(m_ui.tabWidget, &QTabWidget::currentChanged, [this](int index) {
|
||||
resizeColumns();
|
||||
setUpdateTimerEnabled(index == 1);
|
||||
});
|
||||
connect(m_ui.cheatList, &QTreeWidget::currentItemChanged, this, &CheatManagerDialog::cheatListCurrentItemChanged);
|
||||
connect(m_ui.cheatList, &QTreeWidget::itemActivated, this, &CheatManagerDialog::cheatListItemActivated);
|
||||
connect(m_ui.cheatList, &QTreeWidget::itemChanged, this, &CheatManagerDialog::cheatListItemChanged);
|
||||
connect(m_ui.cheatListNewCategory, &QPushButton::clicked, this, &CheatManagerDialog::newCategoryClicked);
|
||||
connect(m_ui.cheatListAdd, &QPushButton::clicked, this, &CheatManagerDialog::addCodeClicked);
|
||||
connect(m_ui.cheatListEdit, &QPushButton::clicked, this, &CheatManagerDialog::editCodeClicked);
|
||||
connect(m_ui.cheatListRemove, &QPushButton::clicked, this, &CheatManagerDialog::deleteCodeClicked);
|
||||
connect(m_ui.cheatListActivate, &QPushButton::clicked, this, &CheatManagerDialog::activateCodeClicked);
|
||||
connect(m_ui.cheatListImport, &QPushButton::clicked, this, &CheatManagerDialog::importClicked);
|
||||
connect(m_ui.cheatListExport, &QPushButton::clicked, this, &CheatManagerDialog::exportClicked);
|
||||
|
||||
connect(m_ui.scanValue, &QLineEdit::textChanged, this, &CheatManagerDialog::updateScanValue);
|
||||
connect(m_ui.scanValueBase, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
[this](int index) { updateScanValue(); });
|
||||
connect(m_ui.scanSize, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) {
|
||||
m_scanner.SetSize(static_cast<MemoryAccessSize>(index));
|
||||
m_scanner.ResetSearch();
|
||||
updateResults();
|
||||
});
|
||||
connect(m_ui.scanValueSigned, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) {
|
||||
m_scanner.SetValueSigned(index == 0);
|
||||
m_scanner.ResetSearch();
|
||||
updateResults();
|
||||
});
|
||||
connect(m_ui.scanOperator, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
[this](int index) { m_scanner.SetOperator(static_cast<MemoryScan::Operator>(index)); });
|
||||
connect(m_ui.scanNewSearch, &QPushButton::clicked, [this]() {
|
||||
m_scanner.Search();
|
||||
updateResults();
|
||||
});
|
||||
connect(m_ui.scanSearchAgain, &QPushButton::clicked, [this]() {
|
||||
m_scanner.SearchAgain();
|
||||
updateResults();
|
||||
});
|
||||
connect(m_ui.scanResetSearch, &QPushButton::clicked, [this]() {
|
||||
m_scanner.ResetSearch();
|
||||
updateResults();
|
||||
});
|
||||
connect(m_ui.scanAddWatch, &QPushButton::clicked, this, &CheatManagerDialog::addToWatchClicked);
|
||||
connect(m_ui.scanRemoveWatch, &QPushButton::clicked, this, &CheatManagerDialog::removeWatchClicked);
|
||||
connect(m_ui.scanTable, &QTableWidget::currentItemChanged, this, &CheatManagerDialog::scanCurrentItemChanged);
|
||||
connect(m_ui.watchTable, &QTableWidget::currentItemChanged, this, &CheatManagerDialog::watchCurrentItemChanged);
|
||||
connect(m_ui.scanTable, &QTableWidget::itemChanged, this, &CheatManagerDialog::scanItemChanged);
|
||||
connect(m_ui.watchTable, &QTableWidget::itemChanged, this, &CheatManagerDialog::watchItemChanged);
|
||||
}
|
||||
|
||||
void CheatManagerDialog::showEvent(QShowEvent* event)
|
||||
{
|
||||
QDialog::showEvent(event);
|
||||
resizeColumns();
|
||||
}
|
||||
|
||||
void CheatManagerDialog::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
QDialog::resizeEvent(event);
|
||||
resizeColumns();
|
||||
}
|
||||
|
||||
void CheatManagerDialog::resizeColumns()
|
||||
{
|
||||
QtUtils::ResizeColumnsForTableView(m_ui.scanTable, {-1, 100, 100});
|
||||
QtUtils::ResizeColumnsForTableView(m_ui.watchTable, {50, -1, 100, 150, 100});
|
||||
QtUtils::ResizeColumnsForTreeView(m_ui.cheatList, {-1, 100, 150, 100});
|
||||
}
|
||||
|
||||
void CheatManagerDialog::setUpdateTimerEnabled(bool enabled)
|
||||
{
|
||||
if ((!m_update_timer && !enabled) && m_update_timer->isActive() == enabled)
|
||||
return;
|
||||
|
||||
if (!m_update_timer)
|
||||
{
|
||||
m_update_timer = new QTimer(this);
|
||||
connect(m_update_timer, &QTimer::timeout, this, &CheatManagerDialog::updateScanUi);
|
||||
}
|
||||
|
||||
if (enabled)
|
||||
m_update_timer->start(100);
|
||||
else
|
||||
m_update_timer->stop();
|
||||
}
|
||||
|
||||
int CheatManagerDialog::getSelectedResultIndex() const
|
||||
{
|
||||
QList<QTableWidgetSelectionRange> sel = m_ui.scanTable->selectedRanges();
|
||||
if (sel.isEmpty())
|
||||
return -1;
|
||||
|
||||
return sel.front().topRow();
|
||||
}
|
||||
|
||||
int CheatManagerDialog::getSelectedWatchIndex() const
|
||||
{
|
||||
QList<QTableWidgetSelectionRange> sel = m_ui.watchTable->selectedRanges();
|
||||
if (sel.isEmpty())
|
||||
return -1;
|
||||
|
||||
return sel.front().topRow();
|
||||
}
|
||||
|
||||
QTreeWidgetItem* CheatManagerDialog::getItemForCheatIndex(u32 index) const
|
||||
{
|
||||
QTreeWidgetItemIterator iter(m_ui.cheatList);
|
||||
while (*iter)
|
||||
{
|
||||
QTreeWidgetItem* item = *iter;
|
||||
const QVariant item_data(item->data(0, Qt::UserRole));
|
||||
if (item_data.isValid() && item_data.toUInt() == index)
|
||||
return item;
|
||||
|
||||
++iter;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static u32 getCheatIndexFromItem(QTreeWidgetItem* item)
|
||||
{
|
||||
return item->data(0, Qt::UserRole).toUInt();
|
||||
}
|
||||
|
||||
int CheatManagerDialog::getSelectedCheatIndex() const
|
||||
{
|
||||
QList<QTreeWidgetItem*> sel = m_ui.cheatList->selectedItems();
|
||||
if (sel.isEmpty())
|
||||
return -1;
|
||||
|
||||
return static_cast<int>(getCheatIndexFromItem(sel.first()));
|
||||
}
|
||||
|
||||
CheatList* CheatManagerDialog::getCheatList() const
|
||||
{
|
||||
Assert(System::IsValid());
|
||||
|
||||
CheatList* list = System::GetCheatList();
|
||||
if (!list)
|
||||
QtHostInterface::GetInstance()->LoadCheatListFromGameTitle();
|
||||
if (!list)
|
||||
{
|
||||
QtHostInterface::GetInstance()->executeOnEmulationThread(
|
||||
[]() { System::SetCheatList(std::make_unique<CheatList>()); }, true);
|
||||
list = System::GetCheatList();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void CheatManagerDialog::updateCheatList()
|
||||
{
|
||||
QSignalBlocker sb(m_ui.cheatList);
|
||||
|
||||
CheatList* list = getCheatList();
|
||||
while (m_ui.cheatList->topLevelItemCount() > 0)
|
||||
delete m_ui.cheatList->takeTopLevelItem(0);
|
||||
|
||||
const std::vector<std::string> groups = list->GetCodeGroups();
|
||||
for (const std::string& group_name : groups)
|
||||
{
|
||||
QTreeWidgetItem* group = new QTreeWidgetItem();
|
||||
group->setFlags(group->flags() | Qt::ItemIsUserCheckable);
|
||||
group->setText(0, QString::fromStdString(group_name));
|
||||
m_ui.cheatList->addTopLevelItem(group);
|
||||
|
||||
const u32 count = list->GetCodeCount();
|
||||
bool all_enabled = true;
|
||||
for (u32 i = 0; i < count; i++)
|
||||
{
|
||||
const CheatCode& code = list->GetCode(i);
|
||||
if (code.group != group_name)
|
||||
continue;
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(group);
|
||||
item->setData(0, Qt::UserRole, QVariant(static_cast<uint>(i)));
|
||||
if (code.IsManuallyActivated())
|
||||
{
|
||||
item->setFlags(item->flags() & ~(Qt::ItemIsUserCheckable));
|
||||
}
|
||||
else
|
||||
{
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(0, code.enabled ? Qt::Checked : Qt::Unchecked);
|
||||
}
|
||||
item->setText(0, QString::fromStdString(code.description));
|
||||
item->setText(1, qApp->translate("Cheats", CheatCode::GetTypeDisplayName(code.type)));
|
||||
item->setText(2, qApp->translate("Cheats", CheatCode::GetActivationDisplayName(code.activation)));
|
||||
item->setText(3, QString::number(static_cast<uint>(code.instructions.size())));
|
||||
|
||||
all_enabled &= code.enabled;
|
||||
}
|
||||
|
||||
group->setCheckState(0, all_enabled ? Qt::Checked : Qt::Unchecked);
|
||||
group->setExpanded(true);
|
||||
}
|
||||
|
||||
m_ui.cheatListEdit->setEnabled(false);
|
||||
m_ui.cheatListRemove->setEnabled(false);
|
||||
m_ui.cheatListActivate->setText(tr("Activate"));
|
||||
m_ui.cheatListActivate->setEnabled(false);
|
||||
m_ui.cheatListExport->setEnabled(list->GetCodeCount() > 0);
|
||||
}
|
||||
|
||||
void CheatManagerDialog::saveCheatList()
|
||||
{
|
||||
QtHostInterface::GetInstance()->executeOnEmulationThread([]() { QtHostInterface::GetInstance()->SaveCheatList(); });
|
||||
}
|
||||
|
||||
void CheatManagerDialog::cheatListCurrentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous)
|
||||
{
|
||||
const bool has_current = (current != nullptr);
|
||||
m_ui.cheatListEdit->setEnabled(has_current);
|
||||
m_ui.cheatListRemove->setEnabled(has_current);
|
||||
m_ui.cheatListActivate->setEnabled(has_current);
|
||||
|
||||
if (!current)
|
||||
{
|
||||
m_ui.cheatListActivate->setText(tr("Activate"));
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool manual_activation = getCheatList()->GetCode(getCheatIndexFromItem(current)).IsManuallyActivated();
|
||||
m_ui.cheatListActivate->setText(manual_activation ? tr("Activate") : tr("Toggle"));
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManagerDialog::cheatListItemActivated(QTreeWidgetItem* item)
|
||||
{
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
const u32 index = getCheatIndexFromItem(item);
|
||||
activateCheat(index);
|
||||
}
|
||||
|
||||
void CheatManagerDialog::cheatListItemChanged(QTreeWidgetItem* item, int column)
|
||||
{
|
||||
if (!item || column != 0)
|
||||
return;
|
||||
|
||||
const u32 index = getCheatIndexFromItem(item);
|
||||
CheatList* list = getCheatList();
|
||||
if (index >= list->GetCodeCount())
|
||||
return;
|
||||
|
||||
CheatCode& cc = list->GetCode(index);
|
||||
if (cc.IsManuallyActivated())
|
||||
return;
|
||||
|
||||
const bool new_enabled = (item->checkState(0) == Qt::Checked);
|
||||
if (cc.enabled == new_enabled)
|
||||
return;
|
||||
|
||||
QtHostInterface::GetInstance()->executeOnEmulationThread([index, new_enabled]() {
|
||||
System::GetCheatList()->SetCodeEnabled(index, new_enabled);
|
||||
QtHostInterface::GetInstance()->SaveCheatList();
|
||||
});
|
||||
}
|
||||
|
||||
void CheatManagerDialog::activateCheat(u32 index)
|
||||
{
|
||||
CheatList* list = getCheatList();
|
||||
if (index >= list->GetCodeCount())
|
||||
return;
|
||||
|
||||
CheatCode& cc = list->GetCode(index);
|
||||
if (cc.IsManuallyActivated())
|
||||
{
|
||||
QtHostInterface::GetInstance()->applyCheat(index);
|
||||
return;
|
||||
}
|
||||
|
||||
const bool new_enabled = !cc.enabled;
|
||||
QTreeWidgetItem* item = getItemForCheatIndex(index);
|
||||
if (item)
|
||||
{
|
||||
QSignalBlocker sb(m_ui.cheatList);
|
||||
item->setCheckState(0, new_enabled ? Qt::Checked : Qt::Unchecked);
|
||||
}
|
||||
|
||||
QtHostInterface::GetInstance()->executeOnEmulationThread([index, new_enabled]() {
|
||||
System::GetCheatList()->SetCodeEnabled(index, new_enabled);
|
||||
QtHostInterface::GetInstance()->SaveCheatList();
|
||||
});
|
||||
}
|
||||
|
||||
void CheatManagerDialog::newCategoryClicked()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
void CheatManagerDialog::addCodeClicked()
|
||||
{
|
||||
CheatList* list = getCheatList();
|
||||
|
||||
CheatCode new_code;
|
||||
CheatCodeEditorDialog editor(list, &new_code, this);
|
||||
if (editor.exec() > 0)
|
||||
{
|
||||
QtHostInterface::GetInstance()->executeOnEmulationThread(
|
||||
[this, &new_code]() {
|
||||
System::GetCheatList()->AddCode(std::move(new_code));
|
||||
QtHostInterface::GetInstance()->SaveCheatList();
|
||||
},
|
||||
true);
|
||||
updateCheatList();
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManagerDialog::editCodeClicked()
|
||||
{
|
||||
int index = getSelectedCheatIndex();
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
CheatList* list = getCheatList();
|
||||
if (static_cast<u32>(index) >= list->GetCodeCount())
|
||||
return;
|
||||
|
||||
CheatCode new_code = list->GetCode(static_cast<u32>(index));
|
||||
CheatCodeEditorDialog editor(list, &new_code, this);
|
||||
if (editor.exec() > 0)
|
||||
{
|
||||
QtHostInterface::GetInstance()->executeOnEmulationThread(
|
||||
[index, &new_code]() {
|
||||
System::GetCheatList()->SetCode(static_cast<u32>(index), std::move(new_code));
|
||||
QtHostInterface::GetInstance()->SaveCheatList();
|
||||
},
|
||||
true);
|
||||
updateCheatList();
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManagerDialog::deleteCodeClicked()
|
||||
{
|
||||
int index = getSelectedCheatIndex();
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
CheatList* list = getCheatList();
|
||||
if (static_cast<u32>(index) >= list->GetCodeCount())
|
||||
return;
|
||||
|
||||
if (QMessageBox::question(this, tr("Delete Code"),
|
||||
tr("Are you sure you wish to delete the selected code? This action is not reversible."),
|
||||
QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QtHostInterface::GetInstance()->executeOnEmulationThread(
|
||||
[index]() {
|
||||
System::GetCheatList()->RemoveCode(static_cast<u32>(index));
|
||||
QtHostInterface::GetInstance()->SaveCheatList();
|
||||
},
|
||||
true);
|
||||
updateCheatList();
|
||||
}
|
||||
|
||||
void CheatManagerDialog::activateCodeClicked()
|
||||
{
|
||||
int index = getSelectedCheatIndex();
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
activateCheat(static_cast<u32>(index));
|
||||
}
|
||||
|
||||
void CheatManagerDialog::importClicked()
|
||||
{
|
||||
const QString filter(tr("PCSXR/Libretro Cheat Files (*.cht *.txt);;All Files (*.*)"));
|
||||
const QString filename(QFileDialog::getOpenFileName(this, tr("Import Cheats"), QString(), filter));
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
|
||||
CheatList new_cheats;
|
||||
if (!new_cheats.LoadFromFile(filename.toUtf8().constData(), CheatList::Format::Autodetect))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to parse cheat file. The log may contain more information."));
|
||||
return;
|
||||
}
|
||||
|
||||
QtHostInterface::GetInstance()->executeOnEmulationThread(
|
||||
[&new_cheats]() {
|
||||
DebugAssert(System::HasCheatList());
|
||||
CheatList* list = System::GetCheatList();
|
||||
for (u32 i = 0; i < new_cheats.GetCodeCount(); i++)
|
||||
list->AddCode(new_cheats.GetCode(i));
|
||||
|
||||
QtHostInterface::GetInstance()->SaveCheatList();
|
||||
},
|
||||
true);
|
||||
updateCheatList();
|
||||
}
|
||||
|
||||
void CheatManagerDialog::exportClicked()
|
||||
{
|
||||
const QString filter(tr("PCSXR Cheat Files (*.cht);;All Files (*.*)"));
|
||||
const QString filename(QFileDialog::getSaveFileName(this, tr("Export Cheats"), QString(), filter));
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
|
||||
if (!getCheatList()->SaveToPCSXRFile(filename.toUtf8().constData()))
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to save cheat file. The log may contain more information."));
|
||||
}
|
||||
|
||||
void CheatManagerDialog::addToWatchClicked()
|
||||
{
|
||||
const int index = getSelectedResultIndex();
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
const MemoryScan::Result& res = m_scanner.GetResults()[static_cast<u32>(index)];
|
||||
m_watch.AddEntry(StringUtil::StdStringFromFormat("0x%08x", res.address), res.address, m_scanner.GetSize(),
|
||||
m_scanner.GetValueSigned(), false);
|
||||
updateWatch();
|
||||
}
|
||||
|
||||
void CheatManagerDialog::removeWatchClicked()
|
||||
{
|
||||
const int index = getSelectedWatchIndex();
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
m_watch.RemoveEntry(static_cast<u32>(index));
|
||||
updateWatch();
|
||||
}
|
||||
|
||||
void CheatManagerDialog::scanCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
|
||||
{
|
||||
m_ui.scanAddWatch->setEnabled((current != nullptr));
|
||||
}
|
||||
|
||||
void CheatManagerDialog::watchCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
|
||||
{
|
||||
m_ui.scanRemoveWatch->setEnabled((current != nullptr));
|
||||
}
|
||||
|
||||
void CheatManagerDialog::scanItemChanged(QTableWidgetItem* item)
|
||||
{
|
||||
const u32 index = static_cast<u32>(item->row());
|
||||
switch (item->column())
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
bool value_ok = false;
|
||||
if (m_scanner.GetValueSigned())
|
||||
{
|
||||
int value = item->text().toInt(&value_ok);
|
||||
if (value_ok)
|
||||
m_scanner.SetResultValue(index, static_cast<u32>(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint value = item->text().toUInt(&value_ok);
|
||||
if (value_ok)
|
||||
m_scanner.SetResultValue(index, static_cast<u32>(value));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManagerDialog::watchItemChanged(QTableWidgetItem* item)
|
||||
{
|
||||
const u32 index = static_cast<u32>(item->row());
|
||||
if (index >= m_watch.GetEntryCount())
|
||||
return;
|
||||
|
||||
switch (item->column())
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_watch.SetEntryFreeze(index, (item->checkState() == Qt::Checked));
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
m_watch.SetEntryDescription(index, item->text().toStdString());
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
{
|
||||
const MemoryWatchList::Entry& entry = m_watch.GetEntry(index);
|
||||
bool value_ok = false;
|
||||
if (entry.is_signed)
|
||||
{
|
||||
int value = item->text().toInt(&value_ok);
|
||||
if (value_ok)
|
||||
m_watch.SetEntryValue(index, static_cast<u32>(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint value = item->text().toUInt(&value_ok);
|
||||
if (value_ok)
|
||||
m_watch.SetEntryValue(index, static_cast<u32>(value));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManagerDialog::updateScanValue()
|
||||
{
|
||||
QString value = m_ui.scanValue->text();
|
||||
if (value.startsWith(QStringLiteral("0x")))
|
||||
value.remove(0, 2);
|
||||
|
||||
bool ok = false;
|
||||
uint uint_value = value.toUInt(&ok, (m_ui.scanValueBase->currentIndex() > 0) ? 16 : 10);
|
||||
if (ok)
|
||||
m_scanner.SetValue(uint_value);
|
||||
}
|
||||
|
||||
void CheatManagerDialog::updateResults()
|
||||
{
|
||||
QSignalBlocker sb(m_ui.scanTable);
|
||||
m_ui.scanTable->setRowCount(0);
|
||||
|
||||
const MemoryScan::ResultVector& results = m_scanner.GetResults();
|
||||
if (!results.empty())
|
||||
{
|
||||
int row = 0;
|
||||
for (const MemoryScan::Result& res : m_scanner.GetResults())
|
||||
{
|
||||
m_ui.scanTable->insertRow(row);
|
||||
|
||||
QTableWidgetItem* address_item = new QTableWidgetItem(formatHexValue(res.address));
|
||||
address_item->setFlags(address_item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.scanTable->setItem(row, 0, address_item);
|
||||
|
||||
QTableWidgetItem* value_item = new QTableWidgetItem(formatValue(res.value, m_scanner.GetValueSigned()));
|
||||
m_ui.scanTable->setItem(row, 1, value_item);
|
||||
|
||||
QTableWidgetItem* previous_item = new QTableWidgetItem(formatValue(res.last_value, m_scanner.GetValueSigned()));
|
||||
previous_item->setFlags(address_item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.scanTable->setItem(row, 2, previous_item);
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
m_ui.scanResetSearch->setEnabled(!results.empty());
|
||||
m_ui.scanSearchAgain->setEnabled(!results.empty());
|
||||
m_ui.scanAddWatch->setEnabled(false);
|
||||
}
|
||||
|
||||
void CheatManagerDialog::updateResultsValues()
|
||||
{
|
||||
QSignalBlocker sb(m_ui.scanTable);
|
||||
|
||||
int row = 0;
|
||||
for (const MemoryScan::Result& res : m_scanner.GetResults())
|
||||
{
|
||||
if (res.value_changed)
|
||||
{
|
||||
QTableWidgetItem* item = m_ui.scanTable->item(row, 1);
|
||||
item->setText(formatValue(res.value, m_scanner.GetValueSigned()));
|
||||
item->setForeground(Qt::red);
|
||||
}
|
||||
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManagerDialog::updateWatch()
|
||||
{
|
||||
static constexpr std::array<const char*, 6> size_strings = {
|
||||
{QT_TR_NOOP("Byte"), QT_TR_NOOP("Halfword"), QT_TR_NOOP("Word"), QT_TR_NOOP("Signed Byte"),
|
||||
QT_TR_NOOP("Signed Halfword"), QT_TR_NOOP("Signed Word")}};
|
||||
|
||||
m_watch.UpdateValues();
|
||||
|
||||
QSignalBlocker sb(m_ui.watchTable);
|
||||
m_ui.watchTable->setRowCount(0);
|
||||
|
||||
const MemoryWatchList::EntryVector& entries = m_watch.GetEntries();
|
||||
if (!entries.empty())
|
||||
{
|
||||
int row = 0;
|
||||
for (const MemoryWatchList::Entry& res : entries)
|
||||
{
|
||||
m_ui.watchTable->insertRow(row);
|
||||
|
||||
QTableWidgetItem* freeze_item = new QTableWidgetItem();
|
||||
freeze_item->setFlags(freeze_item->flags() | (Qt::ItemIsEditable | Qt::ItemIsUserCheckable));
|
||||
freeze_item->setCheckState(res.freeze ? Qt::Checked : Qt::Unchecked);
|
||||
m_ui.watchTable->setItem(row, 0, freeze_item);
|
||||
|
||||
QTableWidgetItem* description_item = new QTableWidgetItem(QString::fromStdString(res.description));
|
||||
m_ui.watchTable->setItem(row, 1, description_item);
|
||||
|
||||
QTableWidgetItem* address_item = new QTableWidgetItem(formatHexValue(res.address));
|
||||
address_item->setFlags(address_item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.watchTable->setItem(row, 2, address_item);
|
||||
|
||||
QTableWidgetItem* size_item =
|
||||
new QTableWidgetItem(tr(size_strings[static_cast<u32>(res.size) + (res.is_signed ? 3 : 0)]));
|
||||
size_item->setFlags(address_item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.watchTable->setItem(row, 3, size_item);
|
||||
|
||||
QTableWidgetItem* value_item = new QTableWidgetItem(formatValue(res.value, res.is_signed));
|
||||
m_ui.watchTable->setItem(row, 4, value_item);
|
||||
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
m_ui.scanSaveWatch->setEnabled(!entries.empty());
|
||||
m_ui.scanRemoveWatch->setEnabled(false);
|
||||
}
|
||||
|
||||
void CheatManagerDialog::updateWatchValues()
|
||||
{
|
||||
QSignalBlocker sb(m_ui.watchTable);
|
||||
int row = 0;
|
||||
for (const MemoryWatchList::Entry& res : m_watch.GetEntries())
|
||||
{
|
||||
if (res.changed)
|
||||
m_ui.watchTable->item(row, 4)->setText(formatValue(res.value, res.is_signed));
|
||||
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManagerDialog::updateScanUi()
|
||||
{
|
||||
m_scanner.UpdateResultsValues();
|
||||
m_watch.UpdateValues();
|
||||
|
||||
updateResultsValues();
|
||||
updateWatchValues();
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
#include "core/cheats.h"
|
||||
#include "ui_cheatmanagerdialog.h"
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QTableWidget>
|
||||
#include <optional>
|
||||
|
||||
class CheatManagerDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheatManagerDialog(QWidget* parent);
|
||||
~CheatManagerDialog();
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent* event);
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
|
||||
private Q_SLOTS:
|
||||
void resizeColumns();
|
||||
|
||||
CheatList* getCheatList() const;
|
||||
void updateCheatList();
|
||||
void saveCheatList();
|
||||
void cheatListCurrentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
|
||||
void cheatListItemActivated(QTreeWidgetItem* item);
|
||||
void cheatListItemChanged(QTreeWidgetItem* item, int column);
|
||||
void activateCheat(u32 index);
|
||||
void newCategoryClicked();
|
||||
void addCodeClicked();
|
||||
void editCodeClicked();
|
||||
void deleteCodeClicked();
|
||||
void activateCodeClicked();
|
||||
void importClicked();
|
||||
void exportClicked();
|
||||
|
||||
void addToWatchClicked();
|
||||
void removeWatchClicked();
|
||||
void scanCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
|
||||
void watchCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
|
||||
void scanItemChanged(QTableWidgetItem* item);
|
||||
void watchItemChanged(QTableWidgetItem* item);
|
||||
void updateScanValue();
|
||||
void updateScanUi();
|
||||
|
||||
private:
|
||||
void setupAdditionalUi();
|
||||
void connectUi();
|
||||
void setUpdateTimerEnabled(bool enabled);
|
||||
void updateResults();
|
||||
void updateResultsValues();
|
||||
void updateWatch();
|
||||
void updateWatchValues();
|
||||
|
||||
QTreeWidgetItem* getItemForCheatIndex(u32 index) const;
|
||||
int getSelectedCheatIndex() const;
|
||||
int getSelectedResultIndex() const;
|
||||
int getSelectedWatchIndex() const;
|
||||
|
||||
Ui::CheatManagerDialog m_ui;
|
||||
|
||||
MemoryScan m_scanner;
|
||||
MemoryWatchList m_watch;
|
||||
|
||||
QTimer* m_update_timer = nullptr;
|
||||
};
|
||||
@ -0,0 +1,550 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CheatManagerDialog</class>
|
||||
<widget class="QDialog" name="CheatManagerDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>864</width>
|
||||
<height>599</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Cheat Manager</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Cheat List</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="cheatListNewCategory">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&New Category...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cheatListAdd">
|
||||
<property name="text">
|
||||
<string>&Add Code...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cheatListEdit">
|
||||
<property name="text">
|
||||
<string>&Edit Code...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cheatListRemove">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Delete Code</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cheatListActivate">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Activate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cheatListImport">
|
||||
<property name="text">
|
||||
<string>Import...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cheatListExport">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Export...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTreeWidget" name="cheatList">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Activation</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Instructions</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Memory Scanner</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="scanTable">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Previous Value</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Search Parameters</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Value:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="scanValue"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="scanValueSigned">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Signed</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Unsigned</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="scanValueBase">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Decimal</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hex</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Data Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="scanSize">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Byte (1 byte)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Halfword (2 bytes)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Word (4 bytes)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Operator:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="scanOperator">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Equal to...</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Not Equal to...</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Greater Than...</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Greater or Equal...</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Less Than...</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Less or Equal...</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Increased By...</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Decreased By...</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Changed By...</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Equal to Previous</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Not Equal to Previous</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Greater Than Previous</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Greater or Equal to Previous</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Less Than Previous</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Less or Equal to Previous</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Start Address:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="scanStartAddress"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>End Address:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLineEdit" name="scanEndAddress"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="scanNewSearch">
|
||||
<property name="text">
|
||||
<string>New Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="scanSearchAgain">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Search Again</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="scanResetSearch">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear Results</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="watchTable">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Freeze</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="scanAddWatch">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add To Watch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="scanAddManualAddress">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Manual Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="scanRemoveWatch">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove Watch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="scanLoadWatch">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load Watch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="scanSaveWatch">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Watch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Loading…
Reference in New Issue