Add Actions to Create/Rename/Delete Classes

This commit is contained in:
Florian Märkl 2019-02-07 13:40:41 +01:00
parent 277a0ada2f
commit 3a80b111b3
8 changed files with 117 additions and 9 deletions

View File

@ -2068,6 +2068,21 @@ QList<AnalVTableDescription> CutterCore::getAnalClassVTables(const QString &cls)
return ret; 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) bool CutterCore::getAnalMethod(const QString &cls, const QString &meth, AnalMethodDescription *desc)
{ {
RAnalMethod analMeth; RAnalMethod analMeth;

View File

@ -484,6 +484,9 @@ public:
QList<AnalMethodDescription> getAnalClassMethods(const QString &cls); QList<AnalMethodDescription> getAnalClassMethods(const QString &cls);
QList<AnalBaseClassDescription> getAnalClassBaseClasses(const QString &cls); QList<AnalBaseClassDescription> getAnalClassBaseClasses(const QString &cls);
QList<AnalVTableDescription> getAnalClassVTables(const QString &cls); QList<AnalVTableDescription> 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); bool getAnalMethod(const QString &cls, const QString &meth, AnalMethodDescription *desc);
void renameAnalMethod(const QString &className, const QString &oldMethodName, const QString &newMethodName); void renameAnalMethod(const QString &className, const QString &oldMethodName, const QString &newMethodName);
void setAnalMethod(const QString &cls, const AnalMethodDescription &meth); void setAnalMethod(const QString &cls, const AnalMethodDescription &meth);

View File

@ -131,13 +131,13 @@ AnalMethodDescription EditMethodDialog::getMethod()
bool EditMethodDialog::showDialog(const QString &title, bool classFixed, QString *className, AnalMethodDescription *desc, QWidget *parent) bool EditMethodDialog::showDialog(const QString &title, bool classFixed, QString *className, AnalMethodDescription *desc, QWidget *parent)
{ {
auto dialog = new EditMethodDialog(classFixed, parent); EditMethodDialog dialog(classFixed, parent);
dialog->setWindowTitle(title); dialog.setWindowTitle(title);
dialog->setClass(*className); dialog.setClass(*className);
dialog->setMethod(*desc); dialog.setMethod(*desc);
int result = dialog->exec(); int result = dialog.exec();
*className = dialog->getClass(); *className = dialog.getClass();
*desc = dialog->getMethod(); *desc = dialog.getMethod();
return result == QDialog::DialogCode::Accepted; return result == QDialog::DialogCode::Accepted;
} }

View File

@ -36,3 +36,14 @@ void RenameDialog::setPlaceholderText(const QString &text)
{ {
ui->nameEdit->setPlaceholderText(text); ui->nameEdit->setPlaceholderText(text);
} }
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;
}

View File

@ -8,6 +8,9 @@ namespace Ui {
class RenameDialog; class RenameDialog;
} }
/*!
* \brief General Dialog for entering a name
*/
class RenameDialog : public QDialog class RenameDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
@ -21,6 +24,16 @@ public:
void setPlaceholderText(const QString &text); 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: private slots:
void on_buttonBox_accepted(); void on_buttonBox_accepted();

View File

@ -6,6 +6,7 @@
#include "ui_ClassesWidget.h" #include "ui_ClassesWidget.h"
#include "common/Helpers.h" #include "common/Helpers.h"
#include "dialogs/EditMethodDialog.h" #include "dialogs/EditMethodDialog.h"
#include "dialogs/RenameDialog.h"
#include <QMenu> #include <QMenu>
@ -648,12 +649,22 @@ void ClassesWidget::showContextMenu(const QPoint &pt)
if (!index.isValid()) { if (!index.isValid()) {
return; return;
} }
auto type = static_cast<ClassesModel::RowType>(index.data(ClassesModel::TypeRole).toInt());
QMenu menu(ui->classesTreeView); 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); menu.addAction(ui->addMethodAction);
if (index.data(ClassesModel::TypeRole).toInt() == static_cast<int>(ClassesModel::RowType::Method)) { if (type == ClassesModel::RowType::Method) {
menu.addAction(ui->editMethodAction); menu.addAction(ui->editMethodAction);
QString className = index.parent().data(ClassesModel::NameRole).toString(); QString className = index.parent().data(ClassesModel::NameRole).toString();
@ -716,3 +727,40 @@ void ClassesWidget::on_editMethodAction_triggered()
QString methName = index.data(ClassesModel::NameRole).toString(); QString methName = index.data(ClassesModel::NameRole).toString();
EditMethodDialog::editMethod(className, methName, this); 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<int>(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<int>(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);
}

View File

@ -176,6 +176,9 @@ private slots:
void on_seekToVTableAction_triggered(); void on_seekToVTableAction_triggered();
void on_addMethodAction_triggered(); void on_addMethodAction_triggered();
void on_editMethodAction_triggered(); void on_editMethodAction_triggered();
void on_newClassAction_triggered();
void on_deleteClassAction_triggered();
void on_renameClassAction_triggered();
void showContextMenu(const QPoint &pt); void showContextMenu(const QPoint &pt);

View File

@ -119,6 +119,21 @@
<string>Add Method</string> <string>Add Method</string>
</property> </property>
</action> </action>
<action name="newClassAction">
<property name="text">
<string>Create new Class</string>
</property>
</action>
<action name="renameClassAction">
<property name="text">
<string>Rename Class</string>
</property>
</action>
<action name="deleteClassAction">
<property name="text">
<string>Delete Class</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>