2018-08-17 11:27:07 +00:00
|
|
|
#include "EditMethodDialog.h"
|
|
|
|
#include "ui_EditMethodDialog.h"
|
|
|
|
|
2019-04-06 12:04:55 +00:00
|
|
|
#include <QComboBox>
|
|
|
|
|
2019-02-02 10:59:58 +00:00
|
|
|
EditMethodDialog::EditMethodDialog(bool classFixed, QWidget *parent) :
|
2018-08-17 11:27:07 +00:00
|
|
|
QDialog(parent),
|
|
|
|
ui(new Ui::EditMethodDialog)
|
|
|
|
{
|
|
|
|
ui->setupUi(this);
|
|
|
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
|
|
|
|
2019-02-02 10:59:58 +00:00
|
|
|
if (classFixed) {
|
|
|
|
classLabel = new QLabel(this);
|
|
|
|
ui->formLayout->setItem(0, QFormLayout::FieldRole, new QWidgetItem(classLabel));
|
|
|
|
} else {
|
|
|
|
classComboBox = new QComboBox(this);
|
|
|
|
ui->formLayout->setItem(0, QFormLayout::FieldRole, new QWidgetItem(classComboBox));
|
2019-02-07 10:42:53 +00:00
|
|
|
for (auto &cls : Core()->getAllAnalClasses(true)) {
|
2019-02-02 10:59:58 +00:00
|
|
|
classComboBox->addItem(cls, cls);
|
|
|
|
}
|
2019-02-01 20:40:34 +00:00
|
|
|
}
|
2018-08-17 11:27:07 +00:00
|
|
|
|
|
|
|
updateVirtualUI();
|
|
|
|
validateInput();
|
|
|
|
|
|
|
|
connect(ui->virtualCheckBox, &QCheckBox::stateChanged, this, &EditMethodDialog::updateVirtualUI);
|
|
|
|
connect(ui->nameEdit, &QLineEdit::textChanged, this, &EditMethodDialog::validateInput);
|
|
|
|
}
|
|
|
|
|
|
|
|
EditMethodDialog::~EditMethodDialog() {}
|
|
|
|
|
|
|
|
void EditMethodDialog::on_buttonBox_accepted()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void EditMethodDialog::on_buttonBox_rejected()
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EditMethodDialog::updateVirtualUI()
|
|
|
|
{
|
|
|
|
bool enabled = ui->virtualCheckBox->isChecked();
|
|
|
|
ui->vtableOffsetEdit->setEnabled(enabled);
|
|
|
|
ui->vtableOffsetLabel->setEnabled(enabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EditMethodDialog::validateInput()
|
|
|
|
{
|
|
|
|
for (auto button : ui->buttonBox->buttons()) {
|
|
|
|
if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) {
|
|
|
|
button->setEnabled(inputValid());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool EditMethodDialog::inputValid()
|
|
|
|
{
|
|
|
|
if (ui->nameEdit->text().isEmpty()) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-02-02 13:14:39 +00:00
|
|
|
// TODO: do more checks here, for example for name clashes
|
2018-08-17 11:27:07 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EditMethodDialog::setClass(const QString &className)
|
|
|
|
{
|
2019-02-02 10:59:58 +00:00
|
|
|
if (classComboBox) {
|
|
|
|
if (className.isEmpty()) {
|
|
|
|
classComboBox->setCurrentIndex(0);
|
|
|
|
return;
|
|
|
|
}
|
2018-08-17 11:27:07 +00:00
|
|
|
|
2019-02-02 10:59:58 +00:00
|
|
|
for (int i=0; i<classComboBox->count(); i++) {
|
|
|
|
QString cls = classComboBox->itemData(i).toString();
|
|
|
|
if (cls == className) {
|
|
|
|
classComboBox->setCurrentIndex(i);
|
|
|
|
break;
|
|
|
|
}
|
2018-08-17 11:27:07 +00:00
|
|
|
}
|
2019-02-02 10:59:58 +00:00
|
|
|
} else {
|
|
|
|
classLabel->setText(className);
|
|
|
|
fixedClass = className;
|
2018-08-17 11:27:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
validateInput();
|
|
|
|
}
|
|
|
|
|
2019-02-01 20:40:34 +00:00
|
|
|
void EditMethodDialog::setMethod(const AnalMethodDescription &desc)
|
2018-08-17 11:27:07 +00:00
|
|
|
{
|
2019-02-01 20:40:34 +00:00
|
|
|
ui->nameEdit->setText(desc.name);
|
|
|
|
ui->addressEdit->setText(desc.addr != RVA_INVALID ? RAddressString(desc.addr) : nullptr);
|
2018-08-17 11:27:07 +00:00
|
|
|
|
2019-02-01 20:40:34 +00:00
|
|
|
if (desc.vtableOffset >= 0) {
|
2018-08-17 11:27:07 +00:00
|
|
|
ui->virtualCheckBox->setChecked(true);
|
2019-02-01 20:40:34 +00:00
|
|
|
ui->vtableOffsetEdit->setText(QString::number(desc.vtableOffset));
|
2018-08-17 11:27:07 +00:00
|
|
|
} else {
|
|
|
|
ui->virtualCheckBox->setChecked(false);
|
|
|
|
ui->vtableOffsetEdit->setText(nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
updateVirtualUI();
|
|
|
|
validateInput();
|
|
|
|
}
|
|
|
|
|
2019-04-06 12:04:55 +00:00
|
|
|
QString EditMethodDialog::getClass() const
|
2018-08-17 11:27:07 +00:00
|
|
|
{
|
2019-02-02 10:59:58 +00:00
|
|
|
if (classComboBox) {
|
|
|
|
int index = classComboBox->currentIndex();
|
|
|
|
if (index < 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return classComboBox->itemData(index).toString();
|
|
|
|
} else {
|
|
|
|
return fixedClass;
|
2018-08-17 11:27:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-06 12:04:55 +00:00
|
|
|
AnalMethodDescription EditMethodDialog::getMethod() const
|
2018-08-17 11:27:07 +00:00
|
|
|
{
|
2019-02-01 20:40:34 +00:00
|
|
|
AnalMethodDescription ret;
|
2018-08-17 11:27:07 +00:00
|
|
|
ret.name = ui->nameEdit->text();
|
|
|
|
ret.addr = Core()->num(ui->addressEdit->text());
|
2019-02-02 10:59:58 +00:00
|
|
|
if (!ui->virtualCheckBox->isChecked()) {
|
2018-08-17 11:27:07 +00:00
|
|
|
ret.vtableOffset = -1;
|
|
|
|
} else {
|
|
|
|
ret.vtableOffset = Core()->num(ui->vtableOffsetEdit->text());
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-02-02 13:14:39 +00:00
|
|
|
bool EditMethodDialog::showDialog(const QString &title, bool classFixed, QString *className, AnalMethodDescription *desc, QWidget *parent)
|
2018-08-17 11:27:07 +00:00
|
|
|
{
|
2019-02-07 12:40:41 +00:00
|
|
|
EditMethodDialog dialog(classFixed, parent);
|
|
|
|
dialog.setWindowTitle(title);
|
|
|
|
dialog.setClass(*className);
|
|
|
|
dialog.setMethod(*desc);
|
|
|
|
int result = dialog.exec();
|
|
|
|
*className = dialog.getClass();
|
|
|
|
*desc = dialog.getMethod();
|
2018-08-17 11:27:07 +00:00
|
|
|
return result == QDialog::DialogCode::Accepted;
|
|
|
|
}
|
|
|
|
|
2019-02-01 20:40:34 +00:00
|
|
|
void EditMethodDialog::newMethod(QString className, const QString &meth, QWidget *parent)
|
2018-08-17 11:27:07 +00:00
|
|
|
{
|
2019-02-01 20:40:34 +00:00
|
|
|
AnalMethodDescription desc;
|
|
|
|
desc.name = meth;
|
|
|
|
desc.vtableOffset = -1;
|
|
|
|
desc.addr = Core()->getOffset();
|
|
|
|
|
2019-02-02 13:14:39 +00:00
|
|
|
if (!showDialog(tr("Create Method"), false, &className, &desc, parent)) {
|
2018-08-17 11:27:07 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-02-01 20:40:34 +00:00
|
|
|
|
|
|
|
Core()->setAnalMethod(className, desc);
|
2018-08-17 11:27:07 +00:00
|
|
|
}
|
|
|
|
|
2019-02-01 20:40:34 +00:00
|
|
|
void EditMethodDialog::editMethod(const QString &className, const QString &meth, QWidget *parent)
|
2018-08-17 11:27:07 +00:00
|
|
|
{
|
2019-02-01 20:40:34 +00:00
|
|
|
AnalMethodDescription desc;
|
|
|
|
if (!Core()->getAnalMethod(className, meth, &desc)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString classNameCopy = className;
|
2019-02-02 13:14:39 +00:00
|
|
|
if (!showDialog(tr("Edit Method"), false, &classNameCopy, &desc, parent)) {
|
2018-08-17 11:27:07 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-02-01 20:40:34 +00:00
|
|
|
if (desc.name != meth) {
|
|
|
|
Core()->renameAnalMethod(className, meth, desc.name);
|
2018-08-17 11:27:07 +00:00
|
|
|
}
|
2019-02-01 20:40:34 +00:00
|
|
|
Core()->setAnalMethod(className, desc);
|
2019-04-06 12:04:55 +00:00
|
|
|
}
|