Show context menu with non block specific graph actions everywhere. (#1465)

Fixes #1415
This commit is contained in:
karliss 2019-04-18 13:10:18 +03:00 committed by Itay Cohen
parent 1d4bd7ee7f
commit f3a246985a
3 changed files with 53 additions and 35 deletions

View File

@ -31,7 +31,8 @@
DisassemblerGraphView::DisassemblerGraphView(QWidget *parent) DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
: GraphView(parent), : GraphView(parent),
mFontMetrics(nullptr), mFontMetrics(nullptr),
mMenu(new DisassemblyContextMenu(this)), blockMenu(new DisassemblyContextMenu(this)),
contextMenu(new QMenu(this)),
seekable(new CutterSeekable(this)) seekable(new CutterSeekable(this))
{ {
highlight_token = nullptr; highlight_token = nullptr;
@ -68,10 +69,12 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
// Zoom shortcuts // Zoom shortcuts
QShortcut *shortcut_zoom_in = new QShortcut(QKeySequence(Qt::Key_Plus), this); QShortcut *shortcut_zoom_in = new QShortcut(QKeySequence(Qt::Key_Plus), this);
shortcut_zoom_in->setContext(Qt::WidgetShortcut); shortcut_zoom_in->setContext(Qt::WidgetShortcut);
connect(shortcut_zoom_in, &QShortcut::activated, this, std::bind(&DisassemblerGraphView::zoom, this, QPointF(0.5, 0.5), 1)); connect(shortcut_zoom_in, &QShortcut::activated, this, std::bind(&DisassemblerGraphView::zoom, this,
QPointF(0.5, 0.5), 1));
QShortcut *shortcut_zoom_out = new QShortcut(QKeySequence(Qt::Key_Minus), this); QShortcut *shortcut_zoom_out = new QShortcut(QKeySequence(Qt::Key_Minus), this);
shortcut_zoom_out->setContext(Qt::WidgetShortcut); shortcut_zoom_out->setContext(Qt::WidgetShortcut);
connect(shortcut_zoom_out, &QShortcut::activated, this, std::bind(&DisassemblerGraphView::zoom, this, QPointF(0.5, 0.5), -1)); connect(shortcut_zoom_out, &QShortcut::activated, this, std::bind(&DisassemblerGraphView::zoom,
this, QPointF(0.5, 0.5), -1));
QShortcut *shortcut_zoom_reset = new QShortcut(QKeySequence(Qt::Key_Equal), this); QShortcut *shortcut_zoom_reset = new QShortcut(QKeySequence(Qt::Key_Equal), this);
shortcut_zoom_reset->setContext(Qt::WidgetShortcut); shortcut_zoom_reset->setContext(Qt::WidgetShortcut);
connect(shortcut_zoom_reset, SIGNAL(activated()), this, SLOT(zoomReset())); connect(shortcut_zoom_reset, SIGNAL(activated()), this, SLOT(zoomReset()));
@ -100,20 +103,25 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
shortcuts.append(shortcut_prev_instr); shortcuts.append(shortcut_prev_instr);
// Export Graph menu // Export Graph menu
mMenu->addSeparator();
actionExportGraph.setText(tr("Export Graph")); actionExportGraph.setText(tr("Export Graph"));
mMenu->addAction(&actionExportGraph);
connect(&actionExportGraph, SIGNAL(triggered(bool)), this, SLOT(on_actionExportGraph_triggered())); connect(&actionExportGraph, SIGNAL(triggered(bool)), this, SLOT(on_actionExportGraph_triggered()));
mMenu->addSeparator();
actionSyncOffset.setText(tr("Sync/unsync offset")); actionSyncOffset.setText(tr("Sync/unsync offset"));
mMenu->addAction(&actionSyncOffset);
connect(&actionSyncOffset, SIGNAL(triggered(bool)), this, SLOT(toggleSync())); connect(&actionSyncOffset, SIGNAL(triggered(bool)), this, SLOT(toggleSync()));
// Context menu that applies to everything
contextMenu->addAction(&actionExportGraph);
contextMenu->addSeparator();
contextMenu->addAction(&actionSyncOffset);
// Include all actions from generic context menu in block specific menu
blockMenu->addSeparator();
blockMenu->addActions(contextMenu->actions());
initFont(); initFont();
colorsUpdatedSlot(); colorsUpdatedSlot();
connect(mMenu, SIGNAL(copy()), this, SLOT(copySelection())); connect(blockMenu, &DisassemblyContextMenu::copy, this, &DisassemblerGraphView::copySelection);
header = new QTextEdit(); header = new QTextEdit();
header->setFixedHeight(30); header->setFixedHeight(30);
@ -680,7 +688,7 @@ DisassemblerGraphView::DisassemblyBlock *DisassemblerGraphView::blockForAddress(
void DisassemblerGraphView::onSeekChanged(RVA addr) void DisassemblerGraphView::onSeekChanged(RVA addr)
{ {
mMenu->setOffset(addr); blockMenu->setOffset(addr);
DisassemblyBlock *db = blockForAddress(addr); DisassemblyBlock *db = blockForAddress(addr);
if (db) { if (db) {
// This is a local address! We animated to it. // This is a local address! We animated to it.
@ -856,13 +864,14 @@ void DisassemblerGraphView::blockClicked(GraphView::GraphBlock &block, QMouseEve
RVA addr = instr->addr; RVA addr = instr->addr;
seekLocal(addr); seekLocal(addr);
mMenu->setOffset(addr); blockMenu->setOffset(addr);
mMenu->setCanCopy(highlight_token); blockMenu->setCanCopy(highlight_token);
if (highlight_token) { if (highlight_token) {
mMenu->setCurHighlightedWord(highlight_token->content); blockMenu->setCurHighlightedWord(highlight_token->content);
} }
if (event->button() == Qt::RightButton) { if (event->button() == Qt::RightButton) {
mMenu->exec(event->globalPos()); event->accept();
blockMenu->exec(event->globalPos());
} }
viewport()->update(); viewport()->update();
} }
@ -962,6 +971,10 @@ void DisassemblerGraphView::on_actionExportGraph_triggered()
void DisassemblerGraphView::mousePressEvent(QMouseEvent *event) void DisassemblerGraphView::mousePressEvent(QMouseEvent *event)
{ {
GraphView::mousePressEvent(event); GraphView::mousePressEvent(event);
if (!event->isAccepted() && event->button() == Qt::RightButton) {
contextMenu->exec(event->globalPos());
event->accept();
}
emit graphMoved(); emit graphMoved();
} }

View File

@ -148,7 +148,8 @@ private:
int baseline; int baseline;
bool emptyGraph; bool emptyGraph;
DisassemblyContextMenu *mMenu; DisassemblyContextMenu *blockMenu;
QMenu *contextMenu;
void connectSeekChanged(bool disconnect); void connectSeekChanged(bool disconnect);

View File

@ -443,25 +443,27 @@ void GraphView::mousePressEvent(QMouseEvent *event)
} }
// Check if a line beginning/end was clicked // Check if a line beginning/end was clicked
for (auto &blockIt : blocks) { if (event->button() == Qt::LeftButton) {
GraphBlock &block = blockIt.second; for (auto &blockIt : blocks) {
for (GraphEdge &edge : block.edges) { GraphBlock &block = blockIt.second;
if (edge.polyline.length() < 2) { for (GraphEdge &edge : block.edges) {
continue; if (edge.polyline.length() < 2) {
} continue;
QPointF start = edge.polyline.first(); }
QPointF end = edge.polyline.last(); QPointF start = edge.polyline.first();
if (checkPointClicked(start, x, y)) { QPointF end = edge.polyline.last();
showBlock(blocks[edge.target]); if (checkPointClicked(start, x, y)) {
// TODO: Callback to child showBlock(blocks[edge.target]);
return; // TODO: Callback to child
break; return;
} break;
if (checkPointClicked(end, x, y, true)) { }
showBlock(block); if (checkPointClicked(end, x, y, true)) {
// TODO: Callback to child showBlock(block);
return; // TODO: Callback to child
break; return;
break;
}
} }
} }
} }
@ -470,8 +472,10 @@ void GraphView::mousePressEvent(QMouseEvent *event)
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {
//Left click outside any block, enter scrolling mode //Left click outside any block, enter scrolling mode
beginMouseDrag(event); beginMouseDrag(event);
return;
} }
QAbstractScrollArea::mousePressEvent(event);
} }
void GraphView::mouseMoveEvent(QMouseEvent *event) void GraphView::mouseMoveEvent(QMouseEvent *event)