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

View File

@ -65,10 +65,10 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
// Zoom shortcuts
QShortcut *shortcut_zoom_in = new QShortcut(QKeySequence(Qt::Key_Plus), this);
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);
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);
shortcut_zoom_reset->setContext(Qt::WidgetShortcut);
connect(shortcut_zoom_reset, SIGNAL(activated()), this, SLOT(zoomReset()));
@ -369,8 +369,8 @@ void DisassemblerGraphView::initFont()
void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
{
int blockX = block.x - offset_x;
int blockY = block.y - offset_y;
int blockX = block.x - offset.x();
int blockY = block.y - offset.y();
p.setPen(Qt::black);
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);
current_scale += 0.1;
viewport()->update();
emit viewZoomed();
}
mouseRelativePos.rx() *= size().width();
mouseRelativePos.ry() *= size().height();
mouseRelativePos /= current_scale;
void DisassemblerGraphView::zoomOut(QPoint mouse)
{
Q_UNUSED(mouse);
current_scale -= 0.1;
auto globalMouse = mouseRelativePos + offset;
mouseRelativePos *= current_scale;
current_scale *= std::pow(1.25, velocity);
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();
emit viewZoomed();
}
@ -968,13 +970,13 @@ void DisassemblerGraphView::wheelEvent(QWheelEvent *event)
if (Qt::ControlModifier == event->modifiers()) {
const QPoint numDegrees = event->angleDelta() / 8;
if (!numDegrees.isNull()) {
const QPoint numSteps = numDegrees / 15;
QPoint mouse = event->globalPos();
if (numSteps.y() > 0) {
zoomIn(mouse);
} else if (numSteps.y() < 0) {
zoomOut(mouse);
}
int numSteps = numDegrees.y() / 15;
QPointF relativeMousePos = event->pos();
relativeMousePos.rx() /= size().width();
relativeMousePos.ry() /= size().height();
zoom(relativeMousePos, numSteps);
}
event->accept();
} else {

View File

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

View File

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

View File

@ -101,8 +101,7 @@ public:
// Zoom data
qreal current_scale = 1.0;
int offset_x = 0;
int offset_y = 0;
QPoint offset = QPoint(0, 0);
/**
* @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)
{
int blockX = block.x - offset_x;
int blockY = block.y - offset_y;
int blockX = block.x - offset.x();
int blockY = block.y - offset.y();
p.setPen(Qt::black);
p.setBrush(Qt::gray);