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:
Vanellope 2019-02-17 02:17:11 +09:00 committed by Itay Cohen
parent 9a02dd24a7
commit f8cebe0e30
8 changed files with 145 additions and 285 deletions

View File

@ -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();
}

View File

@ -158,7 +158,6 @@ private slots:
void on_actionExportGraph_triggered();
private:
bool first_draw = true;
bool transition_dont_seek = false;
Token *highlight_token;

View File

@ -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();
}

View File

@ -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

View File

@ -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();
}

View File

@ -23,7 +23,6 @@ private:
private slots:
void adjustOverview();
void adjustGraph();
void adjustOffset();
};
#endif // GRAPHWIDGET_H

View File

@ -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)
{

View File

@ -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:
/*