From 3a80b111b3e4a13072c02b6a653aa8b501fe6704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Thu, 7 Feb 2019 13:40:41 +0100 Subject: [PATCH] Add Actions to Create/Rename/Delete Classes --- src/Cutter.cpp | 15 ++++++++++ src/Cutter.h | 3 ++ src/dialogs/EditMethodDialog.cpp | 14 ++++----- src/dialogs/RenameDialog.cpp | 13 ++++++++- src/dialogs/RenameDialog.h | 13 +++++++++ src/widgets/ClassesWidget.cpp | 50 +++++++++++++++++++++++++++++++- src/widgets/ClassesWidget.h | 3 ++ src/widgets/ClassesWidget.ui | 15 ++++++++++ 8 files changed, 117 insertions(+), 9 deletions(-) diff --git a/src/Cutter.cpp b/src/Cutter.cpp index 80c6c2cf..0e2c6369 100644 --- a/src/Cutter.cpp +++ b/src/Cutter.cpp @@ -2068,6 +2068,21 @@ QList CutterCore::getAnalClassVTables(const QString &cls) return ret; } +void CutterCore::createNewClass(const QString &cls) +{ + r_anal_class_create(core_->anal, cls.toUtf8().constData()); +} + +void CutterCore::renameClass(const QString &oldName, const QString &newName) +{ + r_anal_class_rename(core_->anal, oldName.toUtf8().constData(), newName.toUtf8().constData()); +} + +void CutterCore::deleteClass(const QString &cls) +{ + r_anal_class_delete(core_->anal, cls.toUtf8().constData()); +} + bool CutterCore::getAnalMethod(const QString &cls, const QString &meth, AnalMethodDescription *desc) { RAnalMethod analMeth; diff --git a/src/Cutter.h b/src/Cutter.h index af44c7bf..6c64d44e 100644 --- a/src/Cutter.h +++ b/src/Cutter.h @@ -484,6 +484,9 @@ public: QList getAnalClassMethods(const QString &cls); QList getAnalClassBaseClasses(const QString &cls); QList getAnalClassVTables(const QString &cls); + void createNewClass(const QString &cls); + void renameClass(const QString &oldName, const QString &newName); + void deleteClass(const QString &cls); bool getAnalMethod(const QString &cls, const QString &meth, AnalMethodDescription *desc); void renameAnalMethod(const QString &className, const QString &oldMethodName, const QString &newMethodName); void setAnalMethod(const QString &cls, const AnalMethodDescription &meth); diff --git a/src/dialogs/EditMethodDialog.cpp b/src/dialogs/EditMethodDialog.cpp index a6102bf3..6001e291 100644 --- a/src/dialogs/EditMethodDialog.cpp +++ b/src/dialogs/EditMethodDialog.cpp @@ -131,13 +131,13 @@ AnalMethodDescription EditMethodDialog::getMethod() bool EditMethodDialog::showDialog(const QString &title, bool classFixed, QString *className, AnalMethodDescription *desc, QWidget *parent) { - auto dialog = new EditMethodDialog(classFixed, parent); - dialog->setWindowTitle(title); - dialog->setClass(*className); - dialog->setMethod(*desc); - int result = dialog->exec(); - *className = dialog->getClass(); - *desc = dialog->getMethod(); + EditMethodDialog dialog(classFixed, parent); + dialog.setWindowTitle(title); + dialog.setClass(*className); + dialog.setMethod(*desc); + int result = dialog.exec(); + *className = dialog.getClass(); + *desc = dialog.getMethod(); return result == QDialog::DialogCode::Accepted; } diff --git a/src/dialogs/RenameDialog.cpp b/src/dialogs/RenameDialog.cpp index e32f19e7..e95ccbe2 100644 --- a/src/dialogs/RenameDialog.cpp +++ b/src/dialogs/RenameDialog.cpp @@ -35,4 +35,15 @@ QString RenameDialog::getName() const void RenameDialog::setPlaceholderText(const QString &text) { ui->nameEdit->setPlaceholderText(text); -} \ No newline at end of file +} + +bool RenameDialog::showDialog(const QString &title, QString *name, const QString &placeholder, QWidget *parent) +{ + RenameDialog dialog(parent); + dialog.setWindowTitle(title); + dialog.setPlaceholderText(placeholder); + dialog.setName(*name); + int result = dialog.exec(); + *name = dialog.getName(); + return result == QDialog::DialogCode::Accepted; +} diff --git a/src/dialogs/RenameDialog.h b/src/dialogs/RenameDialog.h index 2ba5bb94..666c83b3 100644 --- a/src/dialogs/RenameDialog.h +++ b/src/dialogs/RenameDialog.h @@ -8,6 +8,9 @@ namespace Ui { class RenameDialog; } +/*! + * \brief General Dialog for entering a name + */ class RenameDialog : public QDialog { Q_OBJECT @@ -21,6 +24,16 @@ public: void setPlaceholderText(const QString &text); + /*! + * \brief Helper function to display and execute the dialog + * + * \param title title of the dialog + * \param name initial name, will be overwritten if the user entered something else + * \param placeholder placeholder text for the QLineEdit + * \return whether the dialog was accepted by the user + */ + static bool showDialog(const QString &title, QString *name, const QString &placeholder, QWidget *parent = nullptr); + private slots: void on_buttonBox_accepted(); diff --git a/src/widgets/ClassesWidget.cpp b/src/widgets/ClassesWidget.cpp index a078b14e..75c7bcb5 100644 --- a/src/widgets/ClassesWidget.cpp +++ b/src/widgets/ClassesWidget.cpp @@ -6,6 +6,7 @@ #include "ui_ClassesWidget.h" #include "common/Helpers.h" #include "dialogs/EditMethodDialog.h" +#include "dialogs/RenameDialog.h" #include @@ -648,12 +649,22 @@ void ClassesWidget::showContextMenu(const QPoint &pt) if (!index.isValid()) { return; } + auto type = static_cast(index.data(ClassesModel::TypeRole).toInt()); QMenu menu(ui->classesTreeView); + menu.addAction(ui->newClassAction); + + if (type == ClassesModel::RowType::Class) { + menu.addAction(ui->renameClassAction); + menu.addAction(ui->deleteClassAction); + } + + menu.addSeparator(); + menu.addAction(ui->addMethodAction); - if (index.data(ClassesModel::TypeRole).toInt() == static_cast(ClassesModel::RowType::Method)) { + if (type == ClassesModel::RowType::Method) { menu.addAction(ui->editMethodAction); QString className = index.parent().data(ClassesModel::NameRole).toString(); @@ -716,3 +727,40 @@ void ClassesWidget::on_editMethodAction_triggered() QString methName = index.data(ClassesModel::NameRole).toString(); EditMethodDialog::editMethod(className, methName, this); } + + +void ClassesWidget::on_newClassAction_triggered() +{ + QString name; + if (!RenameDialog::showDialog(tr("Create new Class"), &name, tr("Class Name"), this) || name.isEmpty()) { + return; + } + Core()->createNewClass(name); +} + +void ClassesWidget::on_deleteClassAction_triggered() +{ + QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex(); + if (!index.isValid() || index.data(ClassesModel::TypeRole).toInt() != static_cast(ClassesModel::RowType::Class)) { + return; + } + QString className = index.data(ClassesModel::NameRole).toString(); + if (QMessageBox::question(this, tr("Delete Class"), tr("Are you sure you want to delete the class %1?").arg(className)) != QMessageBox::StandardButton::Yes) { + return; + } + Core()->deleteClass(className); +} + +void ClassesWidget::on_renameClassAction_triggered() +{ + QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex(); + if (!index.isValid() || index.data(ClassesModel::TypeRole).toInt() != static_cast(ClassesModel::RowType::Class)) { + return; + } + QString oldName = index.data(ClassesModel::NameRole).toString(); + QString newName = oldName; + if (!RenameDialog::showDialog(tr("Rename Class %1").arg(oldName), &newName, tr("Class Name"), this) || newName.isEmpty()) { + return; + } + Core()->renameClass(oldName, newName); +} diff --git a/src/widgets/ClassesWidget.h b/src/widgets/ClassesWidget.h index 443c936c..89300267 100644 --- a/src/widgets/ClassesWidget.h +++ b/src/widgets/ClassesWidget.h @@ -176,6 +176,9 @@ private slots: void on_seekToVTableAction_triggered(); void on_addMethodAction_triggered(); void on_editMethodAction_triggered(); + void on_newClassAction_triggered(); + void on_deleteClassAction_triggered(); + void on_renameClassAction_triggered(); void showContextMenu(const QPoint &pt); diff --git a/src/widgets/ClassesWidget.ui b/src/widgets/ClassesWidget.ui index cb104bfe..42839c0d 100644 --- a/src/widgets/ClassesWidget.ui +++ b/src/widgets/ClassesWidget.ui @@ -119,6 +119,21 @@ Add Method + + + Create new Class + + + + + Rename Class + + + + + Delete Class + +