mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-31 08:37:26 +00:00
Global variable actions and Show in action and refactoring (#2295)
* Show in action for global variables and functions * Copy address of global variable or function referenced by the cursor selection * Rename global variable
This commit is contained in:
parent
eef9baa300
commit
37fc01478f
@ -927,12 +927,19 @@ void MainWindow::showMemoryWidget(MemoryWidgetType type)
|
|||||||
memoryDockWidget->raiseMemoryWidget();
|
memoryDockWidget->raiseMemoryWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
QMenu *MainWindow::createShowInMenu(QWidget *parent, RVA address)
|
QMenu *MainWindow::createShowInMenu(QWidget *parent, RVA address, AddressTypeHint addressType)
|
||||||
{
|
{
|
||||||
QMenu *menu = new QMenu(parent);
|
QMenu *menu = new QMenu(parent);
|
||||||
// Memory dock widgets
|
// Memory dock widgets
|
||||||
for (auto &dock : dockWidgets) {
|
for (auto &dock : dockWidgets) {
|
||||||
if (auto memoryWidget = qobject_cast<MemoryDockWidget *>(dock)) {
|
if (auto memoryWidget = qobject_cast<MemoryDockWidget *>(dock)) {
|
||||||
|
if (memoryWidget->getType() == MemoryWidgetType::Graph
|
||||||
|
|| memoryWidget->getType() == MemoryWidgetType::Decompiler)
|
||||||
|
{
|
||||||
|
if (addressType == AddressTypeHint::Data) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
QAction *action = new QAction(memoryWidget->windowTitle(), menu);
|
QAction *action = new QAction(memoryWidget->windowTitle(), menu);
|
||||||
connect(action, &QAction::triggered, this, [memoryWidget, address]() {
|
connect(action, &QAction::triggered, this, [memoryWidget, address]() {
|
||||||
memoryWidget->getSeekable()->seek(address);
|
memoryWidget->getSeekable()->seek(address);
|
||||||
@ -965,7 +972,9 @@ QMenu *MainWindow::createShowInMenu(QWidget *parent, RVA address)
|
|||||||
menu->addAction(action);
|
menu->addAction(action);
|
||||||
};
|
};
|
||||||
createAddNewWidgetAction(tr("New disassembly"), MemoryWidgetType::Disassembly);
|
createAddNewWidgetAction(tr("New disassembly"), MemoryWidgetType::Disassembly);
|
||||||
|
if (addressType != AddressTypeHint::Data) {
|
||||||
createAddNewWidgetAction(tr("New graph"), MemoryWidgetType::Graph);
|
createAddNewWidgetAction(tr("New graph"), MemoryWidgetType::Graph);
|
||||||
|
}
|
||||||
createAddNewWidgetAction(tr("New hexdump"), MemoryWidgetType::Hexdump);
|
createAddNewWidgetAction(tr("New hexdump"), MemoryWidgetType::Hexdump);
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
|
@ -121,8 +121,8 @@ public:
|
|||||||
QString getUniqueObjectName(const QString &widgetType) const;
|
QString getUniqueObjectName(const QString &widgetType) const;
|
||||||
void showMemoryWidget();
|
void showMemoryWidget();
|
||||||
void showMemoryWidget(MemoryWidgetType type);
|
void showMemoryWidget(MemoryWidgetType type);
|
||||||
|
enum class AddressTypeHint { Function, Data, Unknown };
|
||||||
QMenu *createShowInMenu(QWidget *parent, RVA address);
|
QMenu *createShowInMenu(QWidget *parent, RVA address, AddressTypeHint addressType = AddressTypeHint::Unknown);
|
||||||
void setCurrentMemoryWidget(MemoryDockWidget* memoryWidget);
|
void setCurrentMemoryWidget(MemoryDockWidget* memoryWidget);
|
||||||
MemoryDockWidget* getLastMemoryWidget();
|
MemoryDockWidget* getLastMemoryWidget();
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "dialogs/BreakpointsDialog.h"
|
#include "dialogs/BreakpointsDialog.h"
|
||||||
#include "dialogs/CommentsDialog.h"
|
#include "dialogs/CommentsDialog.h"
|
||||||
|
#include "common/Configuration.h"
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
@ -14,27 +15,36 @@
|
|||||||
|
|
||||||
DecompilerContextMenu::DecompilerContextMenu(QWidget *parent, MainWindow *mainWindow)
|
DecompilerContextMenu::DecompilerContextMenu(QWidget *parent, MainWindow *mainWindow)
|
||||||
: QMenu(parent),
|
: QMenu(parent),
|
||||||
|
curHighlightedWord(QString()),
|
||||||
offset(0),
|
offset(0),
|
||||||
isTogglingBreakpoints(false),
|
isTogglingBreakpoints(false),
|
||||||
mainWindow(mainWindow),
|
mainWindow(mainWindow),
|
||||||
annotationHere(nullptr),
|
annotationHere(nullptr),
|
||||||
actionCopy(tr("Copy"), this),
|
actionCopy(tr("Copy"), this),
|
||||||
|
actionCopyInstructionAddress(tr("Copy instruction address (<address>)"), this),
|
||||||
|
actionCopyReferenceAddress(tr("Copy address of [flag] (<address>)"), this),
|
||||||
|
actionShowInSubmenu(tr("Show in"), this),
|
||||||
actionAddComment(tr("Add Comment"), this),
|
actionAddComment(tr("Add Comment"), this),
|
||||||
actionDeleteComment(tr("Delete comment"), this),
|
actionDeleteComment(tr("Delete comment"), this),
|
||||||
actionRenameThingHere(tr("Rename function at cursor"), this),
|
actionRenameThingHere(tr("Rename function at cursor"), this),
|
||||||
|
actionDeleteName(tr("Delete <name>"), this),
|
||||||
actionToggleBreakpoint(tr("Add/remove breakpoint"), this),
|
actionToggleBreakpoint(tr("Add/remove breakpoint"), this),
|
||||||
actionAdvancedBreakpoint(tr("Advanced breakpoint"), this),
|
actionAdvancedBreakpoint(tr("Advanced breakpoint"), this),
|
||||||
breakpointsInLineMenu(new QMenu(this)),
|
breakpointsInLineMenu(new QMenu(this)),
|
||||||
actionContinueUntil(tr("Continue until line"), this),
|
actionContinueUntil(tr("Continue until line"), this),
|
||||||
actionSetPC(tr("Set PC"), this)
|
actionSetPC(tr("Set PC"), this)
|
||||||
{
|
{
|
||||||
setActionCopy();
|
setActionCopy(); // Sets all three copy actions
|
||||||
addSeparator();
|
addSeparator();
|
||||||
|
|
||||||
|
setActionShowInSubmenu();
|
||||||
|
copySeparator = addSeparator();
|
||||||
|
|
||||||
setActionAddComment();
|
setActionAddComment();
|
||||||
setActionDeleteComment();
|
setActionDeleteComment();
|
||||||
|
|
||||||
setActionRenameThingHere();
|
setActionRenameThingHere();
|
||||||
|
setActionDeleteName();
|
||||||
|
|
||||||
addSeparator();
|
addSeparator();
|
||||||
addBreakpointMenu();
|
addBreakpointMenu();
|
||||||
@ -57,6 +67,11 @@ void DecompilerContextMenu::setAnnotationHere(RCodeAnnotation *annotation)
|
|||||||
this->annotationHere = annotation;
|
this->annotationHere = annotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecompilerContextMenu::setCurHighlightedWord(QString word)
|
||||||
|
{
|
||||||
|
this->curHighlightedWord = word;
|
||||||
|
}
|
||||||
|
|
||||||
void DecompilerContextMenu::setOffset(RVA offset)
|
void DecompilerContextMenu::setOffset(RVA offset)
|
||||||
{
|
{
|
||||||
this->offset = offset;
|
this->offset = offset;
|
||||||
@ -86,11 +101,6 @@ void DecompilerContextMenu::setupBreakpointsInLineMenu()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompilerContextMenu::setCanCopy(bool enabled)
|
|
||||||
{
|
|
||||||
actionCopy.setVisible(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DecompilerContextMenu::setShortcutContextInActions(QMenu *menu)
|
void DecompilerContextMenu::setShortcutContextInActions(QMenu *menu)
|
||||||
{
|
{
|
||||||
for (QAction *action : menu->actions()) {
|
for (QAction *action : menu->actions()) {
|
||||||
@ -117,11 +127,14 @@ bool DecompilerContextMenu::getIsTogglingBreakpoints()
|
|||||||
void DecompilerContextMenu::aboutToHideSlot()
|
void DecompilerContextMenu::aboutToHideSlot()
|
||||||
{
|
{
|
||||||
actionAddComment.setVisible(true);
|
actionAddComment.setVisible(true);
|
||||||
|
actionRenameThingHere.setVisible(true);
|
||||||
|
actionDeleteName.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompilerContextMenu::aboutToShowSlot()
|
void DecompilerContextMenu::aboutToShowSlot()
|
||||||
{
|
{
|
||||||
if (this->firstOffsetInLine != RVA_MAX) {
|
if (this->firstOffsetInLine != RVA_MAX) {
|
||||||
|
actionShowInSubmenu.setVisible(true);
|
||||||
QString comment = Core()->cmdRawAt("CC.", this->firstOffsetInLine);
|
QString comment = Core()->cmdRawAt("CC.", this->firstOffsetInLine);
|
||||||
actionAddComment.setVisible(true);
|
actionAddComment.setVisible(true);
|
||||||
if (comment.isEmpty()) {
|
if (comment.isEmpty()) {
|
||||||
@ -132,6 +145,7 @@ void DecompilerContextMenu::aboutToShowSlot()
|
|||||||
actionAddComment.setText(tr("Edit Comment"));
|
actionAddComment.setText(tr("Edit Comment"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
actionShowInSubmenu.setVisible(false);
|
||||||
actionAddComment.setVisible(false);
|
actionAddComment.setVisible(false);
|
||||||
actionDeleteComment.setVisible(false);
|
actionDeleteComment.setVisible(false);
|
||||||
}
|
}
|
||||||
@ -163,22 +177,82 @@ void DecompilerContextMenu::aboutToShowSlot()
|
|||||||
QString progCounterName = Core()->getRegisterName("PC").toUpper();
|
QString progCounterName = Core()->getRegisterName("PC").toUpper();
|
||||||
actionSetPC.setText(tr("Set %1 here").arg(progCounterName));
|
actionSetPC.setText(tr("Set %1 here").arg(progCounterName));
|
||||||
|
|
||||||
if (!annotationHere) { // To be considered as invalid
|
if (!annotationHere
|
||||||
|
|| annotationHere->type ==
|
||||||
|
R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE) { // To be considered as invalid
|
||||||
actionRenameThingHere.setVisible(false);
|
actionRenameThingHere.setVisible(false);
|
||||||
|
copySeparator->setVisible(false);
|
||||||
} else {
|
} else {
|
||||||
|
copySeparator->setVisible(true);
|
||||||
|
if (annotationHere->type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME) {
|
||||||
actionRenameThingHere.setVisible(true);
|
actionRenameThingHere.setVisible(true);
|
||||||
actionRenameThingHere.setText(tr("Rename function %1").arg(QString(
|
actionRenameThingHere.setText(tr("Rename function %1").arg(QString(
|
||||||
annotationHere->function_name.name)));
|
annotationHere->reference.name)));
|
||||||
}
|
}
|
||||||
|
if (annotationHere->type == R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE) {
|
||||||
|
RFlagItem *flagDetails = r_flag_get_i(Core()->core()->flags, annotationHere->reference.offset);
|
||||||
|
if (flagDetails) {
|
||||||
|
actionRenameThingHere.setText(tr("Rename %1").arg(QString(flagDetails->name)));
|
||||||
|
actionDeleteName.setText(tr("Remove %1").arg(QString(flagDetails->name)));
|
||||||
|
actionDeleteName.setVisible(true);
|
||||||
|
} else {
|
||||||
|
actionRenameThingHere.setText(tr("Add name to %1").arg(curHighlightedWord));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actionCopyInstructionAddress.setText(tr("Copy instruction address (%1)").arg(RAddressString(
|
||||||
|
offset)));
|
||||||
|
bool isReference = false;
|
||||||
|
if (annotationHere) {
|
||||||
|
isReference = (annotationHere->type == R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE
|
||||||
|
|| annotationHere->type == R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE
|
||||||
|
|| annotationHere->type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME);
|
||||||
|
}
|
||||||
|
if (isReference) {
|
||||||
|
actionCopyReferenceAddress.setVisible(true);
|
||||||
|
RVA referenceAddr = annotationHere->reference.offset;
|
||||||
|
RFlagItem *flagDetails = r_flag_get_i(Core()->core()->flags, referenceAddr);
|
||||||
|
if (annotationHere->type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME) {
|
||||||
|
actionCopyReferenceAddress.setText(tr("Copy address of %1 (%2)").arg
|
||||||
|
(QString(annotationHere->reference.name), RAddressString(referenceAddr)));
|
||||||
|
} else if (flagDetails) {
|
||||||
|
actionCopyReferenceAddress.setText(tr("Copy address of %1 (%2)").arg
|
||||||
|
(flagDetails->name, RAddressString(referenceAddr)));
|
||||||
|
} else {
|
||||||
|
actionCopyReferenceAddress.setText(tr("Copy address (%1)").arg(RAddressString(referenceAddr)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
actionCopyReferenceAddress.setVisible(false);
|
||||||
|
}
|
||||||
|
if (actionShowInSubmenu.menu() != nullptr) {
|
||||||
|
actionShowInSubmenu.menu()->deleteLater();
|
||||||
|
}
|
||||||
|
actionShowInSubmenu.setMenu(mainWindow->createShowInMenu(this, offset));
|
||||||
|
updateTargetMenuActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up actions
|
// Set up actions
|
||||||
|
|
||||||
void DecompilerContextMenu::setActionCopy()
|
|
||||||
|
void DecompilerContextMenu::setActionCopy() // Set all three copy actions
|
||||||
{
|
{
|
||||||
connect(&actionCopy, &QAction::triggered, this, &DecompilerContextMenu::actionCopyTriggered);
|
connect(&actionCopy, &QAction::triggered, this, &DecompilerContextMenu::actionCopyTriggered);
|
||||||
addAction(&actionCopy);
|
addAction(&actionCopy);
|
||||||
actionCopy.setShortcut(QKeySequence::Copy);
|
actionCopy.setShortcut(QKeySequence::Copy);
|
||||||
|
|
||||||
|
connect(&actionCopyInstructionAddress, &QAction::triggered, this,
|
||||||
|
&DecompilerContextMenu::actionCopyInstructionAddressTriggered);
|
||||||
|
addAction(&actionCopyInstructionAddress);
|
||||||
|
|
||||||
|
connect(&actionCopyReferenceAddress, &QAction::triggered, this,
|
||||||
|
&DecompilerContextMenu::actionCopyReferenceAddressTriggered);
|
||||||
|
addAction(&actionCopyReferenceAddress);
|
||||||
|
actionCopyReferenceAddress.setShortcut({Qt::CTRL + Qt::SHIFT + Qt::Key_C});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecompilerContextMenu::setActionShowInSubmenu()
|
||||||
|
{
|
||||||
|
addAction(&actionShowInSubmenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompilerContextMenu::setActionAddComment()
|
void DecompilerContextMenu::setActionAddComment()
|
||||||
@ -198,12 +272,20 @@ void DecompilerContextMenu::setActionDeleteComment()
|
|||||||
|
|
||||||
void DecompilerContextMenu::setActionRenameThingHere()
|
void DecompilerContextMenu::setActionRenameThingHere()
|
||||||
{
|
{
|
||||||
actionRenameThingHere.setShortcut({Qt::SHIFT + Qt::Key_N});
|
actionRenameThingHere.setShortcut({Qt::Key_N});
|
||||||
connect(&actionRenameThingHere, &QAction::triggered, this,
|
connect(&actionRenameThingHere, &QAction::triggered, this,
|
||||||
&DecompilerContextMenu::actionRenameThingHereTriggered);
|
&DecompilerContextMenu::actionRenameThingHereTriggered);
|
||||||
addAction(&actionRenameThingHere);
|
addAction(&actionRenameThingHere);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecompilerContextMenu::setActionDeleteName()
|
||||||
|
{
|
||||||
|
connect(&actionDeleteName, &QAction::triggered, this,
|
||||||
|
&DecompilerContextMenu::actionDeleteNameTriggered);
|
||||||
|
addAction(&actionDeleteName);
|
||||||
|
actionDeleteName.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
void DecompilerContextMenu::setActionToggleBreakpoint()
|
void DecompilerContextMenu::setActionToggleBreakpoint()
|
||||||
{
|
{
|
||||||
connect(&actionToggleBreakpoint, &QAction::triggered, this,
|
connect(&actionToggleBreakpoint, &QAction::triggered, this,
|
||||||
@ -236,6 +318,18 @@ void DecompilerContextMenu::actionCopyTriggered()
|
|||||||
emit copy();
|
emit copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecompilerContextMenu::actionCopyInstructionAddressTriggered()
|
||||||
|
{
|
||||||
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
|
clipboard->setText(RAddressString(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecompilerContextMenu::actionCopyReferenceAddressTriggered()
|
||||||
|
{
|
||||||
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
|
clipboard->setText(RAddressString(annotationHere->reference.offset));
|
||||||
|
}
|
||||||
|
|
||||||
void DecompilerContextMenu::actionAddCommentTriggered()
|
void DecompilerContextMenu::actionAddCommentTriggered()
|
||||||
{
|
{
|
||||||
CommentsDialog::addOrEditComment(this->firstOffsetInLine, this);
|
CommentsDialog::addOrEditComment(this->firstOffsetInLine, this);
|
||||||
@ -251,14 +345,16 @@ void DecompilerContextMenu::actionRenameThingHereTriggered()
|
|||||||
if (!annotationHere) {
|
if (!annotationHere) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
RCoreLocked core = Core()->core();
|
||||||
bool ok;
|
bool ok;
|
||||||
auto type = annotationHere->type;
|
auto type = annotationHere->type;
|
||||||
if (type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME) {
|
if (type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME) {
|
||||||
QString currentName(annotationHere->function_name.name);
|
QString currentName(annotationHere->reference.name);
|
||||||
RVA func_addr = annotationHere->function_name.offset;
|
RVA func_addr = annotationHere->reference.offset;
|
||||||
RAnalFunction *func = Core()->functionAt(func_addr);
|
RAnalFunction *func = Core()->functionAt(func_addr);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
QString function_name = QInputDialog::getText(this, tr("Define this function at %2").arg(RAddressString(func_addr)),
|
QString function_name = QInputDialog::getText(this,
|
||||||
|
tr("Define this function at %2").arg(RAddressString(func_addr)),
|
||||||
tr("Function name:"), QLineEdit::Normal, currentName, &ok);
|
tr("Function name:"), QLineEdit::Normal, currentName, &ok);
|
||||||
if (ok && !function_name.isEmpty()) {
|
if (ok && !function_name.isEmpty()) {
|
||||||
Core()->createFunctionAt(func_addr, function_name);
|
Core()->createFunctionAt(func_addr, function_name);
|
||||||
@ -271,7 +367,29 @@ void DecompilerContextMenu::actionRenameThingHereTriggered()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (type == R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE) {
|
||||||
|
RVA var_addr = annotationHere->reference.offset;
|
||||||
|
RFlagItem *flagDetails = r_flag_get_i(core->flags, var_addr);
|
||||||
|
if (flagDetails) {
|
||||||
|
QString newName = QInputDialog::getText(this, tr("Rename %2").arg(flagDetails->name),
|
||||||
|
tr("Enter name"), QLineEdit::Normal, flagDetails->name, &ok);
|
||||||
|
if (ok && !newName.isEmpty()) {
|
||||||
|
Core()->renameFlag(flagDetails->name, newName);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
QString newName = QInputDialog::getText(this, tr("Add name to %2").arg(curHighlightedWord),
|
||||||
|
tr("Enter name"), QLineEdit::Normal, curHighlightedWord, &ok);
|
||||||
|
if (ok && !newName.isEmpty()) {
|
||||||
|
Core()->addFlag(var_addr, newName, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecompilerContextMenu::actionDeleteNameTriggered()
|
||||||
|
{
|
||||||
|
Core()->delFlag(annotationHere->reference.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompilerContextMenu::actionToggleBreakpointTriggered()
|
void DecompilerContextMenu::actionToggleBreakpointTriggered()
|
||||||
@ -335,3 +453,43 @@ void DecompilerContextMenu::addDebugMenu()
|
|||||||
setActionSetPC();
|
setActionSetPC();
|
||||||
debugMenu->addAction(&actionSetPC);
|
debugMenu->addAction(&actionSetPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecompilerContextMenu::updateTargetMenuActions()
|
||||||
|
{
|
||||||
|
for (auto action : showTargetMenuActions) {
|
||||||
|
removeAction(action);
|
||||||
|
auto menu = action->menu();
|
||||||
|
if (menu) {
|
||||||
|
menu->deleteLater();
|
||||||
|
}
|
||||||
|
action->deleteLater();
|
||||||
|
}
|
||||||
|
showTargetMenuActions.clear();
|
||||||
|
RCoreLocked core = Core()->core();
|
||||||
|
if (annotationHere && (annotationHere->type == R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE
|
||||||
|
|| annotationHere->type == R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE
|
||||||
|
|| annotationHere->type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME)) {
|
||||||
|
QString name;
|
||||||
|
QMenu *menu;
|
||||||
|
if (annotationHere->type == R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE
|
||||||
|
|| annotationHere->type == R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE) {
|
||||||
|
menu = mainWindow->createShowInMenu(this, annotationHere->reference.offset, MainWindow::AddressTypeHint::Data);
|
||||||
|
RVA var_addr = annotationHere->reference.offset;
|
||||||
|
RFlagItem *flagDetails = r_flag_get_i(core->flags, var_addr);
|
||||||
|
if (flagDetails) {
|
||||||
|
name = tr("Show %1 in").arg(flagDetails->name);
|
||||||
|
} else {
|
||||||
|
name = tr("Show %1 in").arg(RAddressString(annotationHere->reference.offset));
|
||||||
|
}
|
||||||
|
} else if (annotationHere->type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME) {
|
||||||
|
menu = mainWindow->createShowInMenu(this, annotationHere->reference.offset,
|
||||||
|
MainWindow::AddressTypeHint::Function);
|
||||||
|
name = tr("%1 (%2)").arg(QString(annotationHere->reference.name),
|
||||||
|
RAddressString(annotationHere->reference.offset));
|
||||||
|
}
|
||||||
|
auto action = new QAction(name, this);
|
||||||
|
showTargetMenuActions.append(action);
|
||||||
|
action->setMenu(menu);
|
||||||
|
insertActions(copySeparator, showTargetMenuActions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,8 +22,8 @@ signals:
|
|||||||
void copy();
|
void copy();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void setCurHighlightedWord(QString word);
|
||||||
void setOffset(RVA offset);
|
void setOffset(RVA offset);
|
||||||
void setCanCopy(bool enabled);
|
|
||||||
void setFirstOffsetInLine(RVA firstOffset);
|
void setFirstOffsetInLine(RVA firstOffset);
|
||||||
void setAvailableBreakpoints(QVector<RVA> offsetList);
|
void setAvailableBreakpoints(QVector<RVA> offsetList);
|
||||||
|
|
||||||
@ -33,11 +33,14 @@ private slots:
|
|||||||
void aboutToHideSlot();
|
void aboutToHideSlot();
|
||||||
|
|
||||||
void actionCopyTriggered();
|
void actionCopyTriggered();
|
||||||
|
void actionCopyInstructionAddressTriggered();
|
||||||
|
void actionCopyReferenceAddressTriggered();
|
||||||
|
|
||||||
void actionAddCommentTriggered();
|
void actionAddCommentTriggered();
|
||||||
void actionDeleteCommentTriggered();
|
void actionDeleteCommentTriggered();
|
||||||
|
|
||||||
void actionRenameThingHereTriggered();
|
void actionRenameThingHereTriggered();
|
||||||
|
void actionDeleteNameTriggered();
|
||||||
|
|
||||||
void actionToggleBreakpointTriggered();
|
void actionToggleBreakpointTriggered();
|
||||||
void actionAdvancedBreakpointTriggered();
|
void actionAdvancedBreakpointTriggered();
|
||||||
@ -47,6 +50,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Private variables
|
// Private variables
|
||||||
|
QString curHighlightedWord;
|
||||||
RVA offset;
|
RVA offset;
|
||||||
RVA firstOffsetInLine;
|
RVA firstOffsetInLine;
|
||||||
bool isTogglingBreakpoints;
|
bool isTogglingBreakpoints;
|
||||||
@ -56,12 +60,18 @@ private:
|
|||||||
RCodeAnnotation *annotationHere;
|
RCodeAnnotation *annotationHere;
|
||||||
|
|
||||||
QAction actionCopy;
|
QAction actionCopy;
|
||||||
|
QAction actionCopyInstructionAddress;
|
||||||
|
QAction actionCopyReferenceAddress;
|
||||||
QAction *copySeparator;
|
QAction *copySeparator;
|
||||||
|
|
||||||
|
QAction actionShowInSubmenu;
|
||||||
|
QList<QAction *> showTargetMenuActions;
|
||||||
|
|
||||||
QAction actionAddComment;
|
QAction actionAddComment;
|
||||||
QAction actionDeleteComment;
|
QAction actionDeleteComment;
|
||||||
|
|
||||||
QAction actionRenameThingHere;
|
QAction actionRenameThingHere;
|
||||||
|
QAction actionDeleteName;
|
||||||
|
|
||||||
QMenu *breakpointMenu;
|
QMenu *breakpointMenu;
|
||||||
QAction actionToggleBreakpoint;
|
QAction actionToggleBreakpoint;
|
||||||
@ -81,10 +91,13 @@ private:
|
|||||||
// Set actions
|
// Set actions
|
||||||
void setActionCopy();
|
void setActionCopy();
|
||||||
|
|
||||||
|
void setActionShowInSubmenu();
|
||||||
|
|
||||||
void setActionAddComment();
|
void setActionAddComment();
|
||||||
void setActionDeleteComment();
|
void setActionDeleteComment();
|
||||||
|
|
||||||
void setActionRenameThingHere();
|
void setActionRenameThingHere();
|
||||||
|
void setActionDeleteName();
|
||||||
|
|
||||||
void setActionToggleBreakpoint();
|
void setActionToggleBreakpoint();
|
||||||
void setActionAdvancedBreakpoint();
|
void setActionAdvancedBreakpoint();
|
||||||
@ -113,6 +126,7 @@ private:
|
|||||||
// QVector<ThingUsedHere> getThingUsedHere(RVA offset);
|
// QVector<ThingUsedHere> getThingUsedHere(RVA offset);
|
||||||
|
|
||||||
// void updateTargetMenuActions(const QVector<ThingUsedHere> &targets);
|
// void updateTargetMenuActions(const QVector<ThingUsedHere> &targets);
|
||||||
|
void updateTargetMenuActions();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DECOMPILERCONTEXTMENU_H
|
#endif // DECOMPILERCONTEXTMENU_H
|
@ -12,6 +12,7 @@
|
|||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
|
#include <QClipboard>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTextBlockUserData>
|
#include <QTextBlockUserData>
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ DecompilerWidget::DecompilerWidget(MainWindow *main) :
|
|||||||
connect(Config(), &Configuration::fontsUpdated, this, &DecompilerWidget::fontsUpdatedSlot);
|
connect(Config(), &Configuration::fontsUpdated, this, &DecompilerWidget::fontsUpdatedSlot);
|
||||||
connect(Config(), &Configuration::colorsUpdated, this, &DecompilerWidget::colorsUpdatedSlot);
|
connect(Config(), &Configuration::colorsUpdated, this, &DecompilerWidget::colorsUpdatedSlot);
|
||||||
connect(Core(), &CutterCore::registersChanged, this, &DecompilerWidget::highlightPC);
|
connect(Core(), &CutterCore::registersChanged, this, &DecompilerWidget::highlightPC);
|
||||||
connect(mCtxMenu, &DecompilerContextMenu::copy, ui->textEdit, &QPlainTextEdit::copy);
|
connect(mCtxMenu, &DecompilerContextMenu::copy, this, &DecompilerWidget::copy);
|
||||||
|
|
||||||
decompiledFunctionAddr = RVA_INVALID;
|
decompiledFunctionAddr = RVA_INVALID;
|
||||||
decompilerWasBusy = false;
|
decompilerWasBusy = false;
|
||||||
@ -87,8 +88,6 @@ DecompilerWidget::DecompilerWidget(MainWindow *main) :
|
|||||||
connect(ui->textEdit, &QWidget::customContextMenuRequested,
|
connect(ui->textEdit, &QWidget::customContextMenuRequested,
|
||||||
this, &DecompilerWidget::showDisasContextMenu);
|
this, &DecompilerWidget::showDisasContextMenu);
|
||||||
|
|
||||||
// refresh the widget when an action in this menu is triggered
|
|
||||||
connect(mCtxMenu, &QMenu::triggered, this, &DecompilerWidget::refreshDecompiler);
|
|
||||||
connect(Core(), &CutterCore::breakpointsChanged, this, &DecompilerWidget::setInfoForBreakpoints);
|
connect(Core(), &CutterCore::breakpointsChanged, this, &DecompilerWidget::setInfoForBreakpoints);
|
||||||
addActions(mCtxMenu->actions());
|
addActions(mCtxMenu->actions());
|
||||||
|
|
||||||
@ -344,7 +343,6 @@ void DecompilerWidget::connectCursorPositionChanged(bool disconnect)
|
|||||||
|
|
||||||
void DecompilerWidget::cursorPositionChanged()
|
void DecompilerWidget::cursorPositionChanged()
|
||||||
{
|
{
|
||||||
mCtxMenu->setCanCopy(ui->textEdit->textCursor().hasSelection());
|
|
||||||
// Do not perform seeks along with the cursor while selecting multiple lines
|
// Do not perform seeks along with the cursor while selecting multiple lines
|
||||||
if (!ui->textEdit->textCursor().selectedText().isEmpty()) {
|
if (!ui->textEdit->textCursor().selectedText().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
@ -414,6 +412,7 @@ void DecompilerWidget::updateSelection()
|
|||||||
// Highlight all the words in the document same as the current one
|
// Highlight all the words in the document same as the current one
|
||||||
cursor.select(QTextCursor::WordUnderCursor);
|
cursor.select(QTextCursor::WordUnderCursor);
|
||||||
QString searchString = cursor.selectedText();
|
QString searchString = cursor.selectedText();
|
||||||
|
mCtxMenu->setCurHighlightedWord(searchString);
|
||||||
extraSelections.append(createSameWordsSelections(ui->textEdit, searchString));
|
extraSelections.append(createSameWordsSelections(ui->textEdit, searchString));
|
||||||
|
|
||||||
ui->textEdit->setExtraSelections(extraSelections);
|
ui->textEdit->setExtraSelections(extraSelections);
|
||||||
@ -438,7 +437,6 @@ void DecompilerWidget::colorsUpdatedSlot()
|
|||||||
void DecompilerWidget::showDisasContextMenu(const QPoint &pt)
|
void DecompilerWidget::showDisasContextMenu(const QPoint &pt)
|
||||||
{
|
{
|
||||||
mCtxMenu->exec(ui->textEdit->mapToGlobal(pt));
|
mCtxMenu->exec(ui->textEdit->mapToGlobal(pt));
|
||||||
doRefresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompilerWidget::seekToReference()
|
void DecompilerWidget::seekToReference()
|
||||||
@ -460,7 +458,7 @@ bool DecompilerWidget::eventFilter(QObject *obj, QEvent *event)
|
|||||||
if (event->type() == QEvent::MouseButtonPress
|
if (event->type() == QEvent::MouseButtonPress
|
||||||
&& (obj == ui->textEdit || obj == ui->textEdit->viewport())) {
|
&& (obj == ui->textEdit || obj == ui->textEdit->viewport())) {
|
||||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||||
if (mouseEvent->button() == Qt::RightButton) {
|
if (mouseEvent->button() == Qt::RightButton && !ui->textEdit->textCursor().hasSelection()) {
|
||||||
ui->textEdit->setTextCursor(ui->textEdit->cursorForPosition(mouseEvent->pos()));
|
ui->textEdit->setTextCursor(ui->textEdit->cursorForPosition(mouseEvent->pos()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -509,3 +507,20 @@ bool DecompilerWidget::colorLine(QTextEdit::ExtraSelection extraSelection)
|
|||||||
ui->textEdit->setExtraSelections(extraSelections);
|
ui->textEdit->setExtraSelections(extraSelections);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecompilerWidget::copy()
|
||||||
|
{
|
||||||
|
if (ui->textEdit->textCursor().hasSelection()) {
|
||||||
|
ui->textEdit->copy();
|
||||||
|
} else {
|
||||||
|
QTextCursor cursor = ui->textEdit->textCursor();
|
||||||
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
|
cursor.select(QTextCursor::WordUnderCursor);
|
||||||
|
if (!cursor.selectedText().isEmpty()) {
|
||||||
|
clipboard->setText(cursor.selectedText());
|
||||||
|
} else {
|
||||||
|
cursor.select(QTextCursor::LineUnderCursor);
|
||||||
|
clipboard->setText(cursor.selectedText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -32,6 +32,7 @@ public slots:
|
|||||||
|
|
||||||
void highlightPC();
|
void highlightPC();
|
||||||
private slots:
|
private slots:
|
||||||
|
void copy();
|
||||||
void fontsUpdatedSlot();
|
void fontsUpdatedSlot();
|
||||||
void colorsUpdatedSlot();
|
void colorsUpdatedSlot();
|
||||||
void refreshDecompiler();
|
void refreshDecompiler();
|
||||||
|
Loading…
Reference in New Issue
Block a user