mirror of
https://github.com/rizinorg/cutter.git
synced 2025-02-20 13:46:06 +00:00
Graph scrolling forever (#1195)
* Replace scroll algorithm with just using offset * WIP * Text is now shown properly on each node * WIP * Scaling well WIP * Fix positioning for Graph * Overview properly displays Rect WIP * Rect in overview moves along with the mouse WIP * Overview rect properly moves WIP * mouse properly moves WIP * in middle of fixing resizing WIP * scaling issue WIP * Properly zooms * almost done * Edge width fixed for the overview * Fixed a small bug * Clean up
This commit is contained in:
parent
9a02dd24a7
commit
f8cebe0e30
@ -320,12 +320,7 @@ void DisassemblerGraphView::loadCurrentGraph()
|
||||
|
||||
if (!func["blocks"].toArray().isEmpty()) {
|
||||
computeGraph(entry);
|
||||
viewport()->update();
|
||||
|
||||
if (first_draw) {
|
||||
showBlock(blocks[entry]);
|
||||
first_draw = false;
|
||||
}
|
||||
showBlock(blocks[entry]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,9 +377,12 @@ void DisassemblerGraphView::initFont()
|
||||
|
||||
void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
{
|
||||
int blockX = block.x - offset_x;
|
||||
int blockY = block.y - offset_y;
|
||||
|
||||
p.setPen(Qt::black);
|
||||
p.setBrush(Qt::gray);
|
||||
p.drawRect(block.x, block.y, block.width, block.height);
|
||||
p.drawRect(blockX, blockY, block.width, block.height);
|
||||
|
||||
breakpoints = Core()->getBreakpointsAddresses();
|
||||
|
||||
@ -419,7 +417,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
}
|
||||
|
||||
// Node's shadow effect
|
||||
p.drawRect(block.x + 2, block.y + 2,
|
||||
p.drawRect(blockX + 2, blockY + 2,
|
||||
block.width, block.height);
|
||||
p.setPen(QPen(graphNodeColor, 1));
|
||||
|
||||
@ -429,12 +427,12 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
p.setBrush(disassemblyBackgroundColor);
|
||||
}
|
||||
|
||||
p.drawRect(block.x, block.y,
|
||||
p.drawRect(blockX, blockY,
|
||||
block.width, block.height);
|
||||
|
||||
// Draw different background for selected instruction
|
||||
if (selected_instruction != RVA_INVALID) {
|
||||
int y = static_cast<int>(block.y + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
|
||||
int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
|
||||
for (const Instr &instr : db.instrs) {
|
||||
if (instr.addr > selected_instruction) {
|
||||
break;
|
||||
@ -443,11 +441,11 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
//auto traceCount = dbgfunctions->GetTraceRecordHitCount(instr.addr);
|
||||
auto traceCount = 0;
|
||||
if (selected && traceCount) {
|
||||
p.fillRect(QRect(static_cast<int>(block.x + charWidth), y,
|
||||
p.fillRect(QRect(static_cast<int>(blockX + charWidth), y,
|
||||
static_cast<int>(block.width - (10 + 2 * charWidth)),
|
||||
int(instr.text.lines.size()) * charHeight), disassemblyTracedSelectionColor);
|
||||
} else if (selected) {
|
||||
p.fillRect(QRect(static_cast<int>(block.x + charWidth), y,
|
||||
p.fillRect(QRect(static_cast<int>(blockX + charWidth), y,
|
||||
static_cast<int>(block.width - (10 + 2 * charWidth)),
|
||||
int(instr.text.lines.size()) * charHeight), disassemblySelectionColor);
|
||||
} else if (traceCount) {
|
||||
@ -461,7 +459,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
if (disassemblyTracedColor.blue() > 160)
|
||||
colorDiff *= -1;
|
||||
|
||||
p.fillRect(QRect(static_cast<int>(block.x + charWidth), y,
|
||||
p.fillRect(QRect(static_cast<int>(blockX + charWidth), y,
|
||||
static_cast<int>(block.width - (10 + 2 * charWidth)),
|
||||
int(instr.text.lines.size()) * charHeight),
|
||||
QColor(disassemblyTracedColor.red(),
|
||||
@ -474,7 +472,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
|
||||
// highlight selected tokens
|
||||
if (highlight_token != nullptr) {
|
||||
int y = static_cast<int>(block.y + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
|
||||
int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
|
||||
int tokenWidth = mFontMetrics->width(highlight_token->content);
|
||||
|
||||
for (const Instr &instr : db.instrs) {
|
||||
@ -500,7 +498,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
|
||||
QColor selectionColor = ConfigColor("highlightWord");
|
||||
|
||||
p.fillRect(QRect(static_cast<int>(block.x + charWidth * 3 + widthBefore), y, highlightWidth,
|
||||
p.fillRect(QRect(static_cast<int>(blockX + charWidth * 3 + widthBefore), y, highlightWidth,
|
||||
charHeight), selectionColor);
|
||||
}
|
||||
|
||||
@ -510,14 +508,14 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
|
||||
// highlight program counter
|
||||
if (PCInBlock) {
|
||||
int y = static_cast<int>(block.y + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
|
||||
int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
|
||||
for (const Instr &instr : db.instrs) {
|
||||
if (instr.addr > PCAddr) {
|
||||
break;
|
||||
}
|
||||
auto PC = instr.addr == PCAddr;
|
||||
if (PC) {
|
||||
p.fillRect(QRect(static_cast<int>(block.x + charWidth), y,
|
||||
p.fillRect(QRect(static_cast<int>(blockX + charWidth), y,
|
||||
static_cast<int>(block.width - (10 + 2 * charWidth)),
|
||||
int(instr.text.lines.size()) * charHeight), PCSelectionColor);
|
||||
}
|
||||
@ -525,20 +523,18 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
}
|
||||
}
|
||||
|
||||
qreal render_offset_y = -verticalScrollBar()->value() * current_scale + unscrolled_render_offset_y;
|
||||
qreal render_height = viewport()->size().height();
|
||||
|
||||
// Render node text
|
||||
auto x = block.x + (2 * charWidth);
|
||||
int y = static_cast<int>(block.y + (2 * charWidth));
|
||||
auto x = blockX + (2 * charWidth);
|
||||
int y = static_cast<int>(blockY + (2 * charWidth));
|
||||
qreal lineHeightRender = charHeight;
|
||||
for (auto &line : db.header_text.lines) {
|
||||
qreal lineYRender = y * current_scale;
|
||||
qreal lineHeightRender = charHeight * current_scale;
|
||||
qreal lineYRender = y;
|
||||
|
||||
// Check if line does NOT intersects with view area
|
||||
if (-render_offset_y >= lineYRender + lineHeightRender
|
||||
|| -render_offset_y + render_height <= lineYRender) {
|
||||
// Skip if it does not intersects
|
||||
if (0 > lineYRender + lineHeightRender
|
||||
|| render_height < lineYRender) {
|
||||
y += charHeight;
|
||||
continue;
|
||||
}
|
||||
@ -550,23 +546,20 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
|
||||
for (const Instr &instr : db.instrs) {
|
||||
if (Core()->isBreakpoint(breakpoints, instr.addr)) {
|
||||
p.fillRect(QRect(static_cast<int>(block.x + charWidth), y,
|
||||
p.fillRect(QRect(static_cast<int>(blockX + charWidth), y,
|
||||
static_cast<int>(block.width - (10 + 2 * charWidth)),
|
||||
int(instr.text.lines.size()) * charHeight), ConfigColor("gui.breakpoint_background"));
|
||||
if (instr.addr == selected_instruction) {
|
||||
p.fillRect(QRect(static_cast<int>(block.x + charWidth), y,
|
||||
p.fillRect(QRect(static_cast<int>(blockX + charWidth), y,
|
||||
static_cast<int>(block.width - (10 + 2 * charWidth)),
|
||||
int(instr.text.lines.size()) * charHeight), disassemblySelectionColor);
|
||||
}
|
||||
}
|
||||
for (auto &line : instr.text.lines) {
|
||||
qreal lineYRender = y * current_scale;
|
||||
qreal lineHeightRender = charHeight * current_scale;
|
||||
qreal lineYRender = y;
|
||||
|
||||
// Check if line does NOT intersects with view area
|
||||
if (-render_offset_y >= lineYRender + lineHeightRender
|
||||
|| -render_offset_y + render_height <= lineYRender) {
|
||||
// Skip if it does not intersects
|
||||
if (0 > lineYRender + lineHeightRender
|
||||
|| render_height < lineYRender) {
|
||||
y += charHeight;
|
||||
continue;
|
||||
}
|
||||
@ -706,7 +699,7 @@ void DisassemblerGraphView::onSeekChanged(RVA addr)
|
||||
if (db) {
|
||||
// This is a local address! We animated to it.
|
||||
transition_dont_seek = true;
|
||||
showBlock(&blocks[db->entry], true);
|
||||
showBlock(&blocks[db->entry]);
|
||||
prepareHeader();
|
||||
} else {
|
||||
refreshView();
|
||||
@ -714,7 +707,7 @@ void DisassemblerGraphView::onSeekChanged(RVA addr)
|
||||
if (db) {
|
||||
// This is a local address! We animated to it.
|
||||
transition_dont_seek = true;
|
||||
showBlock(&blocks[db->entry], true);
|
||||
showBlock(&blocks[db->entry]);
|
||||
prepareHeader();
|
||||
} else {
|
||||
header->hide();
|
||||
@ -724,19 +717,17 @@ void DisassemblerGraphView::onSeekChanged(RVA addr)
|
||||
|
||||
void DisassemblerGraphView::zoomIn(QPoint mouse)
|
||||
{
|
||||
Q_UNUSED(mouse);
|
||||
current_scale += 0.1;
|
||||
auto areaSize = viewport()->size();
|
||||
adjustSize(areaSize.width(), areaSize.height(), mouse);
|
||||
viewport()->update();
|
||||
emit viewZoomed();
|
||||
}
|
||||
|
||||
void DisassemblerGraphView::zoomOut(QPoint mouse)
|
||||
{
|
||||
Q_UNUSED(mouse);
|
||||
current_scale -= 0.1;
|
||||
current_scale = std::max(current_scale, 0.3);
|
||||
auto areaSize = viewport()->size();
|
||||
adjustSize(areaSize.width(), areaSize.height(), mouse);
|
||||
viewport()->update();
|
||||
emit viewZoomed();
|
||||
}
|
||||
@ -744,8 +735,6 @@ void DisassemblerGraphView::zoomOut(QPoint mouse)
|
||||
void DisassemblerGraphView::zoomReset()
|
||||
{
|
||||
current_scale = 1.0;
|
||||
auto areaSize = viewport()->size();
|
||||
adjustSize(areaSize.width(), areaSize.height());
|
||||
viewport()->update();
|
||||
emit viewZoomed();
|
||||
}
|
||||
|
@ -158,7 +158,6 @@ private slots:
|
||||
void on_actionExportGraph_triggered();
|
||||
|
||||
private:
|
||||
bool first_draw = true;
|
||||
bool transition_dont_seek = false;
|
||||
|
||||
Token *highlight_token;
|
||||
|
@ -9,12 +9,6 @@
|
||||
GraphView::GraphView(QWidget *parent)
|
||||
: QAbstractScrollArea(parent)
|
||||
{
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
horizontalScrollBar()->setSingleStep(charWidth);
|
||||
verticalScrollBar()->setSingleStep(charWidth);
|
||||
QSize areaSize = viewport()->size();
|
||||
adjustSize(areaSize.width(), areaSize.height());
|
||||
}
|
||||
|
||||
GraphView::~GraphView()
|
||||
@ -70,10 +64,8 @@ void GraphView::blockHelpEvent(GraphView::GraphBlock &block, QHelpEvent *event,
|
||||
|
||||
bool GraphView::helpEvent(QHelpEvent *event)
|
||||
{
|
||||
int x = ((event->pos().x() - unscrolled_render_offset_x) / current_scale) +
|
||||
horizontalScrollBar()->value();
|
||||
int y = ((event->pos().y() - unscrolled_render_offset_y) / current_scale) +
|
||||
verticalScrollBar()->value();
|
||||
int x = event->pos().x() + offset_x;
|
||||
int y = event->pos().y() - offset_y;
|
||||
|
||||
for (auto &blockIt : blocks) {
|
||||
GraphBlock &block = blockIt.second;
|
||||
@ -105,32 +97,6 @@ GraphView::EdgeConfiguration GraphView::edgeConfiguration(GraphView::GraphBlock
|
||||
return ec;
|
||||
}
|
||||
|
||||
void GraphView::adjustSize(int new_width, int new_height, QPoint mouse)
|
||||
{
|
||||
int originalRangeX = horizontalScrollBar()->maximum();
|
||||
int originalRangeY = verticalScrollBar()->maximum();
|
||||
int newMaxX = width - (new_width / current_scale);
|
||||
int newMaxY = height - (new_height / current_scale);
|
||||
|
||||
// Update scroll bar information
|
||||
horizontalScrollBar()->setPageStep(new_width);
|
||||
horizontalScrollBar()->setRange(0, newMaxX);
|
||||
verticalScrollBar()->setPageStep(new_height);
|
||||
verticalScrollBar()->setRange(0, newMaxY);
|
||||
|
||||
// Compute new scrollBar values so that the mouse always points
|
||||
// to the same place when zooming
|
||||
QPoint mouseLocal = mapFromGlobal(mouse);
|
||||
|
||||
int topX = horizontalScrollBar()->value();
|
||||
int topY = verticalScrollBar()->value();
|
||||
|
||||
int dx = newMaxX - originalRangeX;
|
||||
int dy = newMaxY - originalRangeY;
|
||||
horizontalScrollBar()->setValue(topX + dx * ((float)mouseLocal.x() / new_width));
|
||||
verticalScrollBar()->setValue(topY + dy * ((float)mouseLocal.y() / new_height));
|
||||
}
|
||||
|
||||
bool GraphView::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip) {
|
||||
@ -145,8 +111,6 @@ bool GraphView::event(QEvent *event)
|
||||
// This calculates the full graph starting at block entry.
|
||||
void GraphView::computeGraph(ut64 entry)
|
||||
{
|
||||
QSize areaSize = viewport()->size();
|
||||
|
||||
// Populate incoming lists
|
||||
for (auto &blockIt : blocks) {
|
||||
GraphBlock &block = blockIt.second;
|
||||
@ -403,8 +367,15 @@ void GraphView::computeGraph(ut64 entry)
|
||||
ready = true;
|
||||
|
||||
viewport()->update();
|
||||
areaSize = viewport()->size();
|
||||
adjustSize(areaSize.width(), areaSize.height());
|
||||
}
|
||||
|
||||
QPolygonF GraphView::recalculatePolygon(QPolygonF polygon)
|
||||
{
|
||||
QPolygonF ret;
|
||||
for (int i = 0; i < polygon.size(); i++) {
|
||||
ret << QPointF(polygon[i].x() - offset_x, polygon[i].y() - offset_y);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GraphView::paintEvent(QPaintEvent *event)
|
||||
@ -414,53 +385,29 @@ void GraphView::paintEvent(QPaintEvent *event)
|
||||
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
int render_offset_x = -horizontalScrollBar()->value() * current_scale;
|
||||
int render_offset_y = -verticalScrollBar()->value() * current_scale;
|
||||
int render_width = viewport()->size().width();
|
||||
int render_height = viewport()->size().height();
|
||||
int render_width = viewport()->width();
|
||||
int render_height = viewport()->height();
|
||||
|
||||
// Do we have scrollbars?
|
||||
bool hscrollbar = horizontalScrollBar()->pageStep() < width * current_scale;
|
||||
bool vscrollbar = verticalScrollBar()->pageStep() < height * current_scale;
|
||||
|
||||
// Draw background
|
||||
QRect viewportRect(viewport()->rect().topLeft(), viewport()->rect().bottomRight() - QPoint(1, 1));
|
||||
p.setBrush(backgroundColor);
|
||||
p.drawRect(viewportRect);
|
||||
p.setBrush(Qt::black);
|
||||
|
||||
unscrolled_render_offset_x = 0;
|
||||
unscrolled_render_offset_y = 0;
|
||||
|
||||
// We do not have a scrollbar on this axis, so we center the view
|
||||
if (!hscrollbar) {
|
||||
unscrolled_render_offset_x = (viewport()->size().width() - (width * current_scale)) / 2;
|
||||
render_offset_x += unscrolled_render_offset_x;
|
||||
}
|
||||
if (!vscrollbar) {
|
||||
unscrolled_render_offset_y = (viewport()->size().height() - (height * current_scale)) / 2;
|
||||
render_offset_y += unscrolled_render_offset_y;
|
||||
}
|
||||
|
||||
p.translate(render_offset_x, render_offset_y);
|
||||
p.scale(current_scale, current_scale);
|
||||
|
||||
|
||||
// Draw blocks
|
||||
for (auto &blockIt : blocks) {
|
||||
GraphBlock &block = blockIt.second;
|
||||
|
||||
qreal blockXRender = block.x * current_scale;
|
||||
qreal blockYRender = block.y * current_scale;
|
||||
qreal blockWidthRender = block.width * current_scale;
|
||||
qreal blockHeightRender = block.height * current_scale;
|
||||
qreal blockX = block.x * current_scale;
|
||||
qreal blockY = block.y * current_scale;
|
||||
qreal blockWidth = block.width * current_scale;
|
||||
qreal blockHeight = block.height * current_scale;
|
||||
|
||||
// Check if block is visible by checking if block intersects with view area
|
||||
if (-render_offset_x < blockXRender + blockWidthRender
|
||||
&& -render_offset_x + render_width > blockXRender
|
||||
&& -render_offset_y < blockYRender + blockHeightRender
|
||||
&& -render_offset_y + render_height > blockYRender) {
|
||||
// If it intersects then draw it
|
||||
if (offset_x * current_scale < blockX + blockWidth
|
||||
&& blockX < offset_x * current_scale + render_width
|
||||
&& offset_y * current_scale < blockY + blockHeight
|
||||
&& blockY < offset_y * current_scale + render_height) {
|
||||
drawBlock(p, block);
|
||||
}
|
||||
|
||||
@ -470,21 +417,22 @@ void GraphView::paintEvent(QPaintEvent *event)
|
||||
// TODO: Only draw edges if they are actually visible ...
|
||||
// Draw edges
|
||||
for (GraphEdge &edge : block.edges) {
|
||||
QPolygonF polyline = recalculatePolygon(edge.polyline);
|
||||
QPolygonF arrow_start = recalculatePolygon(edge.arrow_start);
|
||||
QPolygonF arrow_end = recalculatePolygon(edge.arrow_end);
|
||||
EdgeConfiguration ec = edgeConfiguration(block, edge.dest);
|
||||
QPen pen(edge.color);
|
||||
// if(blockSelected)
|
||||
// pen.setStyle(Qt::DashLine);
|
||||
pen.setWidth(pen.width() / ec.width_scale);
|
||||
p.setPen(pen);
|
||||
p.setBrush(edge.color);
|
||||
p.drawPolyline(edge.polyline);
|
||||
p.drawPolyline(polyline);
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
p.setPen(pen);
|
||||
if (ec.start_arrow) {
|
||||
p.drawConvexPolygon(edge.arrow_start);
|
||||
p.drawConvexPolygon(arrow_start);
|
||||
}
|
||||
if (ec.end_arrow) {
|
||||
p.drawConvexPolygon(edge.arrow_end);
|
||||
p.drawConvexPolygon(arrow_end);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -727,46 +675,43 @@ int GraphView::findVertEdgeIndex(EdgesVector &edges, int col, int min_row, int m
|
||||
return i;
|
||||
}
|
||||
|
||||
void GraphView::showBlock(GraphBlock &block, bool animated)
|
||||
void GraphView::center()
|
||||
{
|
||||
showBlock(&block, animated);
|
||||
centerX();
|
||||
centerY();
|
||||
}
|
||||
|
||||
void GraphView::showBlock(GraphBlock *block, bool animated)
|
||||
void GraphView::centerX()
|
||||
{
|
||||
int render_width = viewport()->size().width() / current_scale;
|
||||
offset_x = -((viewport()->width() - width * current_scale) / 2);
|
||||
offset_x /= current_scale;
|
||||
}
|
||||
|
||||
void GraphView::centerY()
|
||||
{
|
||||
offset_y = -((viewport()->height() - height * current_scale) / 2);
|
||||
offset_y /= current_scale;
|
||||
}
|
||||
|
||||
// Show block middle of X
|
||||
int target_x = (block->x + (block->width / 2)) - (render_width / 2);
|
||||
int show_block_offset_y = 30;
|
||||
// But beginning of Y (so we show the top of the block)
|
||||
int target_y = block->y - show_block_offset_y;
|
||||
void GraphView::showBlock(GraphBlock &block)
|
||||
{
|
||||
showBlock(&block);
|
||||
}
|
||||
|
||||
target_x = std::max(0, target_x);
|
||||
target_y = std::max(0, target_y);
|
||||
target_x = std::min(horizontalScrollBar()->maximum(), target_x);
|
||||
target_y = std::min(verticalScrollBar()->maximum(), target_y);
|
||||
if (animated) {
|
||||
QPropertyAnimation *animation_x = new QPropertyAnimation(horizontalScrollBar(), "value", this);
|
||||
animation_x->setDuration(500);
|
||||
animation_x->setStartValue(horizontalScrollBar()->value());
|
||||
animation_x->setEndValue(target_x);
|
||||
animation_x->setEasingCurve(QEasingCurve::InOutQuad);
|
||||
animation_x->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
QPropertyAnimation *animation_y = new QPropertyAnimation(verticalScrollBar(), "value", this);
|
||||
animation_y->setDuration(500);
|
||||
animation_y->setStartValue(verticalScrollBar()->value());
|
||||
animation_y->setEndValue(target_y);
|
||||
animation_y->setEasingCurve(QEasingCurve::InOutQuad);
|
||||
animation_y->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
void GraphView::showBlock(GraphBlock *block)
|
||||
{
|
||||
if (width * current_scale <= viewport()->width()) {
|
||||
centerX();
|
||||
} else {
|
||||
horizontalScrollBar()->setValue(target_x);
|
||||
verticalScrollBar()->setValue(target_y);
|
||||
int render_width = viewport()->width() / current_scale;
|
||||
offset_x = block->x - ((render_width - block->width) / 2);
|
||||
}
|
||||
if (height * current_scale <= viewport()->height()) {
|
||||
centerY();
|
||||
} else {
|
||||
offset_y = block->y - 30;
|
||||
}
|
||||
|
||||
blockTransitionedTo(block);
|
||||
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
@ -802,18 +747,11 @@ bool GraphView::checkPointClicked(QPointF &point, int x, int y, bool above_y)
|
||||
return false;
|
||||
}
|
||||
|
||||
void GraphView::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
adjustSize(event->size().width(), event->size().height());
|
||||
}
|
||||
|
||||
// Mouse events
|
||||
void GraphView::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
int x = ((event->pos().x() - unscrolled_render_offset_x) / current_scale) +
|
||||
horizontalScrollBar()->value();
|
||||
int y = ((event->pos().y() - unscrolled_render_offset_y) / current_scale) +
|
||||
verticalScrollBar()->value();
|
||||
int x = event->pos().x() + offset_x;
|
||||
int y = event->pos().y() + offset_y;
|
||||
|
||||
// Check if a block was clicked
|
||||
for (auto &blockIt : blocks) {
|
||||
@ -839,13 +777,13 @@ void GraphView::mousePressEvent(QMouseEvent *event)
|
||||
QPointF start = edge.polyline.first();
|
||||
QPointF end = edge.polyline.last();
|
||||
if (checkPointClicked(start, x, y)) {
|
||||
showBlock(edge.dest, true);
|
||||
showBlock(edge.dest);
|
||||
// TODO: Callback to child
|
||||
return;
|
||||
break;
|
||||
}
|
||||
if (checkPointClicked(end, x, y, true)) {
|
||||
showBlock(block, true);
|
||||
showBlock(block);
|
||||
// TODO: Callback to child
|
||||
return;
|
||||
break;
|
||||
@ -868,21 +806,18 @@ void GraphView::mousePressEvent(QMouseEvent *event)
|
||||
void GraphView::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (scroll_mode) {
|
||||
int x_delta = scroll_base_x - event->x();
|
||||
int y_delta = scroll_base_y - event->y();
|
||||
offset_x += scroll_base_x - event->x();
|
||||
offset_y += scroll_base_y - event->y();
|
||||
scroll_base_x = event->x();
|
||||
scroll_base_y = event->y();
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + x_delta * (1 / current_scale));
|
||||
verticalScrollBar()->setValue(verticalScrollBar()->value() + y_delta * (1 / current_scale));
|
||||
viewport()->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphView::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
int x = ((event->pos().x() - unscrolled_render_offset_x) / current_scale) +
|
||||
horizontalScrollBar()->value();
|
||||
int y = ((event->pos().y() - unscrolled_render_offset_y) / current_scale) +
|
||||
verticalScrollBar()->value();
|
||||
int x = event->pos().x() + offset_x;
|
||||
int y = event->pos().y() + offset_y;
|
||||
|
||||
// Check if a block was clicked
|
||||
for (auto &blockIt : blocks) {
|
||||
@ -918,9 +853,8 @@ void GraphView::mouseReleaseEvent(QMouseEvent *event)
|
||||
void GraphView::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
const QPoint delta = -event->angleDelta();
|
||||
int x_delta = delta.x();
|
||||
int y_delta = delta.y();
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + x_delta * (1 / current_scale));
|
||||
verticalScrollBar()->setValue(verticalScrollBar()->value() + y_delta * (1 / current_scale));
|
||||
offset_x += delta.x() * current_scale;
|
||||
offset_y += delta.y() * current_scale;
|
||||
viewport()->update();
|
||||
event->accept();
|
||||
}
|
||||
|
@ -95,15 +95,14 @@ public:
|
||||
~GraphView() override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
// Show a block centered. Animates to it if animated=true
|
||||
void showBlock(GraphBlock &block, bool animated = false);
|
||||
void showBlock(GraphBlock *block, bool animated = false);
|
||||
void showBlock(GraphBlock &block);
|
||||
void showBlock(GraphBlock *block);
|
||||
|
||||
// Zoom data
|
||||
qreal current_scale = 1.0;
|
||||
|
||||
int unscrolled_render_offset_x = 0;
|
||||
int unscrolled_render_offset_y = 0;
|
||||
int offset_x = 0;
|
||||
int offset_y = 0;
|
||||
|
||||
protected:
|
||||
std::unordered_map<ut64, GraphBlock> blocks;
|
||||
@ -130,17 +129,17 @@ protected:
|
||||
virtual void wheelEvent(QWheelEvent *event) override;
|
||||
virtual EdgeConfiguration edgeConfiguration(GraphView::GraphBlock &from, GraphView::GraphBlock *to);
|
||||
|
||||
void adjustSize(int new_width, int new_height, QPoint mouse = QPoint(0, 0));
|
||||
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
// Mouse events
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
void center();
|
||||
void centerX();
|
||||
void centerY();
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
private:
|
||||
@ -177,6 +176,7 @@ private:
|
||||
int findVertEdgeIndex(EdgesVector &edges, int col, int min_row, int max_row);
|
||||
GraphEdge routeEdge(EdgesVector &horiz_edges, EdgesVector &vert_edges, Matrix<bool> &edge_valid,
|
||||
GraphBlock &start, GraphBlock &end, QColor color);
|
||||
QPolygonF recalculatePolygon(QPolygonF polygon);
|
||||
};
|
||||
|
||||
#endif // GRAPHVIEW_H
|
||||
|
@ -26,6 +26,7 @@ GraphWidget::GraphWidget(MainWindow *main, OverviewWidget *overview, QAction *ac
|
||||
toggleOverview(visibility);
|
||||
if (visibility) {
|
||||
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph);
|
||||
this->graphView->refreshView();
|
||||
}
|
||||
});
|
||||
|
||||
@ -53,18 +54,12 @@ void GraphWidget::toggleOverview(bool visibility)
|
||||
if (visibility) {
|
||||
connect(graphView, SIGNAL(refreshBlock()), this, SLOT(adjustOverview()));
|
||||
connect(graphView, SIGNAL(viewZoomed()), this, SLOT(adjustOverview()));
|
||||
connect(graphView->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjustOverview()));
|
||||
connect(graphView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjustOverview()));
|
||||
connect(overviewWidget->graphView, SIGNAL(refreshBlock()), this, SLOT(adjustOffset()));
|
||||
connect(overviewWidget->graphView, SIGNAL(mouseMoved()), this, SLOT(adjustGraph()));
|
||||
connect(overviewWidget, &QDockWidget::dockLocationChanged, this, &GraphWidget::adjustOverview);
|
||||
connect(overviewWidget, &OverviewWidget::resized, this, &GraphWidget::adjustOverview);
|
||||
} else {
|
||||
disconnect(graphView, SIGNAL(refreshBlock()), this, SLOT(adjustOverview()));
|
||||
disconnect(graphView, SIGNAL(viewZoomed()), this, SLOT(adjustOverview()));
|
||||
disconnect(graphView->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjustOverview()));
|
||||
disconnect(graphView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjustOverview()));
|
||||
disconnect(overviewWidget->graphView, SIGNAL(refreshBlock()), this, SLOT(adjustOffset()));
|
||||
disconnect(overviewWidget->graphView, SIGNAL(mouseMoved()), this, SLOT(adjustGraph()));
|
||||
disconnect(overviewWidget, &QDockWidget::dockLocationChanged, this, &GraphWidget::adjustOverview);
|
||||
disconnect(overviewWidget, &OverviewWidget::resized, this, &GraphWidget::adjustOverview);
|
||||
@ -86,41 +81,18 @@ void GraphWidget::adjustOverview()
|
||||
if (!overviewWidget) {
|
||||
return;
|
||||
}
|
||||
overviewWidget->graphView->h_offset = 0;
|
||||
overviewWidget->graphView->v_offset = 0;
|
||||
bool scrollXVisible = graphView->horizontalScrollBar()->isVisible();
|
||||
bool scrollYVisible = graphView->verticalScrollBar()->isVisible();
|
||||
if (!scrollXVisible && !scrollYVisible) {
|
||||
disableOverviewRect();
|
||||
return;
|
||||
}
|
||||
qreal x = 0;
|
||||
qreal y = 0;
|
||||
qreal w = graphView->viewport()->width();
|
||||
qreal h = graphView->viewport()->height();
|
||||
qreal curScale = overviewWidget->graphView->current_scale;
|
||||
qreal baseScale = graphView->current_scale;
|
||||
qreal w = graphView->viewport()->width() * curScale / baseScale;
|
||||
qreal h = graphView->viewport()->height() * curScale / baseScale;
|
||||
int graph_offset_x = graphView->offset_x;
|
||||
int graph_offset_y = graphView->offset_y;
|
||||
int overview_offset_x = overviewWidget->graphView->offset_x;
|
||||
int overview_offset_y = overviewWidget->graphView->offset_y;
|
||||
int rangeRectX = graph_offset_x * curScale - overview_offset_x * curScale;
|
||||
int rangeRectY = graph_offset_y * curScale - overview_offset_y * curScale;
|
||||
|
||||
w *= curScale / baseScale;
|
||||
h *= curScale / baseScale;
|
||||
if (scrollXVisible) {
|
||||
x = graphView->horizontalScrollBar()->value();
|
||||
x *= curScale;
|
||||
} else {
|
||||
x = (overviewWidget->graphView->viewport()->width() - w) / 2;
|
||||
overviewWidget->graphView->h_offset = x;
|
||||
}
|
||||
|
||||
if (scrollYVisible) {
|
||||
y = graphView->verticalScrollBar()->value();
|
||||
y *= curScale;
|
||||
} else {
|
||||
y = (overviewWidget->graphView->viewport()->height() - h) / 2;
|
||||
overviewWidget->graphView->v_offset = y;
|
||||
}
|
||||
|
||||
overviewWidget->graphView->rangeRect = QRectF(x + overviewWidget->graphView->unscrolled_render_offset_x,
|
||||
y + overviewWidget->graphView->unscrolled_render_offset_y, w, h);
|
||||
overviewWidget->graphView->rangeRect = QRectF(rangeRectX, rangeRectY, w, h);
|
||||
overviewWidget->graphView->viewport()->update();
|
||||
}
|
||||
|
||||
@ -129,23 +101,12 @@ void GraphWidget::adjustGraph()
|
||||
if (!overviewWidget) {
|
||||
return;
|
||||
}
|
||||
int x1 = overviewWidget->graphView->horizontalScrollBar()->value();
|
||||
int y1 = overviewWidget->graphView->verticalScrollBar()->value();
|
||||
qreal x2 = (overviewWidget->graphView->rangeRect.x() - (qreal)overviewWidget->graphView->unscrolled_render_offset_x) / overviewWidget->graphView->current_scale;
|
||||
qreal y2 = (overviewWidget->graphView->rangeRect.y() - (qreal)overviewWidget->graphView->unscrolled_render_offset_y) / overviewWidget->graphView->current_scale;
|
||||
|
||||
graphView->horizontalScrollBar()->setValue(x1 + x2);
|
||||
graphView->verticalScrollBar()->setValue(y1 + y2);
|
||||
}
|
||||
|
||||
void GraphWidget::adjustOffset()
|
||||
{
|
||||
bool scrollXVisible = graphView->horizontalScrollBar()->isVisible();
|
||||
bool scrollYVisible = graphView->verticalScrollBar()->isVisible();
|
||||
if (!scrollXVisible) {
|
||||
overviewWidget->graphView->unscrolled_render_offset_x = 0;
|
||||
}
|
||||
if (!scrollYVisible) {
|
||||
overviewWidget->graphView->unscrolled_render_offset_y = 0;
|
||||
}
|
||||
qreal curScale = overviewWidget->graphView->current_scale;
|
||||
int rectx = overviewWidget->graphView->rangeRect.x();
|
||||
int recty = overviewWidget->graphView->rangeRect.y();
|
||||
int overview_offset_x = overviewWidget->graphView->offset_x;
|
||||
int overview_offset_y = overviewWidget->graphView->offset_y;
|
||||
graphView->offset_x = rectx /curScale + overview_offset_x;
|
||||
graphView->offset_y = recty /curScale + overview_offset_y;
|
||||
graphView->viewport()->update();
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ private:
|
||||
private slots:
|
||||
void adjustOverview();
|
||||
void adjustGraph();
|
||||
void adjustOffset();
|
||||
};
|
||||
|
||||
#endif // GRAPHWIDGET_H
|
||||
|
@ -28,16 +28,12 @@ OverviewView::~OverviewView()
|
||||
|
||||
void OverviewView::adjustScale()
|
||||
{
|
||||
if (horizontalScrollBar()->maximum() > 0) {
|
||||
current_scale = (qreal)viewport()->width() / (qreal)(horizontalScrollBar()->maximum() + horizontalScrollBar()->pageStep());
|
||||
current_scale = (qreal)viewport()->width() / width;
|
||||
qreal h_scale = (qreal)viewport()->height() / height;
|
||||
if (current_scale > h_scale) {
|
||||
current_scale = h_scale;
|
||||
}
|
||||
if (verticalScrollBar()->maximum() > 0) {
|
||||
qreal h_scale = (qreal)viewport()->height() / (qreal)(verticalScrollBar()->maximum() + verticalScrollBar()->pageStep());
|
||||
if (current_scale > h_scale) {
|
||||
current_scale = h_scale;
|
||||
}
|
||||
}
|
||||
adjustSize(viewport()->size().width(), viewport()->size().height());
|
||||
center();
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
@ -45,21 +41,23 @@ void OverviewView::refreshView()
|
||||
{
|
||||
current_scale = 1.0;
|
||||
viewport()->update();
|
||||
adjustSize(viewport()->size().width(), viewport()->size().height());
|
||||
adjustScale();
|
||||
}
|
||||
|
||||
void OverviewView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||
{
|
||||
int blockX = block.x - offset_x;
|
||||
int blockY = block.y - offset_y;
|
||||
|
||||
p.setPen(Qt::black);
|
||||
p.setBrush(Qt::gray);
|
||||
p.drawRect(block.x, block.y, block.width, block.height);
|
||||
p.drawRect(blockX, blockY, block.width, block.height);
|
||||
p.setBrush(QColor(0, 0, 0, 100));
|
||||
p.drawRect(block.x + 2, block.y + 2,
|
||||
p.drawRect(blockX + 2, blockY + 2,
|
||||
block.width, block.height);
|
||||
p.setPen(QPen(graphNodeColor, 1));
|
||||
p.setBrush(disassemblyBackgroundColor);
|
||||
p.drawRect(block.x, block.y,
|
||||
p.drawRect(blockX, blockY,
|
||||
block.width, block.height);
|
||||
}
|
||||
|
||||
@ -91,8 +89,8 @@ void OverviewView::mousePressEvent(QMouseEvent *event)
|
||||
}
|
||||
qreal w = rangeRect.width();
|
||||
qreal h = rangeRect.height();
|
||||
qreal x = event->localPos().x() - w/2 + h_offset;
|
||||
qreal y = event->localPos().y() - h/2 + v_offset;
|
||||
qreal x = event->localPos().x() - w / 2;
|
||||
qreal y = event->localPos().y() - h / 2;
|
||||
rangeRect = QRectF(x, y, w, h);
|
||||
viewport()->update();
|
||||
emit mouseMoved();
|
||||
@ -112,33 +110,16 @@ void OverviewView::mouseMoveEvent(QMouseEvent *event)
|
||||
}
|
||||
qreal x = event->localPos().x() - initialDiff.x();
|
||||
qreal y = event->localPos().y() - initialDiff.y();
|
||||
qreal w = rangeRect.width();
|
||||
qreal h = rangeRect.height();
|
||||
qreal real_width = width * current_scale;
|
||||
qreal real_height = height * current_scale;
|
||||
qreal max_right = unscrolled_render_offset_x + real_width;
|
||||
qreal max_bottom = unscrolled_render_offset_y + real_height;
|
||||
qreal rect_right = x + w;
|
||||
qreal rect_bottom = y + h;
|
||||
if (rect_right >= max_right) {
|
||||
x = unscrolled_render_offset_x + real_width - w;
|
||||
}
|
||||
if (rect_bottom >= max_bottom) {
|
||||
y = unscrolled_render_offset_y + real_height - h;
|
||||
}
|
||||
if (x <= unscrolled_render_offset_x) {
|
||||
x = unscrolled_render_offset_x;
|
||||
}
|
||||
if (y <= unscrolled_render_offset_y) {
|
||||
y = unscrolled_render_offset_y;
|
||||
}
|
||||
x += h_offset;
|
||||
y += v_offset;
|
||||
rangeRect = QRectF(x, y, w, h);
|
||||
rangeRect = QRectF(x, y, rangeRect.width(), rangeRect.height());
|
||||
viewport()->update();
|
||||
emit mouseMoved();
|
||||
}
|
||||
|
||||
void OverviewView::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
GraphView::EdgeConfiguration OverviewView::edgeConfiguration(GraphView::GraphBlock &from,
|
||||
GraphView::GraphBlock *to)
|
||||
{
|
||||
|
@ -26,13 +26,6 @@ public:
|
||||
*/
|
||||
QRectF rangeRect;
|
||||
|
||||
/*
|
||||
* \brief offset for the rect which is put when either of the scrollbar of
|
||||
* Graph is not visible.
|
||||
*/
|
||||
qreal h_offset = 0;
|
||||
qreal v_offset = 0;
|
||||
|
||||
/*
|
||||
* \brief Graph access this function to set minimum set of the data
|
||||
* @param baseWidth width of Graph when it computed the blocks
|
||||
@ -67,6 +60,10 @@ protected:
|
||||
* \brief mouseMoveEvent to move the rect.
|
||||
*/
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
/*
|
||||
* \brief override this to prevent scrolling
|
||||
*/
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
|
||||
private:
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user