GUI: MenuBuilder class for building menus in one central place (runtime variation of the menu structure is possible)
This commit is contained in:
parent
58168e024b
commit
087362d578
|
@ -10,6 +10,7 @@
|
|||
#include <QMenu>
|
||||
#include "StringUtil.h"
|
||||
#include "Configuration.h"
|
||||
#include "MenuBuilder.h"
|
||||
|
||||
//Hacky class that fixes a really annoying cursor problem
|
||||
class AbstractTableScrollBar : public QScrollBar
|
||||
|
@ -240,6 +241,18 @@ private:
|
|||
}
|
||||
|
||||
protected:
|
||||
inline QMenu* makeMenu(const QString & title)
|
||||
{
|
||||
return new QMenu(title, this);
|
||||
}
|
||||
|
||||
inline QMenu* makeMenu(const QIcon & icon, const QString & title)
|
||||
{
|
||||
QMenu* menu = new QMenu(title, this);
|
||||
menu->setIcon(icon);
|
||||
return menu;
|
||||
}
|
||||
|
||||
inline QAction* makeAction(const QString & text, const char* slot)
|
||||
{
|
||||
return connectAction(new QAction(text, this), slot);
|
||||
|
|
|
@ -171,233 +171,203 @@ void CPUDisassembly::setupFollowReferenceMenu(dsint wVA, QMenu* menu, bool isRef
|
|||
*/
|
||||
void CPUDisassembly::contextMenuEvent(QContextMenuEvent* event)
|
||||
{
|
||||
if(getSize() != 0)
|
||||
{
|
||||
int wI;
|
||||
QMenu* wMenu = new QMenu(this);
|
||||
duint wVA = rvaToVa(getInitialSelection());
|
||||
BPXTYPE wBpType = DbgGetBpxTypeAt(wVA);
|
||||
|
||||
// Build Menu
|
||||
wMenu->addMenu(mBinaryMenu);
|
||||
wMenu->addMenu(mCopyMenu);
|
||||
dsint start = rvaToVa(getSelectionStart());
|
||||
dsint end = rvaToVa(getSelectionEnd());
|
||||
if(DbgFunctions()->PatchInRange(start, end)) //nothing patched in selected range
|
||||
wMenu->addAction(mUndoSelection);
|
||||
|
||||
// BP Menu
|
||||
mBPMenu->clear();
|
||||
// Soft BP
|
||||
mBPMenu->addAction(mToggleInt3BpAction);
|
||||
// Hardware BP
|
||||
if((wBpType & bp_hardware) == bp_hardware)
|
||||
{
|
||||
mBPMenu->addAction(mClearHwBpAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
BPMAP wBPList;
|
||||
DbgGetBpList(bp_hardware, &wBPList);
|
||||
|
||||
//get enabled hwbp count
|
||||
int enabledCount = wBPList.count;
|
||||
for(int i = 0; i < wBPList.count; i++)
|
||||
if(!wBPList.bp[i].enabled)
|
||||
enabledCount--;
|
||||
|
||||
if(enabledCount < 4)
|
||||
{
|
||||
mBPMenu->addAction(mSetHwBpAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
REGDUMP wRegDump;
|
||||
DbgGetRegDump(&wRegDump);
|
||||
|
||||
for(wI = 0; wI < 4; wI++)
|
||||
{
|
||||
switch(wBPList.bp[wI].slot)
|
||||
{
|
||||
case 0:
|
||||
msetHwBPOnSlot0Action->setText("Replace Slot 0 (0x" + QString("%1").arg(wBPList.bp[wI].addr, 8, 16, QChar('0')).toUpper() + ")");
|
||||
break;
|
||||
case 1:
|
||||
msetHwBPOnSlot1Action->setText("Replace Slot 1 (0x" + QString("%1").arg(wBPList.bp[wI].addr, 8, 16, QChar('0')).toUpper() + ")");
|
||||
break;
|
||||
case 2:
|
||||
msetHwBPOnSlot2Action->setText("Replace Slot 2 (0x" + QString("%1").arg(wBPList.bp[wI].addr, 8, 16, QChar('0')).toUpper() + ")");
|
||||
break;
|
||||
case 3:
|
||||
msetHwBPOnSlot3Action->setText("Replace Slot 3 (0x" + QString("%1").arg(wBPList.bp[wI].addr, 8, 16, QChar('0')).toUpper() + ")");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mHwSlotSelectMenu->addAction(msetHwBPOnSlot0Action);
|
||||
mHwSlotSelectMenu->addAction(msetHwBPOnSlot1Action);
|
||||
mHwSlotSelectMenu->addAction(msetHwBPOnSlot2Action);
|
||||
mHwSlotSelectMenu->addAction(msetHwBPOnSlot3Action);
|
||||
mBPMenu->addMenu(mHwSlotSelectMenu);
|
||||
}
|
||||
if(wBPList.count)
|
||||
BridgeFree(wBPList.bp);
|
||||
}
|
||||
wMenu->addMenu(mBPMenu);
|
||||
wMenu->addMenu(mFollowMenu);
|
||||
setupFollowReferenceMenu(wVA, mFollowMenu, false);
|
||||
if(DbgFunctions()->GetSourceFromAddr(wVA, 0, 0))
|
||||
wMenu->addAction(mOpenSourceAction);
|
||||
|
||||
mDecompileMenu->clear();
|
||||
if(DbgFunctionGet(wVA, 0, 0))
|
||||
mDecompileMenu->addAction(mDecompileFunctionAction);
|
||||
mDecompileMenu->addAction(mDecompileSelectionAction);
|
||||
wMenu->addMenu(mDecompileMenu);
|
||||
|
||||
wMenu->addAction(mEnableHighlightingMode);
|
||||
wMenu->addSeparator();
|
||||
|
||||
wMenu->addAction(mSetLabelAction);
|
||||
wMenu->addAction(mSetCommentAction);
|
||||
wMenu->addAction(mSetBookmarkAction);
|
||||
|
||||
duint selection_start = rvaToVa(getSelectionStart());
|
||||
duint selection_end = rvaToVa(getSelectionEnd());
|
||||
if(!DbgFunctionOverlaps(selection_start, selection_end))
|
||||
{
|
||||
mToggleFunctionAction->setText("Add function");
|
||||
wMenu->addAction(mToggleFunctionAction);
|
||||
}
|
||||
else if(DbgFunctionOverlaps(selection_start, selection_end))
|
||||
{
|
||||
mToggleFunctionAction->setText("Delete function");
|
||||
wMenu->addAction(mToggleFunctionAction);
|
||||
}
|
||||
|
||||
wMenu->addAction(mAssembleAction);
|
||||
|
||||
wMenu->addAction(mPatchesAction);
|
||||
wMenu->addAction(mYaraAction);
|
||||
|
||||
wMenu->addSeparator();
|
||||
|
||||
// New origin
|
||||
wMenu->addAction(mSetNewOriginHere);
|
||||
|
||||
// Goto Menu
|
||||
mGotoMenu->clear();
|
||||
mGotoMenu->addAction(mGotoOriginAction);
|
||||
if(historyHasPrevious())
|
||||
mGotoMenu->addAction(mGotoPreviousAction);
|
||||
if(historyHasNext())
|
||||
mGotoMenu->addAction(mGotoNextAction);
|
||||
mGotoMenu->addAction(mGotoExpressionAction);
|
||||
char modname[MAX_MODULE_SIZE] = "";
|
||||
if(DbgGetModuleAt(wVA, modname))
|
||||
mGotoMenu->addAction(mGotoFileOffsetAction);
|
||||
mGotoMenu->addAction(mGotoStartAction);
|
||||
mGotoMenu->addAction(mGotoEndAction);
|
||||
wMenu->addMenu(mGotoMenu);
|
||||
wMenu->addSeparator();
|
||||
|
||||
wMenu->addMenu(mSearchMenu);
|
||||
|
||||
wMenu->addMenu(mReferencesMenu);
|
||||
setupFollowReferenceMenu(wVA, mReferencesMenu, true);
|
||||
|
||||
wMenu->addSeparator();
|
||||
wMenu->addActions(mPluginMenu->actions());
|
||||
|
||||
wMenu->exec(event->globalPos());
|
||||
}
|
||||
QMenu wMenu(this);
|
||||
mMenuBuilder->build(&wMenu);
|
||||
wMenu.exec(event->globalPos());
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
Context Menu Management
|
||||
************************************************************************************/
|
||||
void CPUDisassembly::setupRightClickContextMenu()
|
||||
{
|
||||
mBinaryMenu = new QMenu("&Binary", this);
|
||||
mBinaryMenu->setIcon(QIcon(":/icons/images/binary.png"));
|
||||
mBinaryEditAction = makeShortcutMenuAction(mBinaryMenu, "&Edit", SLOT(binaryEditSlot()), "ActionBinaryEdit");
|
||||
mBinaryFillAction = makeShortcutMenuAction(mBinaryMenu, "&Fill...", SLOT(binaryFillSlot()), "ActionBinaryFill");
|
||||
mBinaryFillNopsAction = makeShortcutMenuAction(mBinaryMenu, "Fill with &NOPs", SLOT(binaryFillNopsSlot()), "ActionBinaryFillNops");
|
||||
mBinaryMenu->addSeparator();
|
||||
mBinaryCopyAction = makeShortcutMenuAction(mBinaryMenu, "&Copy", SLOT(binaryCopySlot()), "ActionBinaryCopy");
|
||||
mBinaryPasteAction = makeShortcutMenuAction(mBinaryMenu, "&Paste", SLOT(binaryPasteSlot()), "ActionBinaryPaste");
|
||||
mBinaryPasteIgnoreSizeAction = makeShortcutMenuAction(mBinaryMenu, "Paste (&Ignore Size)", SLOT(binaryPasteIgnoreSizeSlot()), "ActionBinaryPasteIgnoreSize");
|
||||
mMenuBuilder = new MenuBuilder(this, [](QMenu*)
|
||||
{
|
||||
return DbgIsDebugging();
|
||||
});
|
||||
|
||||
mUndoSelection = makeShortcutAction("&Restore selection", SLOT(undoSelectionSlot()), "ActionUndoSelection");
|
||||
mSetLabelAction = makeShortcutAction(QIcon(":/icons/images/label.png"), "Label", SLOT(setLabelSlot()), "ActionSetLabel");
|
||||
mSetCommentAction = makeShortcutAction(QIcon(":/icons/images/comment.png"), "Comment", SLOT(setCommentSlot()), "ActionSetComment");
|
||||
mSetBookmarkAction = makeShortcutAction(QIcon(":/icons/images/bookmark.png"), "Bookmark", SLOT(setBookmarkSlot()), "ActionToggleBookmark");
|
||||
mToggleFunctionAction = makeShortcutAction(QIcon(":/icons/images/functions.png"), "Function", SLOT(toggleFunctionSlot()), "ActionToggleFunction");
|
||||
mAssembleAction = makeShortcutAction("Assemble", SLOT(assembleSlot()), "ActionAssemble");
|
||||
MenuBuilder* binaryMenu = new MenuBuilder(this);
|
||||
binaryMenu->addAction(makeShortcutAction("&Edit", SLOT(binaryEditSlot()), "ActionBinaryEdit"));
|
||||
binaryMenu->addAction(makeShortcutAction("&Fill...", SLOT(binaryFillSlot()), "ActionBinaryFill"));
|
||||
binaryMenu->addAction(makeShortcutAction("Fill with &NOPs", SLOT(binaryFillNopsSlot()), "ActionBinaryFillNops"));
|
||||
binaryMenu->addSeparator();
|
||||
binaryMenu->addAction(makeShortcutAction("&Copy", SLOT(binaryCopySlot()), "ActionBinaryCopy"));
|
||||
binaryMenu->addAction(makeShortcutAction("&Paste", SLOT(binaryPasteSlot()), "ActionBinaryPaste"));
|
||||
binaryMenu->addAction(makeShortcutAction("Paste (&Ignore Size)", SLOT(binaryPasteIgnoreSizeSlot()), "ActionBinaryPasteIgnoreSize"));
|
||||
mMenuBuilder->addMenu(makeMenu(QIcon(":/icons/images/binary.png"), "&Binary"), binaryMenu);
|
||||
|
||||
mBPMenu = new QMenu("Breakpoint", this);
|
||||
mBPMenu->setIcon(QIcon(":/icons/images/breakpoint.png"));
|
||||
mToggleInt3BpAction = makeShortcutAction("Toggle", SLOT(toggleInt3BPActionSlot()), "ActionToggleBreakpoint");
|
||||
MenuBuilder* copyMenu = new MenuBuilder(this);
|
||||
copyMenu->addAction(makeShortcutAction("&Selection", SLOT(copySelectionSlot()), "ActionCopy"));
|
||||
copyMenu->addAction(makeAction("Selection (&No Bytes)", SLOT(copySelectionNoBytesSlot())));
|
||||
copyMenu->addAction(makeShortcutAction("&Address", SLOT(copyAddressSlot()), "ActionCopyAddress"));
|
||||
copyMenu->addAction(makeAction("&RVA", SLOT(copyRvaSlot())));
|
||||
copyMenu->addAction(makeAction("Disassembly", SLOT(copyDisassemblySlot())));
|
||||
mMenuBuilder->addMenu(makeMenu(QIcon(":/icons/images/copy.png"), "&Copy"), copyMenu);
|
||||
|
||||
mHwSlotSelectMenu = new QMenu("Set Hardware on Execution", this);
|
||||
mSetHwBpAction = makeAction("Set Hardware on Execution", SLOT(toggleHwBpActionSlot()));
|
||||
mClearHwBpAction = makeAction("Remove Hardware", SLOT(toggleHwBpActionSlot()));
|
||||
msetHwBPOnSlot0Action = makeAction("Set Hardware on Execution on Slot 0 (Free)", SLOT(setHwBpOnSlot0ActionSlot()));
|
||||
msetHwBPOnSlot1Action = makeAction("Set Hardware on Execution on Slot 1 (Free)", SLOT(setHwBpOnSlot1ActionSlot()));
|
||||
msetHwBPOnSlot2Action = makeAction("Set Hardware on Execution on Slot 2 (Free)", SLOT(setHwBpOnSlot2ActionSlot()));
|
||||
msetHwBPOnSlot3Action = makeAction("Set Hardware on Execution on Slot 3 (Free)", SLOT(setHwBpOnSlot3ActionSlot()));
|
||||
mMenuBuilder->addAction(makeShortcutAction("&Restore selection", SLOT(undoSelectionSlot()), "ActionUndoSelection"), [this](QMenu*)
|
||||
{
|
||||
dsint start = rvaToVa(getSelectionStart());
|
||||
dsint end = rvaToVa(getSelectionEnd());
|
||||
return DbgFunctions()->PatchInRange(start, end); //something patched in selected range
|
||||
});
|
||||
|
||||
mPatchesAction = makeShortcutAction(QIcon(":/icons/images/patch.png"), "Patches", SLOT(showPatchesSlot()), "ViewPatches");
|
||||
removeAction(mPatchesAction); //prevent conflicting shortcut with the MainWindow
|
||||
mYaraAction = makeShortcutAction(QIcon(":/icons/images/yara.png"), "&Yara...", SLOT(yaraSlot()), "ActionYara");
|
||||
mSetNewOriginHere = makeShortcutAction("Set New Origin Here", SLOT(setNewOriginHereActionSlot()), "ActionSetNewOriginHere");
|
||||
QAction* toggleBreakpointAction = makeShortcutAction("Toggle", SLOT(toggleInt3BPActionSlot()), "ActionToggleBreakpoint");
|
||||
QAction* setHwBreakpointAction = makeAction("Set Hardware on Execution", SLOT(toggleHwBpActionSlot()));
|
||||
QAction* removeHwBreakpointAction = makeAction("Remove Hardware", SLOT(toggleHwBpActionSlot()));
|
||||
|
||||
mGotoMenu = new QMenu("Go to", this);
|
||||
mGotoOriginAction = makeShortcutAction("Origin", SLOT(gotoOriginSlot()), "ActionGotoOrigin");
|
||||
mGotoPreviousAction = makeShortcutAction("Previous", SLOT(gotoPreviousSlot()), "ActionGotoPrevious");
|
||||
mGotoNextAction = makeShortcutAction("Next", SLOT(gotoNextSlot()), "ActionGotoNext");
|
||||
mGotoExpressionAction = makeShortcutAction("Expression", SLOT(gotoExpressionSlot()), "ActionGotoExpression");
|
||||
mGotoFileOffsetAction = makeShortcutAction("File Offset", SLOT(gotoFileOffsetSlot()), "ActionGotoFileOffset");
|
||||
mGotoStartAction = makeShortcutAction("Start of Page", SLOT(gotoStartSlot()), "ActionGotoStart");
|
||||
mGotoEndAction = makeShortcutAction("End of Page", SLOT(gotoEndSlot()), "ActionGotoEnd");
|
||||
QMenu* replaceSlotMenu = makeMenu("Set Hardware on Execution");
|
||||
QAction* replaceSlot0Action = makeMenuAction(replaceSlotMenu, "Replace Slot 0 (Free)", SLOT(setHwBpOnSlot0ActionSlot()));
|
||||
QAction* replaceSlot1Action = makeMenuAction(replaceSlotMenu, "Replace Slot 1 (Free)", SLOT(setHwBpOnSlot1ActionSlot()));
|
||||
QAction* replaceSlot2Action = makeMenuAction(replaceSlotMenu, "Replace Slot 2 (Free)", SLOT(setHwBpOnSlot2ActionSlot()));
|
||||
QAction* replaceSlot3Action = makeMenuAction(replaceSlotMenu, "Replace Slot 3 (Free)", SLOT(setHwBpOnSlot3ActionSlot()));
|
||||
|
||||
mFollowMenu = new QMenu("&Follow in Dump", this);
|
||||
mMenuBuilder->addMenu(makeMenu(QIcon(":/icons/images/breakpoint.png"), "Breakpoint"), [=](QMenu* menu)
|
||||
{
|
||||
BPXTYPE bpType = DbgGetBpxTypeAt(rvaToVa(getInitialSelection()));
|
||||
|
||||
mCopyMenu = new QMenu("&Copy", this);
|
||||
mCopyMenu->setIcon(QIcon(":/icons/images/copy.png"));
|
||||
mCopySelectionAction = makeShortcutMenuAction(mCopyMenu, "&Selection", SLOT(copySelectionSlot()), "ActionCopy");
|
||||
mCopySelectionNoBytesAction = makeMenuAction(mCopyMenu, "Selection (&No Bytes)", SLOT(copySelectionNoBytesSlot()));
|
||||
mCopyAddressAction = makeShortcutMenuAction(mCopyMenu, "&Address", SLOT(copyAddressSlot()), "ActionCopyAddress");
|
||||
mCopyRvaAction = makeMenuAction(mCopyMenu, "&RVA", SLOT(copyRvaSlot()));
|
||||
mCopyDisassemblyAction = makeMenuAction(mCopyMenu, "Disassembly", SLOT(copyDisassemblySlot()));
|
||||
menu->addAction(toggleBreakpointAction);
|
||||
|
||||
mOpenSourceAction = makeAction(QIcon(":/icons/images/source.png"), "Open Source File", SLOT(openSourceSlot()));
|
||||
if((bpType & bp_hardware) == bp_hardware)
|
||||
{
|
||||
menu->addAction(removeHwBreakpointAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
BPMAP bpList;
|
||||
DbgGetBpList(bp_hardware, &bpList);
|
||||
|
||||
mDecompileMenu = new QMenu("Decompile");
|
||||
mDecompileMenu->setIcon(QIcon(":/icons/images/snowman.png"));
|
||||
mDecompileSelectionAction = makeShortcutAction("Selection", SLOT(decompileSelectionSlot()), "ActionDecompileSelection");
|
||||
mDecompileFunctionAction = makeShortcutAction("Function", SLOT(decompileFunctionSlot()), "ActionDecompileFunction");
|
||||
//get enabled hwbp count
|
||||
int enabledCount = bpList.count;
|
||||
for(int i = 0; i < bpList.count; i++)
|
||||
if(!bpList.bp[i].enabled)
|
||||
enabledCount--;
|
||||
|
||||
if(enabledCount < 4)
|
||||
{
|
||||
menu->addAction(setHwBreakpointAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
REGDUMP wRegDump;
|
||||
DbgGetRegDump(&wRegDump);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
switch(bpList.bp[i].slot)
|
||||
{
|
||||
case 0:
|
||||
replaceSlot0Action->setText("Replace Slot 0 (0x" + QString("%1").arg(bpList.bp[i].addr, 8, 16, QChar('0')).toUpper() + ")");
|
||||
break;
|
||||
case 1:
|
||||
replaceSlot1Action->setText("Replace Slot 1 (0x" + QString("%1").arg(bpList.bp[i].addr, 8, 16, QChar('0')).toUpper() + ")");
|
||||
break;
|
||||
case 2:
|
||||
replaceSlot2Action->setText("Replace Slot 2 (0x" + QString("%1").arg(bpList.bp[i].addr, 8, 16, QChar('0')).toUpper() + ")");
|
||||
break;
|
||||
case 3:
|
||||
replaceSlot3Action->setText("Replace Slot 3 (0x" + QString("%1").arg(bpList.bp[i].addr, 8, 16, QChar('0')).toUpper() + ")");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
menu->addMenu(replaceSlotMenu);
|
||||
}
|
||||
if(bpList.count)
|
||||
BridgeFree(bpList.bp);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
mMenuBuilder->addMenu(makeMenu("&Follow in Dump"), [this](QMenu* menu)
|
||||
{
|
||||
setupFollowReferenceMenu(rvaToVa(getInitialSelection()), menu, false);
|
||||
return true;
|
||||
});
|
||||
|
||||
mMenuBuilder->addAction(makeAction(QIcon(":/icons/images/source.png"), "Open Source File", SLOT(openSourceSlot())), [this](QMenu*)
|
||||
{
|
||||
return DbgFunctions()->GetSourceFromAddr(rvaToVa(getInitialSelection()), 0, 0);
|
||||
});
|
||||
|
||||
MenuBuilder* decompileMenu = new MenuBuilder(this);
|
||||
decompileMenu->addAction(makeShortcutAction("Selection", SLOT(decompileSelectionSlot()), "ActionDecompileSelection"), [this](QMenu*)
|
||||
{
|
||||
return DbgFunctionGet(rvaToVa(getInitialSelection()), 0, 0);
|
||||
});
|
||||
decompileMenu->addAction(makeShortcutAction("Function", SLOT(decompileFunctionSlot()), "ActionDecompileFunction"));
|
||||
mMenuBuilder->addMenu(makeMenu(QIcon(":/icons/images/snowman.png"), "Decompile"), decompileMenu);
|
||||
|
||||
mMenuBuilder->addAction(makeShortcutAction(QIcon(":/icons/images/highlight.png"), "&Highlighting mode", SLOT(enableHighlightingModeSlot()), "ActionHighlightingMode"));
|
||||
mMenuBuilder->addSeparator();
|
||||
|
||||
mMenuBuilder->addAction(makeShortcutAction(QIcon(":/icons/images/label.png"), "Label", SLOT(setLabelSlot()), "ActionSetLabel"));
|
||||
mMenuBuilder->addAction(makeShortcutAction(QIcon(":/icons/images/comment.png"), "Comment", SLOT(setCommentSlot()), "ActionSetComment"));
|
||||
mMenuBuilder->addAction(makeShortcutAction(QIcon(":/icons/images/bookmark.png"), "Bookmark", SLOT(setBookmarkSlot()), "ActionToggleBookmark"));
|
||||
QAction* toggleFunctionAction = makeShortcutAction(QIcon(":/icons/images/functions.png"), "Function", SLOT(toggleFunctionSlot()), "ActionToggleFunction");
|
||||
mMenuBuilder->addAction(toggleFunctionAction, [this, toggleFunctionAction](QMenu*)
|
||||
{
|
||||
if(!DbgFunctionOverlaps(rvaToVa(getSelectionStart()), rvaToVa(getSelectionEnd())))
|
||||
toggleFunctionAction->setText("Add function");
|
||||
else
|
||||
toggleFunctionAction->setText("Delete function");
|
||||
return true;
|
||||
});
|
||||
mMenuBuilder->addAction(makeShortcutAction("Assemble", SLOT(assembleSlot()), "ActionAssemble"));
|
||||
removeAction(mMenuBuilder->addAction(makeShortcutAction(QIcon(":/icons/images/patch.png"), "Patches", SLOT(showPatchesSlot()), "ViewPatches"))); //prevent conflicting shortcut with the MainWindow
|
||||
mMenuBuilder->addAction(makeShortcutAction(QIcon(":/icons/images/yara.png"), "&Yara...", SLOT(yaraSlot()), "ActionYara"));
|
||||
mMenuBuilder->addSeparator();
|
||||
|
||||
mMenuBuilder->addAction(makeShortcutAction("Set New Origin Here", SLOT(setNewOriginHereActionSlot()), "ActionSetNewOriginHere"));
|
||||
|
||||
MenuBuilder* gotoMenu = new MenuBuilder(this);
|
||||
gotoMenu->addAction(makeShortcutAction("Origin", SLOT(gotoOriginSlot()), "ActionGotoOrigin"));
|
||||
gotoMenu->addAction(makeShortcutAction("Previous", SLOT(gotoPreviousSlot()), "ActionGotoPrevious"), [this](QMenu*)
|
||||
{
|
||||
return historyHasPrevious();
|
||||
});
|
||||
gotoMenu->addAction(makeShortcutAction("Next", SLOT(gotoNextSlot()), "ActionGotoNext"), [this](QMenu*)
|
||||
{
|
||||
return historyHasNext();
|
||||
});
|
||||
gotoMenu->addAction(makeShortcutAction("Expression", SLOT(gotoExpressionSlot()), "ActionGotoExpression"));
|
||||
gotoMenu->addAction(makeShortcutAction("File Offset", SLOT(gotoFileOffsetSlot()), "ActionGotoFileOffset"), [this](QMenu*)
|
||||
{
|
||||
char modname[MAX_MODULE_SIZE] = "";
|
||||
return DbgGetModuleAt(rvaToVa(getInitialSelection()), modname);
|
||||
});
|
||||
gotoMenu->addAction(makeShortcutAction("Start of Page", SLOT(gotoStartSlot()), "ActionGotoStart"));
|
||||
gotoMenu->addAction(makeShortcutAction("End of Page", SLOT(gotoEndSlot()), "ActionGotoEnd"));
|
||||
mMenuBuilder->addMenu(makeMenu("Go to"), gotoMenu);
|
||||
mMenuBuilder->addSeparator();
|
||||
|
||||
MenuBuilder* searchMenu = new MenuBuilder(this);
|
||||
searchMenu->addAction(makeShortcutAction("C&ommand", SLOT(findCommandSlot()), "ActionFind"));
|
||||
searchMenu->addAction(makeAction("&Constant", SLOT(findConstantSlot())));
|
||||
searchMenu->addAction(makeAction("&String references", SLOT(findStringsSlot())));
|
||||
searchMenu->addAction(makeAction("&Intermodular calls", SLOT(findCallsSlot())));
|
||||
searchMenu->addAction(makeShortcutAction("&Pattern", SLOT(findPatternSlot()), "ActionFindPattern"));
|
||||
mMenuBuilder->addMenu(makeMenu(QIcon(":/icons/images/search-for.png"), "&Search for"), searchMenu);
|
||||
|
||||
mReferencesMenu = new QMenu("Find &references to", this);
|
||||
mReferenceSelectedAddressAction = makeShortcutAction("&Selected Address(es)", SLOT(findReferencesSlot()), "ActionFindReferencesToSelectedAddress");
|
||||
mReferenceSelectedAddressAction->setFont(QFont("Courier New", 8));
|
||||
|
||||
mSearchMenu = new QMenu("&Search for", this);
|
||||
mSearchMenu->setIcon(QIcon(":/icons/images/search-for.png"));
|
||||
mSearchCommand = makeShortcutMenuAction(mSearchMenu, "C&ommand", SLOT(findCommandSlot()), "ActionFind");
|
||||
mSearchConstant = makeMenuAction(mSearchMenu, "&Constant", SLOT(findConstantSlot()));
|
||||
mSearchStrings = makeMenuAction(mSearchMenu, "&String references", SLOT(findStringsSlot()));
|
||||
mSearchCalls = makeMenuAction(mSearchMenu, "&Intermodular calls", SLOT(findCallsSlot()));
|
||||
mSearchPattern = makeShortcutMenuAction(mSearchMenu, "&Pattern", SLOT(findPatternSlot()), "ActionFindPattern");
|
||||
|
||||
mEnableHighlightingMode = makeShortcutAction(QIcon(":/icons/images/highlight.png"), "&Highlighting mode", SLOT(enableHighlightingModeSlot()), "ActionHighlightingMode");
|
||||
mMenuBuilder->addMenu(makeMenu("Find &references to"), [this](QMenu* menu)
|
||||
{
|
||||
setupFollowReferenceMenu(rvaToVa(getInitialSelection()), menu, true);
|
||||
return true;
|
||||
});
|
||||
|
||||
// Plugins
|
||||
mPluginMenu = new QMenu(this);
|
||||
Bridge::getBridge()->emitMenuAddToList(this, mPluginMenu, GUI_DISASM_MENU);
|
||||
|
||||
mMenuBuilder->addSeparator();
|
||||
mMenuBuilder->addBuilder(new MenuBuilder(this, [this](QMenu* menu)
|
||||
{
|
||||
menu->addActions(mPluginMenu->actions());
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
void CPUDisassembly::gotoOriginSlot()
|
||||
|
@ -471,14 +441,6 @@ void CPUDisassembly::setHwBpOnSlot3ActionSlot()
|
|||
|
||||
void CPUDisassembly::setHwBpAt(duint va, int slot)
|
||||
{
|
||||
BPXTYPE wBpType = DbgGetBpxTypeAt(va);
|
||||
|
||||
if((wBpType & bp_hardware) == bp_hardware)
|
||||
{
|
||||
mBPMenu->addAction(mClearHwBpAction);
|
||||
}
|
||||
|
||||
|
||||
int wI = 0;
|
||||
int wSlotIndex = -1;
|
||||
BPMAP wBPList;
|
||||
|
|
|
@ -88,68 +88,19 @@ protected:
|
|||
|
||||
private:
|
||||
// Menus
|
||||
QMenu* mBinaryMenu;
|
||||
QMenu* mGotoMenu;
|
||||
QMenu* mFollowMenu;
|
||||
QMenu* mBPMenu;
|
||||
QMenu* mHwSlotSelectMenu;
|
||||
QMenu* mReferencesMenu;
|
||||
QMenu* mSearchMenu;
|
||||
QMenu* mCopyMenu;
|
||||
QMenu* mPluginMenu;
|
||||
QMenu* mDecompileMenu;
|
||||
|
||||
// Actions
|
||||
QAction* mBinaryEditAction;
|
||||
QAction* mBinaryFillAction;
|
||||
QAction* mBinaryFillNopsAction;
|
||||
QAction* mBinaryCopyAction;
|
||||
QAction* mBinaryPasteAction;
|
||||
QAction* mBinaryPasteIgnoreSizeAction;
|
||||
QAction* mUndoSelection;
|
||||
QAction* mToggleInt3BpAction;
|
||||
QAction* mSetHwBpAction;
|
||||
QAction* mClearHwBpAction;
|
||||
QAction* mSetNewOriginHere;
|
||||
QAction* mGotoOriginAction;
|
||||
QAction* mSetCommentAction;
|
||||
QAction* mSetLabelAction;
|
||||
QAction* mSetBookmarkAction;
|
||||
QAction* mToggleFunctionAction;
|
||||
QAction* mAssembleAction;
|
||||
QAction* msetHwBPOnSlot0Action;
|
||||
QAction* msetHwBPOnSlot1Action;
|
||||
QAction* msetHwBPOnSlot2Action;
|
||||
QAction* msetHwBPOnSlot3Action;
|
||||
QAction* mGotoExpressionAction;
|
||||
QAction* mGotoFileOffsetAction;
|
||||
QAction* mGotoPreviousAction;
|
||||
QAction* mGotoNextAction;
|
||||
QAction* mGotoStartAction;
|
||||
QAction* mGotoEndAction;
|
||||
QAction* mReferenceSelectedAddressAction;
|
||||
QAction* mSearchCommand;
|
||||
QAction* mSearchConstant;
|
||||
QAction* mSearchStrings;
|
||||
QAction* mSearchCalls;
|
||||
QAction* mSearchPattern;
|
||||
QAction* mEnableHighlightingMode;
|
||||
QAction* mPatchesAction;
|
||||
QAction* mYaraAction;
|
||||
QAction* mCopySelectionAction;
|
||||
QAction* mCopySelectionNoBytesAction;
|
||||
QAction* mCopyAddressAction;
|
||||
QAction* mCopyRvaAction;
|
||||
QAction* mCopyDisassemblyAction;
|
||||
QAction* mOpenSourceAction;
|
||||
QAction* mDecompileSelectionAction;
|
||||
QAction* mDecompileFunctionAction;
|
||||
|
||||
// Goto dialog specific
|
||||
GotoDialog* mGoto;
|
||||
|
||||
// Parent CPU window
|
||||
CPUWidget *mParentCPUWindow;
|
||||
|
||||
MenuBuilder* mMenuBuilder;
|
||||
};
|
||||
|
||||
#endif // CPUDISASSEMBLY_H
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
#ifndef MENUBUILDER
|
||||
#define MENUBUILDER
|
||||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <functional>
|
||||
|
||||
class MenuBuilder : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef std::function<bool(QMenu*)> BuildCallback;
|
||||
|
||||
inline MenuBuilder(QObject* parent, BuildCallback callback = nullptr)
|
||||
: QObject(parent),
|
||||
_callback(callback)
|
||||
{
|
||||
}
|
||||
|
||||
inline void addSeparator()
|
||||
{
|
||||
_containers.push_back(Container());
|
||||
}
|
||||
|
||||
inline QAction* addAction(QAction* action)
|
||||
{
|
||||
_containers.push_back(Container(action));
|
||||
return action;
|
||||
}
|
||||
|
||||
inline QAction* addAction(QAction* action, BuildCallback callback)
|
||||
{
|
||||
addBuilder(new MenuBuilder(action->parent(), callback))->addAction(action);
|
||||
return action;
|
||||
}
|
||||
|
||||
inline QMenu* addMenu(QMenu* menu)
|
||||
{
|
||||
_containers.push_back(Container(menu));
|
||||
return menu;
|
||||
}
|
||||
|
||||
inline QMenu* addMenu(QMenu* submenu, BuildCallback callback)
|
||||
{
|
||||
addBuilder(new MenuBuilder(submenu->parent(), [submenu, callback](QMenu* menu)
|
||||
{
|
||||
submenu->clear();
|
||||
if(callback(submenu));
|
||||
menu->addMenu(submenu);
|
||||
return true;
|
||||
}));
|
||||
return submenu;
|
||||
}
|
||||
|
||||
inline QMenu* addMenu(QMenu* submenu, MenuBuilder* builder)
|
||||
{
|
||||
addBuilder(new MenuBuilder(submenu->parent(), [submenu, builder](QMenu* menu)
|
||||
{
|
||||
submenu->clear();
|
||||
builder->build(submenu);
|
||||
menu->addMenu(submenu);
|
||||
return true;
|
||||
}));
|
||||
return submenu;
|
||||
}
|
||||
|
||||
inline MenuBuilder* addBuilder(MenuBuilder* builder)
|
||||
{
|
||||
_containers.push_back(Container(builder));
|
||||
return builder;
|
||||
}
|
||||
|
||||
inline void build(QMenu* menu) const
|
||||
{
|
||||
if(_callback && !_callback(menu))
|
||||
return;
|
||||
for(const Container & container : _containers)
|
||||
{
|
||||
switch(container.type)
|
||||
{
|
||||
case Container::Separator:
|
||||
menu->addSeparator();
|
||||
break;
|
||||
case Container::Action:
|
||||
menu->addAction(container.action);
|
||||
break;
|
||||
case Container::Menu:
|
||||
menu->addMenu(container.menu);
|
||||
break;
|
||||
case Container::Builder:
|
||||
container.builder->build(menu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct Container
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
Separator,
|
||||
Action,
|
||||
Menu,
|
||||
Builder
|
||||
};
|
||||
|
||||
inline Container()
|
||||
: type(Separator)
|
||||
{
|
||||
}
|
||||
|
||||
inline Container(QAction* action)
|
||||
: type(Action),
|
||||
action(action)
|
||||
{
|
||||
}
|
||||
|
||||
inline Container(QMenu* menu)
|
||||
: type(Menu),
|
||||
menu(menu)
|
||||
{
|
||||
}
|
||||
|
||||
inline Container(MenuBuilder* builder)
|
||||
: type(Builder),
|
||||
builder(builder)
|
||||
{
|
||||
}
|
||||
|
||||
Type type;
|
||||
union
|
||||
{
|
||||
QAction* action;
|
||||
QMenu* menu ;
|
||||
MenuBuilder* builder;
|
||||
};
|
||||
};
|
||||
|
||||
BuildCallback _callback;
|
||||
std::vector<Container> _containers;
|
||||
};
|
||||
|
||||
#endif // MENUBUILDER
|
||||
|
|
@ -217,7 +217,8 @@ HEADERS += \
|
|||
Src/QEntropyView/QEntropyView.h \
|
||||
Src/Gui/EntropyDialog.h \
|
||||
Src/Gui/NotesManager.h \
|
||||
Src/Gui/NotepadView.h
|
||||
Src/Gui/NotepadView.h \
|
||||
Src/Utils/MenuBuilder.h
|
||||
|
||||
FORMS += \
|
||||
Src/Gui/MainWindow.ui \
|
||||
|
|
Loading…
Reference in New Issue