DisassemblerGraphView zooming fix (#1354)

* Zooming of DisassemblerGraphView now works to cursor instead of top left corner.

* formatting fix.

* Fix refactor bug.
This commit is contained in:
Anton Krasnokutskiy 2019-03-23 01:21:06 -07:00 committed by Itay Cohen
parent f59dce1727
commit e096f3ee4a
6 changed files with 60 additions and 57 deletions

View File

@ -392,10 +392,10 @@ void MainWindow::drawOverview()
qreal baseScale = targetGraphDock->graphView->current_scale; qreal baseScale = targetGraphDock->graphView->current_scale;
qreal w = targetGraphDock->graphView->viewport()->width() * curScale / baseScale; qreal w = targetGraphDock->graphView->viewport()->width() * curScale / baseScale;
qreal h = targetGraphDock->graphView->viewport()->height() * curScale / baseScale; qreal h = targetGraphDock->graphView->viewport()->height() * curScale / baseScale;
int graph_offset_x = targetGraphDock->graphView->offset_x; int graph_offset_x = targetGraphDock->graphView->offset.x();
int graph_offset_y = targetGraphDock->graphView->offset_y; int graph_offset_y = targetGraphDock->graphView->offset.y();
int overview_offset_x = overviewDock->graphView->offset_x; int overview_offset_x = overviewDock->graphView->offset.x();
int overview_offset_y = overviewDock->graphView->offset_y; int overview_offset_y = overviewDock->graphView->offset.y();
int rangeRectX = graph_offset_x * curScale - overview_offset_x * curScale; int rangeRectX = graph_offset_x * curScale - overview_offset_x * curScale;
int rangeRectY = graph_offset_y * curScale - overview_offset_y * curScale; int rangeRectY = graph_offset_y * curScale - overview_offset_y * curScale;
@ -413,10 +413,10 @@ void MainWindow::adjustGraph()
qreal curScale = overviewDock->graphView->current_scale; qreal curScale = overviewDock->graphView->current_scale;
int rectx = overviewDock->graphView->rangeRect.x(); int rectx = overviewDock->graphView->rangeRect.x();
int recty = overviewDock->graphView->rangeRect.y(); int recty = overviewDock->graphView->rangeRect.y();
int overview_offset_x = overviewDock->graphView->offset_x; int overview_offset_x = overviewDock->graphView->offset.x();
int overview_offset_y = overviewDock->graphView->offset_y; int overview_offset_y = overviewDock->graphView->offset.y();
targetGraphDock->graphView->offset_x = rectx /curScale + overview_offset_x; targetGraphDock->graphView->offset.rx() = rectx /curScale + overview_offset_x;
targetGraphDock->graphView->offset_y = recty /curScale + overview_offset_y; targetGraphDock->graphView->offset.ry() = recty /curScale + overview_offset_y;
targetGraphDock->graphView->viewport()->update(); targetGraphDock->graphView->viewport()->update();
} }

View File

@ -65,10 +65,10 @@ 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, SIGNAL(activated()), this, SLOT(zoomIn())); 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, SIGNAL(activated()), this, SLOT(zoomOut())); 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()));
@ -369,8 +369,8 @@ void DisassemblerGraphView::initFont()
void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block) void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
{ {
int blockX = block.x - offset_x; int blockX = block.x - offset.x();
int blockY = block.y - offset_y; int blockY = block.y - offset.y();
p.setPen(Qt::black); p.setPen(Qt::black);
p.setBrush(Qt::gray); p.setBrush(Qt::gray);
@ -695,19 +695,21 @@ void DisassemblerGraphView::onSeekChanged(RVA addr)
} }
} }
void DisassemblerGraphView::zoomIn(QPoint mouse) void DisassemblerGraphView::zoom(QPointF mouseRelativePos, double velocity)
{ {
Q_UNUSED(mouse); mouseRelativePos.rx() *= size().width();
current_scale += 0.1; mouseRelativePos.ry() *= size().height();
viewport()->update(); mouseRelativePos /= current_scale;
emit viewZoomed();
}
void DisassemblerGraphView::zoomOut(QPoint mouse) auto globalMouse = mouseRelativePos + offset;
{ mouseRelativePos *= current_scale;
Q_UNUSED(mouse); current_scale *= std::pow(1.25, velocity);
current_scale -= 0.1;
current_scale = std::max(current_scale, 0.3); current_scale = std::max(current_scale, 0.3);
mouseRelativePos /= current_scale;
// Adjusting offset, so that zooming will be approaching to the cursor.
offset = globalMouse.toPoint() - mouseRelativePos.toPoint();
viewport()->update(); viewport()->update();
emit viewZoomed(); emit viewZoomed();
} }
@ -968,13 +970,13 @@ void DisassemblerGraphView::wheelEvent(QWheelEvent *event)
if (Qt::ControlModifier == event->modifiers()) { if (Qt::ControlModifier == event->modifiers()) {
const QPoint numDegrees = event->angleDelta() / 8; const QPoint numDegrees = event->angleDelta() / 8;
if (!numDegrees.isNull()) { if (!numDegrees.isNull()) {
const QPoint numSteps = numDegrees / 15; int numSteps = numDegrees.y() / 15;
QPoint mouse = event->globalPos();
if (numSteps.y() > 0) { QPointF relativeMousePos = event->pos();
zoomIn(mouse); relativeMousePos.rx() /= size().width();
} else if (numSteps.y() < 0) { relativeMousePos.ry() /= size().height();
zoomOut(mouse);
} zoom(relativeMousePos, numSteps);
} }
event->accept(); event->accept();
} else { } else {

View File

@ -104,6 +104,7 @@ public:
int getWidth() { return width; } int getWidth() { return width; }
int getHeight() { return height; } int getHeight() { return height; }
std::unordered_map<ut64, GraphBlock> getBlocks() { return blocks; } std::unordered_map<ut64, GraphBlock> getBlocks() { return blocks; }
public slots: public slots:
void refreshView(); void refreshView();
void colorsUpdatedSlot(); void colorsUpdatedSlot();
@ -111,8 +112,7 @@ public slots:
void onSeekChanged(RVA addr); void onSeekChanged(RVA addr);
void toggleSync(); void toggleSync();
void zoomIn(QPoint mouse = QPoint(0, 0)); void zoom(QPointF mouseRelativePos, double velocity);
void zoomOut(QPoint mouse = QPoint(0, 0));
void zoomReset(); void zoomReset();
void takeTrue(); void takeTrue();

View File

@ -64,8 +64,8 @@ void GraphView::blockHelpEvent(GraphView::GraphBlock &block, QHelpEvent *event,
bool GraphView::helpEvent(QHelpEvent *event) bool GraphView::helpEvent(QHelpEvent *event)
{ {
int x = event->pos().x() + offset_x; int x = event->pos().x() + offset.x();
int y = event->pos().y() - offset_y; int y = event->pos().y() - offset.y();
for (auto &blockIt : blocks) { for (auto &blockIt : blocks) {
GraphBlock &block = blockIt.second; GraphBlock &block = blockIt.second;
@ -373,7 +373,7 @@ QPolygonF GraphView::recalculatePolygon(QPolygonF polygon)
{ {
QPolygonF ret; QPolygonF ret;
for (int i = 0; i < polygon.size(); i++) { for (int i = 0; i < polygon.size(); i++) {
ret << QPointF(polygon[i].x() - offset_x, polygon[i].y() - offset_y); ret << QPointF(polygon[i].x() - offset.x(), polygon[i].y() - offset.y());
} }
return ret; return ret;
} }
@ -409,10 +409,10 @@ void GraphView::paintEvent(QPaintEvent *event)
qreal blockHeight = block.height * current_scale; qreal blockHeight = block.height * current_scale;
// Check if block is visible by checking if block intersects with view area // Check if block is visible by checking if block intersects with view area
if (offset_x * current_scale < blockX + blockWidth if (offset.x() * current_scale < blockX + blockWidth
&& blockX < offset_x * current_scale + render_width && blockX < offset.x() * current_scale + render_width
&& offset_y * current_scale < blockY + blockHeight && offset.y() * current_scale < blockY + blockHeight
&& blockY < offset_y * current_scale + render_height) { && blockY < offset.y() * current_scale + render_height) {
drawBlock(p, block); drawBlock(p, block);
} }
@ -696,14 +696,14 @@ void GraphView::center()
void GraphView::centerX() void GraphView::centerX()
{ {
offset_x = -((viewport()->width() - width * current_scale) / 2); offset.rx() = -((viewport()->width() - width * current_scale) / 2);
offset_x /= current_scale; offset.rx() /= current_scale;
} }
void GraphView::centerY() void GraphView::centerY()
{ {
offset_y = -((viewport()->height() - height * current_scale) / 2); offset.ry() = -((viewport()->height() - height * current_scale) / 2);
offset_y /= current_scale; offset.ry() /= current_scale;
} }
void GraphView::showBlock(GraphBlock &block) void GraphView::showBlock(GraphBlock &block)
@ -717,12 +717,12 @@ void GraphView::showBlock(GraphBlock *block)
centerX(); centerX();
} else { } else {
int render_width = viewport()->width() / current_scale; int render_width = viewport()->width() / current_scale;
offset_x = block->x - ((render_width - block->width) / 2); offset.rx() = block->x - ((render_width - block->width) / 2);
} }
if (height * current_scale <= viewport()->height()) { if (height * current_scale <= viewport()->height()) {
centerY(); centerY();
} else { } else {
offset_y = block->y - 30; offset.ry() = block->y - 30;
} }
blockTransitionedTo(block); blockTransitionedTo(block);
viewport()->update(); viewport()->update();
@ -763,8 +763,8 @@ bool GraphView::checkPointClicked(QPointF &point, int x, int y, bool above_y)
// Mouse events // Mouse events
void GraphView::mousePressEvent(QMouseEvent *event) void GraphView::mousePressEvent(QMouseEvent *event)
{ {
int x = event->pos().x() / current_scale + offset_x; int x = event->pos().x() / current_scale + offset.x();
int y = event->pos().y() / current_scale + offset_y; int y = event->pos().y() / current_scale + offset.y();
// Check if a block was clicked // Check if a block was clicked
for (auto &blockIt : blocks) { for (auto &blockIt : blocks) {
@ -819,8 +819,8 @@ void GraphView::mousePressEvent(QMouseEvent *event)
void GraphView::mouseMoveEvent(QMouseEvent *event) void GraphView::mouseMoveEvent(QMouseEvent *event)
{ {
if (scroll_mode) { if (scroll_mode) {
offset_x += (scroll_base_x - event->x()) / current_scale; offset.rx() += (scroll_base_x - event->x()) / current_scale;
offset_y += (scroll_base_y - event->y()) / current_scale; offset.ry() += (scroll_base_y - event->y()) / current_scale;
scroll_base_x = event->x(); scroll_base_x = event->x();
scroll_base_y = event->y(); scroll_base_y = event->y();
viewport()->update(); viewport()->update();
@ -829,8 +829,8 @@ void GraphView::mouseMoveEvent(QMouseEvent *event)
void GraphView::mouseDoubleClickEvent(QMouseEvent *event) void GraphView::mouseDoubleClickEvent(QMouseEvent *event)
{ {
int x = event->pos().x() / current_scale + offset_x; int x = event->pos().x() / current_scale + offset.x();
int y = event->pos().y() / current_scale + offset_y; int y = event->pos().y() / current_scale + offset.y();
// Check if a block was clicked // Check if a block was clicked
for (auto &blockIt : blocks) { for (auto &blockIt : blocks) {
@ -865,9 +865,11 @@ void GraphView::mouseReleaseEvent(QMouseEvent *event)
void GraphView::wheelEvent(QWheelEvent *event) void GraphView::wheelEvent(QWheelEvent *event)
{ {
const QPoint delta = -event->angleDelta(); QPoint delta = -event->angleDelta();
offset_x += delta.x() / current_scale;
offset_y += delta.y() / current_scale; delta /= current_scale;
offset += delta;
viewport()->update(); viewport()->update();
event->accept(); event->accept();
} }

View File

@ -101,8 +101,7 @@ public:
// Zoom data // Zoom data
qreal current_scale = 1.0; qreal current_scale = 1.0;
int offset_x = 0; QPoint offset = QPoint(0, 0);
int offset_y = 0;
/** /**
* @brief flag to control if the cached pixmap should be used * @brief flag to control if the cached pixmap should be used

View File

@ -44,8 +44,8 @@ void OverviewView::refreshView()
void OverviewView::drawBlock(QPainter &p, GraphView::GraphBlock &block) void OverviewView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
{ {
int blockX = block.x - offset_x; int blockX = block.x - offset.x();
int blockY = block.y - offset_y; int blockY = block.y - offset.y();
p.setPen(Qt::black); p.setPen(Qt::black);
p.setBrush(Qt::gray); p.setBrush(Qt::gray);