Skip to content

Commit

Permalink
Refactor Refresh and Display of Overview (#1453)
Browse files Browse the repository at this point in the history
  • Loading branch information
thestr4ng3r authored Apr 14, 2019
1 parent 34387c7 commit 7eb62a9
Show file tree
Hide file tree
Showing 12 changed files with 273 additions and 225 deletions.
143 changes: 13 additions & 130 deletions src/core/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,18 +240,23 @@ void MainWindow::initDocks()
hexdumpDock = new HexdumpWidget(this, ui->actionHexdump);
pseudocodeDock = new PseudocodeWidget(this, ui->actionPseudocode);
consoleDock = new ConsoleWidget(this, ui->actionConsole);

overviewDock = new OverviewWidget(this, ui->actionOverview);
overviewDock->hide();
graphDock = new GraphWidget(this, ui->actionGraph);
connect(overviewDock, &OverviewWidget::isAvailableChanged, this, [this](bool isAvailable) {
ui->actionOverview->setEnabled(isAvailable);
});
ui->actionOverview->setEnabled(overviewDock->getIsAvailable());
connect(ui->actionOverview, &QAction::toggled, [this](bool checked) {
if (checked) {
overviewDock->setUserClosed(false);
forceUpdateOverview();
if (targetGraphDock) {
toggleOverview(true, targetGraphDock);
}
overviewDock->show();
} else {
overviewDock->hide();
}
});

ui->actionOverview->setChecked(overviewDock->getUserOpened());
graphDock = new GraphWidget(this, ui->actionGraph);
sectionsDock = new SectionsWidget(this, ui->actionSections);
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
Expand Down Expand Up @@ -297,126 +302,11 @@ void MainWindow::toggleOverview(bool visibility, GraphWidget *targetGraph)
if (!overviewDock) {
return;
}
ui->actionOverview->setEnabled(visibility);
if (overviewDock->getUserClosed() || !visibility) {
return;
}
targetGraphDock = targetGraph;
connect(targetGraphDock->getGraphView(), SIGNAL(refreshBlock()), this, SLOT(updateOverview()));
connect(targetGraphDock->getGraphView(), SIGNAL(viewRefreshed()), this, SLOT(forceUpdateOverview()));
connect(targetGraphDock->getGraphView(), SIGNAL(viewZoomed()), this, SLOT(updateOverview()));
connect(targetGraphDock, &GraphWidget::graphClose, [this]() {
disconnectOverview();
enableOverviewMenu(false);
overviewDock->hide();
});
connect(overviewDock->getGraphView(), SIGNAL(mouseMoved()), this, SLOT(adjustGraph()));
connect(overviewDock->getGraphView(), SIGNAL(refreshBlock()), this, SLOT(updateOverviewAddr()));
connect(overviewDock, &QDockWidget::dockLocationChanged, this, &MainWindow::forceUpdateOverview);
connect(overviewDock, &OverviewWidget::graphClose, [this]() {
ui->actionOverview->setChecked(false);
if (!core->isGraphEmpty()) {
overviewDock->setUserClosed(true);
}
});
connect(overviewDock, SIGNAL(resized()), this, SLOT(forceUpdateOverview())); // TODO: remove this, overviewDock handles resize itself!
}

void MainWindow::disconnectOverview()
{
if (targetGraphDock) {
disconnect(targetGraphDock->getGraphView(), SIGNAL(refreshBlock()), this, SLOT(updateOverview()));
disconnect(targetGraphDock->getGraphView(), SIGNAL(viewRefreshed()), this, SLOT(updateOverview()));
disconnect(targetGraphDock->getGraphView(), SIGNAL(viewZoomed()), this, SLOT(updateOverview()));
}
if (overviewDock) {
disconnect(overviewDock->getGraphView(), SIGNAL(mouseMoved()), this, SLOT(adjustGraph()));
disconnect(overviewDock->getGraphView(), SIGNAL(refreshBlock()), this, SLOT(updateOverviewAddr()));
disconnect(overviewDock, &QDockWidget::dockLocationChanged, this, &MainWindow::forceUpdateOverview);
disconnect(overviewDock, SIGNAL(resized()), this, SLOT(forceUpdateOverview())); // TODO: remove this, overviewDock handles resize itself!
if (visibility) {
overviewDock->setTargetGraphWidget(targetGraph);
}
}

void MainWindow::setOverviewData()
{
auto &mainGraphView = *targetGraphDock->getGraphView();
overviewDock->getGraphView()->setData(mainGraphView.getWidth(), mainGraphView.getHeight(),
mainGraphView.getBlocks(), mainGraphView.getEdgeConfigurations());
}

bool MainWindow::isOverviewActive()
{
if (!overviewDock || overviewDock->getUserClosed()) {
return false;
}
if (core->isGraphEmpty()) {
enableOverviewMenu(false);
overviewDock->hide();
return false;
}
return true;
}

void MainWindow::updateOverviewAddr()
{
overviewDock->getGraphView()->currentFcnAddr = targetGraphDock->getGraphView()->currentFcnAddr;
}

void MainWindow::forceUpdateOverview()
{
if (!isOverviewActive()) {
return;
}
setOverviewData();
drawOverview();
}

void MainWindow::updateOverview()
{
if (!isOverviewActive()) {
return;
}
if (overviewDock->getGraphView()->currentFcnAddr != targetGraphDock->getGraphView()->currentFcnAddr) {
setOverviewData();
}
drawOverview();
}

void MainWindow::drawOverview()
{
qreal curScale = overviewDock->getGraphView()->current_scale;
qreal baseScale = targetGraphDock->getGraphView()->current_scale;
qreal w = targetGraphDock->getGraphView()->viewport()->width() * curScale / baseScale;
qreal h = targetGraphDock->getGraphView()->viewport()->height() * curScale / baseScale;
int graph_offset_x = targetGraphDock->getGraphView()->offset.x();
int graph_offset_y = targetGraphDock->getGraphView()->offset.y();
int overview_offset_x = overviewDock->getGraphView()->offset.x();
int overview_offset_y = overviewDock->getGraphView()->offset.y();
int rangeRectX = graph_offset_x * curScale - overview_offset_x * curScale;
int rangeRectY = graph_offset_y * curScale - overview_offset_y * curScale;

overviewDock->getGraphView()->rangeRect = QRectF(rangeRectX, rangeRectY, w, h);
overviewDock->getGraphView()->viewport()->update();
enableOverviewMenu(true);
overviewDock->show();
}

void MainWindow::adjustGraph()
{
if (!overviewDock) {
return;
}

qreal curScale = overviewDock->getGraphView()->current_scale;
int rectx = overviewDock->getGraphView()->rangeRect.x();
int recty = overviewDock->getGraphView()->rangeRect.y();
int overview_offset_x = overviewDock->getGraphView()->offset.x();
int overview_offset_y = overviewDock->getGraphView()->offset.y();
targetGraphDock->getGraphView()->offset.rx() = rectx /curScale + overview_offset_x;
targetGraphDock->getGraphView()->offset.ry() = recty /curScale + overview_offset_y;
targetGraphDock->getGraphView()->viewport()->update();
}

void MainWindow::updateTasksIndicator()
{
bool running = core->getAsyncTaskManager()->getTasksRunning();
Expand Down Expand Up @@ -931,12 +821,6 @@ void MainWindow::enableDebugWidgetsMenu(bool enable)
ui->menuAddDebugWidgets->setEnabled(enable);
}

void MainWindow::enableOverviewMenu(bool enable)
{
ui->actionOverview->setEnabled(enable);
ui->actionOverview->setChecked(enable);
}

void MainWindow::resetToDefaultLayout()
{
hideAllDocks();
Expand Down Expand Up @@ -1005,7 +889,6 @@ void MainWindow::on_actionFunctionsRename_triggered()

void MainWindow::on_actionDefault_triggered()
{
disconnectOverview();
if (core->currentlyDebugging) {
resetToDebugLayout();
} else {
Expand Down
9 changes: 0 additions & 9 deletions src/core/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,6 @@ private slots:
void changeDebugView();
void changeDefinedView();

void disconnectOverview();
void updateOverview();
void forceUpdateOverview();
void updateOverviewAddr();
void drawOverview();
void adjustGraph();

private:
CutterCore *core;

Expand All @@ -216,7 +209,6 @@ private slots:
HexdumpWidget *hexdumpDock = nullptr;
PseudocodeWidget *pseudocodeDock = nullptr;
GraphWidget *graphDock = nullptr;
GraphWidget *targetGraphDock = nullptr;
OverviewWidget *overviewDock = nullptr;
EntrypointWidget *entrypointDock = nullptr;
FunctionsWidget *functionsDock = nullptr;
Expand Down Expand Up @@ -265,7 +257,6 @@ private slots:
void showZenDocks();
void showDebugDocks();
void enableDebugWidgetsMenu(bool enable);
void enableOverviewMenu(bool enable);

void toggleDockWidget(QDockWidget *dock_widget, bool show);

Expand Down
33 changes: 20 additions & 13 deletions src/widgets/DisassemblerGraphView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ void DisassemblerGraphView::loadCurrentGraph()
highlight_token = nullptr;
}

bool emptyGraph = functions.isEmpty();
emptyGraph = functions.isEmpty();
if (emptyGraph) {
// If there's no function to print, just add a message
if (!emptyText) {
Expand Down Expand Up @@ -375,8 +375,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 - getViewOffset().x();
int blockY = block.y - getViewOffset().y();

p.setPen(Qt::black);
p.setBrush(Qt::gray);
Expand Down Expand Up @@ -517,7 +517,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
qreal lineHeightRender = charHeight;
for (auto &line : db.header_text.lines) {
qreal lineYRender = y;
lineYRender *= current_scale;
lineYRender *= getViewScale();
// Check if line does NOT intersects with view area
if (0 > lineYRender + lineHeightRender
|| render_height < lineYRender) {
Expand All @@ -543,7 +543,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
}
for (auto &line : instr.text.lines) {
qreal lineYRender = y;
lineYRender *= current_scale;
lineYRender *= getViewScale();
if (0 > lineYRender + lineHeightRender
|| render_height < lineYRender) {
y += charHeight;
Expand Down Expand Up @@ -705,24 +705,25 @@ void DisassemblerGraphView::zoom(QPointF mouseRelativePos, double velocity)
{
mouseRelativePos.rx() *= size().width();
mouseRelativePos.ry() *= size().height();
mouseRelativePos /= current_scale;
mouseRelativePos /= getViewScale();

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;
auto globalMouse = mouseRelativePos + getViewOffset();
mouseRelativePos *= getViewScale();
qreal newScale = getViewScale() * std::pow(1.25, velocity);
newScale = std::max(newScale, 0.3);
mouseRelativePos /= newScale;
setViewScale(newScale);

// Adjusting offset, so that zooming will be approaching to the cursor.
offset = globalMouse.toPoint() - mouseRelativePos.toPoint();
setViewOffset(globalMouse.toPoint() - mouseRelativePos.toPoint());

viewport()->update();
emit viewZoomed();
}

void DisassemblerGraphView::zoomReset()
{
current_scale = 1.0;
setViewScale(1.0);
viewport()->update();
emit viewZoomed();
}
Expand Down Expand Up @@ -992,6 +993,12 @@ void DisassemblerGraphView::wheelEvent(QWheelEvent *event)
emit graphMoved();
}

void DisassemblerGraphView::resizeEvent(QResizeEvent *event)
{
GraphView::resizeEvent(event);
emit resized();
}

void DisassemblerGraphView::paintEvent(QPaintEvent *event)
{
// DisassemblerGraphView is always dirty
Expand Down
5 changes: 5 additions & 0 deletions src/widgets/DisassemblerGraphView.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public slots:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void resizeEvent(QResizeEvent *event) override;

void paintEvent(QPaintEvent *event) override;

Expand Down Expand Up @@ -196,6 +197,10 @@ private slots:
void viewRefreshed();
void viewZoomed();
void graphMoved();
void resized();

public:
bool isGraphEmpty() { return emptyGraph; }
};

#endif // DISASSEMBLERGRAPHVIEW_H
Loading

0 comments on commit 7eb62a9

Please sign in to comment.