Skip to content
Permalink
Browse files

GraphView: Fixed shortcuts

  • Loading branch information...
Dax89 committed May 10, 2019
1 parent 76ee7ec commit 2bea3b1d0678117f01dc1dfde45c9d69325ac138
@@ -6,11 +6,17 @@
#include <QMessageBox>
#include <QClipboard>

DisassemblerActions::DisassemblerActions(QWidget *parent): QObject(parent), m_renderer(nullptr) { this->createActions(); }
DisassemblerActions::DisassemblerActions(REDasm::ListingRenderer* renderer, QWidget *parent) : QObject(parent), m_renderer(renderer) { this->createActions(); }
void DisassemblerActions::popup(const QPoint &pos) { m_contextmenu->exec(pos); }
void DisassemblerActions::setCurrentRenderer(REDasm::ListingRenderer *renderer) { m_renderer = renderer; }
REDasm::ListingRenderer *DisassemblerActions::renderer() const { return m_renderer; }
void DisassemblerActions::popup(const QPoint &pos) { if(m_renderer) m_contextmenu->exec(pos); }

void DisassemblerActions::adjustActions()
{
if(!m_renderer)
return;

auto lock = REDasm::s_lock_safe_ptr(m_renderer->document());
const REDasm::ListingItem* item = lock->currentItem();

@@ -66,7 +72,7 @@ void DisassemblerActions::adjustActions()
m_actions[DisassemblerActions::HexDumpFunction]->setVisible(itemsegment && !itemsegment->is(REDasm::SegmentType::Bss) && itemsegment->is(REDasm::SegmentType::Code));
}

void DisassemblerActions::goTo(address_t address) { m_renderer->document()->goTo(address); }
void DisassemblerActions::goTo(address_t address) { if(m_renderer) m_renderer->document()->goTo(address); }

void DisassemblerActions::createActions()
{
@@ -77,7 +83,7 @@ void DisassemblerActions::createActions()
m_actions[DisassemblerActions::Comment] = m_contextmenu->addAction("Comment", this, &DisassemblerActions::addComment, QKeySequence(Qt::Key_Semicolon));
m_contextmenu->addSeparator();
m_actions[DisassemblerActions::XRefs] = m_contextmenu->addAction("Cross References", this, &DisassemblerActions::showReferencesUnderCursor, QKeySequence(Qt::Key_X));
m_actions[DisassemblerActions::Follow] = m_contextmenu->addAction("Follow", this, &DisassemblerActions::followUnderCursor);
m_actions[DisassemblerActions::Follow] = m_contextmenu->addAction("Follow", this, QOverload<>::of(&DisassemblerActions::followUnderCursor));
m_actions[DisassemblerActions::FollowPointerHexDump] = m_contextmenu->addAction("Follow pointer in Hex Dump", this, &DisassemblerActions::followPointerHexDump);
m_actions[DisassemblerActions::Goto] = m_contextmenu->addAction("Goto...", this, &DisassemblerActions::gotoDialogRequested, QKeySequence(Qt::Key_G));
m_actions[DisassemblerActions::CallGraph] = m_contextmenu->addAction("Call Graph", this, &DisassemblerActions::showCallGraph, QKeySequence(Qt::CTRL + Qt::Key_G));
@@ -90,21 +96,27 @@ void DisassemblerActions::createActions()
m_contextmenu->addSeparator();
m_actions[DisassemblerActions::Copy] = m_contextmenu->addAction("Copy", this, &DisassemblerActions::copy, QKeySequence(QKeySequence::Copy));

pw->addAction(m_actions[DisassemblerActions::Rename]);
pw->addAction(m_actions[DisassemblerActions::XRefs]);
pw->addAction(m_actions[DisassemblerActions::Comment]);
pw->addAction(m_actions[DisassemblerActions::Goto]);
pw->addAction(m_actions[DisassemblerActions::CallGraph]);
pw->addAction(m_actions[DisassemblerActions::HexDump]);
pw->addAction(m_actions[DisassemblerActions::Back]);
pw->addAction(m_actions[DisassemblerActions::Forward]);
pw->addAction(m_actions[DisassemblerActions::Copy]);
if(pw)
{
pw->addAction(m_actions[DisassemblerActions::Rename]);
pw->addAction(m_actions[DisassemblerActions::XRefs]);
pw->addAction(m_actions[DisassemblerActions::Comment]);
pw->addAction(m_actions[DisassemblerActions::Goto]);
pw->addAction(m_actions[DisassemblerActions::CallGraph]);
pw->addAction(m_actions[DisassemblerActions::HexDump]);
pw->addAction(m_actions[DisassemblerActions::Back]);
pw->addAction(m_actions[DisassemblerActions::Forward]);
pw->addAction(m_actions[DisassemblerActions::Copy]);
}

connect(m_contextmenu, &QMenu::aboutToShow, this, &DisassemblerActions::adjustActions);
}

void DisassemblerActions::renameSymbolUnderCursor()
{
if(!m_renderer)
return;

const REDasm::Symbol* symbol = m_renderer->symbolUnderCursor();

if(!symbol || symbol->isLocked())
@@ -125,6 +137,9 @@ void DisassemblerActions::renameSymbolUnderCursor()

bool DisassemblerActions::followUnderCursor()
{
if(!m_renderer)
return false;

const REDasm::Symbol* symbol = m_renderer->symbolUnderCursor();

if(symbol)
@@ -16,7 +16,10 @@ class DisassemblerActions : public QObject
Back, Forward, Copy };

public:
explicit DisassemblerActions(QWidget *parent = nullptr);
explicit DisassemblerActions(REDasm::ListingRenderer *renderer, QWidget *parent = nullptr);
void setCurrentRenderer(REDasm::ListingRenderer* renderer);
REDasm::ListingRenderer* renderer() const;

public slots:
bool followUnderCursor();
@@ -16,7 +16,6 @@ DisassemblerBlockItem::DisassemblerBlockItem(const REDasm::Graphing::FunctionBas
m_renderer = std::make_unique<ListingDocumentRenderer>(disassembler.get());
m_renderer->setFirstVisibleLine(fbb->startidx);
m_renderer->setFlags(ListingDocumentRenderer::HideSegmentName);
m_actions = new DisassemblerActions(m_renderer.get(), parent);
this->invalidate(false);

QFontMetricsF fm(m_document.defaultFont());
@@ -32,27 +31,22 @@ DisassemblerBlockItem::DisassemblerBlockItem(const REDasm::Graphing::FunctionBas

DisassemblerBlockItem::~DisassemblerBlockItem() { EVENT_DISCONNECT(m_disassembler->document()->cursor(), positionChanged, this); }
std::string DisassemblerBlockItem::currentWord() { return m_renderer->getCurrentWord(); }
DisassemblerActions *DisassemblerBlockItem::disassemblerActions() const { return m_actions; }
ListingDocumentRenderer *DisassemblerBlockItem::renderer() const { return m_renderer.get(); }
bool DisassemblerBlockItem::hasIndex(s64 index) const { return m_basicblock->contains(index); }
QSize DisassemblerBlockItem::size() const { return this->documentSize(); }
void DisassemblerBlockItem::itemSelectionChanged(bool selected) { m_actions->setEnabled(selected); }

void DisassemblerBlockItem::mouseDoubleClickEvent(QMouseEvent *e)
{
if(!m_actions->followUnderCursor())
m_renderer->selectWordAt(e->localPos());

emit followRequested(e->localPos());
e->accept();
}

void DisassemblerBlockItem::mousePressEvent(QMouseEvent *e)
{
if(e->buttons() == Qt::LeftButton)
m_renderer->moveTo(e->localPos());
else if(e->buttons() == Qt::RightButton)
m_actions->popup(QCursor::pos());
else
return;
GraphViewItem::mousePressEvent(e);

e->accept();
}
@@ -15,15 +15,14 @@ class DisassemblerBlockItem : public GraphViewItem
explicit DisassemblerBlockItem(const REDasm::Graphing::FunctionBasicBlock* fbb, const REDasm::DisassemblerPtr& disassembler, const REDasm::Graphing::Node& node, QWidget *parent = nullptr);
virtual ~DisassemblerBlockItem();
std::string currentWord();
DisassemblerActions* disassemblerActions() const;
ListingDocumentRenderer* renderer() const;
bool hasIndex(s64 index) const;

public:
void render(QPainter* painter, size_t state) override;
QSize size() const override;

protected:
void itemSelectionChanged(bool selected) override;
void mouseDoubleClickEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
@@ -33,10 +32,12 @@ class DisassemblerBlockItem : public GraphViewItem
QSize documentSize() const;
void setupDocument();

signals:
void followRequested(const QPointF& localpos);

private:
const REDasm::Graphing::FunctionBasicBlock* m_basicblock;
std::unique_ptr<ListingDocumentRenderer> m_renderer;
DisassemblerActions* m_actions;
REDasm::DisassemblerPtr m_disassembler;
QTextDocument m_document;
qreal m_charheight;
@@ -10,8 +10,18 @@

DisassemblerGraphView::DisassemblerGraphView(QWidget *parent): GraphView(parent), m_currentfunction(nullptr)
{
this->setFocusPolicy(Qt::StrongFocus);
m_blinktimer = this->startTimer(CURSOR_BLINK_INTERVAL);
this->setFocusPolicy(Qt::StrongFocus);


m_disassembleractions = new DisassemblerActions(this);
connect(m_disassembleractions, &DisassemblerActions::gotoDialogRequested, this, &DisassemblerGraphView::gotoDialogRequested);
connect(m_disassembleractions, &DisassemblerActions::hexDumpRequested, this, &DisassemblerGraphView::hexDumpRequested);
connect(m_disassembleractions, &DisassemblerActions::referencesRequested, this, &DisassemblerGraphView::referencesRequested);
connect(m_disassembleractions, &DisassemblerActions::switchToHexDump, this, &DisassemblerGraphView::switchToHexDump);
connect(m_disassembleractions, &DisassemblerActions::callGraphRequested, this, &DisassemblerGraphView::callGraphRequested);

connect(this, &DisassemblerGraphView::selectedItemChanged, this, &DisassemblerGraphView::updateCurrentRenderer);
}

DisassemblerGraphView::~DisassemblerGraphView()
@@ -42,16 +52,14 @@ std::string DisassemblerGraphView::currentWord()

void DisassemblerGraphView::computeLayout()
{
m_disassembleractions->setCurrentRenderer(nullptr);

for(const auto& n : this->graph()->nodes())
{
const auto* fbb = static_cast<REDasm::Graphing::FunctionGraph*>(this->graph())->data(n);
auto* dbi = new DisassemblerBlockItem(fbb, m_disassembler, n, this->viewport());

connect(dbi->disassemblerActions(), &DisassemblerActions::gotoDialogRequested, this, &DisassemblerGraphView::gotoDialogRequested);
connect(dbi->disassemblerActions(), &DisassemblerActions::hexDumpRequested, this, &DisassemblerGraphView::hexDumpRequested);
connect(dbi->disassemblerActions(), &DisassemblerActions::referencesRequested, this, &DisassemblerGraphView::referencesRequested);
connect(dbi->disassemblerActions(), &DisassemblerActions::switchToHexDump, this, &DisassemblerGraphView::switchToHexDump);
connect(dbi->disassemblerActions(), &DisassemblerActions::callGraphRequested, this, &DisassemblerGraphView::callGraphRequested);
connect(dbi, &DisassemblerBlockItem::followRequested, this, &DisassemblerGraphView::onFollowRequested);
connect(dbi, &DisassemblerBlockItem::menuRequested, this, &DisassemblerGraphView::onMenuRequested);

m_items[n] = dbi;
this->graph()->width(n, dbi->width());
@@ -70,6 +78,33 @@ void DisassemblerGraphView::computeLayout()
GraphView::computeLayout();
}

void DisassemblerGraphView::updateCurrentRenderer()
{
GraphViewItem* selecteditem = this->selectedItem();

if(selecteditem)
m_disassembleractions->setCurrentRenderer(static_cast<DisassemblerBlockItem*>(selecteditem)->renderer());
else
m_disassembleractions->setCurrentRenderer(nullptr);
}

void DisassemblerGraphView::onFollowRequested(const QPointF& localpos)
{
if(!m_disassembleractions->renderer())
return;

if(!m_disassembleractions->followUnderCursor())
static_cast<ListingRendererCommon*>(m_disassembleractions->renderer())->selectWordAt(localpos);
}

void DisassemblerGraphView::onMenuRequested()
{
if(!m_disassembleractions->renderer())
return;

m_disassembleractions->popup(QCursor::pos());
}

void DisassemblerGraphView::goTo(address_t address)
{
auto& document = m_disassembler->document();
@@ -33,6 +33,11 @@ class DisassemblerGraphView : public GraphView
void timerEvent(QTimerEvent* e) override;
void computeLayout() override;

private slots:
void updateCurrentRenderer();
void onFollowRequested(const QPointF &localpos);
void onMenuRequested();

signals:
void switchView();
void hexDumpRequested(address_t address, u64 len);
@@ -43,6 +48,7 @@ class DisassemblerGraphView : public GraphView

private:
const REDasm::ListingItem* m_currentfunction;
DisassemblerActions* m_disassembleractions;
int m_blinktimer;
};

@@ -2,6 +2,7 @@
#include <QMouseEvent>
#include <QScrollBar>
#include <QPainter>
#include <QDebug>

GraphView::GraphView(QWidget *parent): QAbstractScrollArea(parent), m_disassembler(nullptr), m_selecteditem(nullptr)
{
@@ -50,43 +51,20 @@ void GraphView::focusBlock(const GraphViewItem *item)

void GraphView::mouseDoubleClickEvent(QMouseEvent* e)
{
GraphViewItem* olditem = m_selecteditem;
m_selecteditem = this->itemFromMouseEvent(e);

if(olditem)
{
olditem->itemSelectionChanged(false);
olditem->invalidate();
}
this->updateSelectedItem(e);

if(m_selecteditem && (e->buttons() == Qt::LeftButton))
{
m_selecteditem->itemSelectionChanged(false);
m_selecteditem->mouseDoubleClickEvent(e);
}

QAbstractScrollArea::mouseDoubleClickEvent(e);
}

void GraphView::mousePressEvent(QMouseEvent *e)
{
GraphViewItem* olditem = m_selecteditem;
m_selecteditem = this->itemFromMouseEvent(e);

if(olditem && (olditem != m_selecteditem))
{
olditem->itemSelectionChanged(false);
olditem->invalidate();
}
this->updateSelectedItem(e);

if(m_selecteditem)
{
if(olditem != m_selecteditem)
{
m_selecteditem->itemSelectionChanged(true);
m_selecteditem->mousePressEvent(e);
}
}
m_selecteditem->mousePressEvent(e);
else if(e->button() == Qt::LeftButton)
{
m_scrollmode = true;
@@ -115,12 +93,11 @@ void GraphView::mouseReleaseEvent(QMouseEvent *e)

void GraphView::mouseMoveEvent(QMouseEvent *e)
{
GraphViewItem* item = this->itemFromMouseEvent(e);
m_selecteditem = item;
this->updateSelectedItem(e);

if(item)
if(m_selecteditem)
{
item->mouseMoveEvent(e);
m_selecteditem->mouseMoveEvent(e);
return;
}

@@ -382,3 +359,21 @@ void GraphView::precomputeLine(const REDasm::Graphing::Edge &e)

m_lines[e] = lines;
}

void GraphView::updateSelectedItem(QMouseEvent *e)
{
GraphViewItem* olditem = m_selecteditem;
m_selecteditem = this->itemFromMouseEvent(e);

if(olditem)
{
olditem->itemSelectionChanged(false);
olditem->invalidate();
}

if(m_selecteditem)
m_selecteditem->itemSelectionChanged(false);

if(olditem != m_selecteditem)
emit selectedItemChanged();
}
@@ -45,11 +45,15 @@ class GraphView : public QAbstractScrollArea
void adjustSize(int vpw, int vph, const QPoint& cursorpos = QPoint(), bool fit = false);
void precomputeArrow(const REDasm::Graphing::Edge& e);
void precomputeLine(const REDasm::Graphing::Edge& e);
void updateSelectedItem(QMouseEvent* e);

protected:
REDasm::DisassemblerPtr m_disassembler;
QHash<REDasm::Graphing::Node, GraphViewItem*> m_items;

signals:
void selectedItemChanged();

private:
GraphViewItem* m_selecteditem;
REDasm::Graphing::Graph* m_graph;
@@ -14,6 +14,6 @@ void GraphViewItem::move(const QPoint &pos) { m_pos = pos; }
void GraphViewItem::itemSelectionChanged(bool selected) { }
QPoint GraphViewItem::mapToItem(const QPoint &p) const { return QPoint(p.x() - m_pos.x(), p.y() - m_pos.y()); }
void GraphViewItem::mouseDoubleClickEvent(QMouseEvent *e) { }
void GraphViewItem::mousePressEvent(QMouseEvent* e) { }
void GraphViewItem::mousePressEvent(QMouseEvent* e) { if(e->buttons() == Qt::RightButton) emit menuRequested(); }
void GraphViewItem::mouseMoveEvent(QMouseEvent *e) { }
void GraphViewItem::invalidate(bool notify) { if(notify) emit invalidated(); }
@@ -41,6 +41,7 @@ class GraphViewItem: public QObject

signals:
void invalidated();
void menuRequested();

private:
QPoint m_pos;

0 comments on commit 2bea3b1

Please sign in to comment.
You can’t perform that action at this time.