Fix a bug which causes segfault when adding another Graph (#1202)

This commit is contained in:
Vanellope 2019-02-20 00:56:50 +09:00 committed by Itay Cohen
parent a8fbe72bf7
commit 4a9b6182f5
8 changed files with 111 additions and 119 deletions

View File

@ -62,6 +62,7 @@
#include "widgets/GraphView.h"
#include "widgets/GraphWidget.h"
#include "widgets/OverviewWidget.h"
#include "widgets/OverviewView.h"
#include "widgets/FunctionsWidget.h"
#include "widgets/SectionsWidget.h"
#include "widgets/SegmentsWidget.h"
@ -192,17 +193,8 @@ void MainWindow::initUI()
// Add graph view as dockable
overviewDock = new OverviewWidget(this, ui->actionOverview);
graphDock = new GraphWidget(this, overviewDock, ui->actionGraph);
connect(graphDock, &QDockWidget::visibilityChanged, this, [ = ](bool visible) {
ui->actionOverview->setChecked(visible);
if (visible) {
overviewDock->show();
} else {
overviewDock->hide();
}
});
overviewDock->hide();
graphDock = new GraphWidget(this, ui->actionGraph);
sectionsDock = new SectionsWidget(this, ui->actionSections);
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
@ -290,6 +282,72 @@ void MainWindow::initUI()
}
}
void MainWindow::toggleOverview(bool visibility, GraphWidget *targetGraph)
{
if (!overviewDock) {
return;
}
targetGraphDock = targetGraph;
ui->actionOverview->setChecked(visibility);
if (visibility) {
connect(targetGraphDock->graphView, SIGNAL(refreshBlock()), this, SLOT(adjustOverview()));
connect(targetGraphDock->graphView, SIGNAL(viewZoomed()), this, SLOT(adjustOverview()));
connect(overviewDock->graphView, SIGNAL(mouseMoved()), this, SLOT(adjustGraph()));
connect(overviewDock, &QDockWidget::dockLocationChanged, this, &MainWindow::adjustOverview);
connect(overviewDock, SIGNAL(resized()), this, SLOT(adjustOverview()));
overviewDock->show();
} else {
disconnect(targetGraphDock->graphView, SIGNAL(refreshBlock()), this, SLOT(adjustOverview()));
disconnect(targetGraphDock->graphView, SIGNAL(viewZoomed()), this, SLOT(adjustOverview()));
disconnect(overviewDock->graphView, SIGNAL(mouseMoved()), this, SLOT(adjustGraph()));
disconnect(overviewDock, &QDockWidget::dockLocationChanged, this, &MainWindow::adjustOverview);
disconnect(overviewDock, SIGNAL(resized()), this, SLOT(adjustOverview()));
overviewDock->hide();
}
}
void MainWindow::setOverviewData()
{
overviewDock->graphView->setData(targetGraphDock->graphView->getWidth(),
targetGraphDock->graphView->getHeight(), targetGraphDock->graphView->getBlocks());
}
void MainWindow::adjustOverview()
{
if (!overviewDock) {
return;
}
setOverviewData();
qreal curScale = overviewDock->graphView->current_scale;
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 rangeRectX = graph_offset_x * curScale - overview_offset_x * curScale;
int rangeRectY = graph_offset_y * curScale - overview_offset_y * curScale;
overviewDock->graphView->rangeRect = QRectF(rangeRectX, rangeRectY, w, h);
overviewDock->graphView->viewport()->update();
}
void MainWindow::adjustGraph()
{
if (!overviewDock) {
return;
}
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;
targetGraphDock->graphView->viewport()->update();
}
void MainWindow::updateTasksIndicator()
{
bool running = core->getAsyncTaskManager()->getTasksRunning();

View File

@ -105,7 +105,10 @@ public:
void updateDockActionChecked(QAction * action);
OverviewWidget *overviewDock = nullptr;
QString getFilename() const
{
return filename;
}
public slots:
void finalizeOpen();
@ -129,6 +132,10 @@ public slots:
void openNewFileFailed();
void toggleOverview(bool visibility, GraphWidget *targetGraph);
void adjustOverview();
void adjustGraph();
private slots:
void on_actionAbout_triggered();
void on_actionIssue_triggered();
@ -204,6 +211,8 @@ private:
HexdumpWidget *hexdumpDock = nullptr;
PseudocodeWidget *pseudocodeDock = nullptr;
GraphWidget *graphDock = nullptr;
GraphWidget *targetGraphDock = nullptr;
OverviewWidget *overviewDock = nullptr;
EntrypointWidget *entrypointDock = nullptr;
FunctionsWidget *functionsDock = nullptr;
ImportsWidget *importsDock = nullptr;
@ -255,12 +264,7 @@ private:
void toggleDockWidget(QDockWidget *dock_widget, bool show);
void updateDockActionsChecked();
public:
QString getFilename() const
{
return filename;
}
void setOverviewData();
};
#endif // MAINWINDOW_H

View File

@ -31,6 +31,7 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
seekable(new CutterSeekable(this))
{
highlight_token = nullptr;
auto *layout = new QVBoxLayout(this);
// Signals that require a refresh all
connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshView()));
connect(Core(), SIGNAL(commentsChanged()), this, SLOT(refreshView()));
@ -124,9 +125,11 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
header->setLineWrapMode(QTextEdit::NoWrap);
// Add header as widget to layout so it stretches to the layout width
layout()->setContentsMargins(0, 0, 0, 0);
layout()->setAlignment(Qt::AlignTop);
layout()->addWidget(header);
layout->setContentsMargins(0, 0, 0, 0);
layout->setAlignment(Qt::AlignTop);
layout->addWidget(header);
prepareHeader();
highlighter = new SyntaxHighlighter(header->document());
}
@ -194,12 +197,11 @@ void DisassemblerGraphView::loadCurrentGraph()
if (emptyGraph) {
// If there's no function to print, just add a message
if (!emptyText) {
auto *layout = new QVBoxLayout(this);
emptyText = new QLabel(this);
emptyText->setText(tr("No function detected. Cannot display graph."));
emptyText->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
layout->addWidget(emptyText);
layout->setAlignment(emptyText, Qt::AlignHCenter);
layout()->addWidget(emptyText);
layout()->setAlignment(emptyText, Qt::AlignHCenter);
}
emptyText->setVisible(true);
} else if (emptyText) {
@ -962,6 +964,18 @@ void DisassemblerGraphView::on_actionExportGraph_triggered()
fileOut << Core()->cmd("agfd $FB");
}
void DisassemblerGraphView::mousePressEvent(QMouseEvent *event)
{
GraphView::mousePressEvent(event);
emit graphMoved();
}
void DisassemblerGraphView::mouseMoveEvent(QMouseEvent *event)
{
GraphView::mouseMoveEvent(event);
emit graphMoved();
}
void DisassemblerGraphView::wheelEvent(QWheelEvent *event)
{
// when CTRL is pressed, we zoom in/out with mouse wheel
@ -981,4 +995,5 @@ void DisassemblerGraphView::wheelEvent(QWheelEvent *event)
// use mouse wheel for scrolling when CTRL is not pressed
GraphView::wheelEvent(event);
}
emit graphMoved();
}

View File

@ -152,7 +152,9 @@ public slots:
void copySelection();
protected:
virtual void wheelEvent(QWheelEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
private slots:
void on_actionExportGraph_triggered();
@ -219,6 +221,7 @@ private:
signals:
void viewRefreshed();
void viewZoomed();
void graphMoved();
};
#endif // DISASSEMBLERGRAPHVIEW_H

View File

@ -2,16 +2,14 @@
#include "GraphWidget.h"
#include "DisassemblerGraphView.h"
#include "WidgetShortcuts.h"
#include "OverviewView.h"
GraphWidget::GraphWidget(MainWindow *main, OverviewWidget *overview, QAction *action) :
GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
CutterDockWidget(main, action)
{
this->setObjectName("Graph");
this->setAllowedAreas(Qt::AllDockWidgetAreas);
this->graphView = new DisassemblerGraphView(this);
this->setWidget(graphView);
this->overviewWidget = overview;
// getting the name of the class is implementation defined, and cannot be
// used reliably across different compilers.
@ -23,15 +21,15 @@ GraphWidget::GraphWidget(MainWindow *main, OverviewWidget *overview, QAction *ac
});
connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) {
toggleOverview(visibility);
main->toggleOverview(visibility, this);
if (visibility) {
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph);
this->graphView->refreshView();
}
});
connect(graphView, &DisassemblerGraphView::viewRefreshed, this, [ = ]() {
overviewWidget->graphView->setData(graphView->getWidth(), graphView->getHeight(), graphView->getBlocks());
connect(graphView, &DisassemblerGraphView::graphMoved, this, [ = ]() {
main->toggleOverview(true, this);
});
connect(Core(), &CutterCore::raisePrioritizedMemoryWidget,
@ -45,68 +43,3 @@ GraphWidget::GraphWidget(MainWindow *main, OverviewWidget *overview, QAction *ac
}
GraphWidget::~GraphWidget() {}
void GraphWidget::toggleOverview(bool visibility)
{
if (!overviewWidget) {
return;
}
if (visibility) {
connect(graphView, SIGNAL(refreshBlock()), this, SLOT(adjustOverview()));
connect(graphView, SIGNAL(viewZoomed()), this, SLOT(adjustOverview()));
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(overviewWidget->graphView, SIGNAL(mouseMoved()), this, SLOT(adjustGraph()));
disconnect(overviewWidget, &QDockWidget::dockLocationChanged, this, &GraphWidget::adjustOverview);
disconnect(overviewWidget, &OverviewWidget::resized, this, &GraphWidget::adjustOverview);
disableOverviewRect();
}
}
void GraphWidget::disableOverviewRect()
{
if (!overviewWidget) {
return;
}
overviewWidget->graphView->rangeRect = QRectF(0, 0, 0, 0);
overviewWidget->graphView->viewport()->update();
}
void GraphWidget::adjustOverview()
{
if (!overviewWidget) {
return;
}
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;
overviewWidget->graphView->rangeRect = QRectF(rangeRectX, rangeRectY, w, h);
overviewWidget->graphView->viewport()->update();
}
void GraphWidget::adjustGraph()
{
if (!overviewWidget) {
return;
}
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

@ -5,24 +5,15 @@
class MainWindow;
class DisassemblerGraphView;
class OverviewWidget;
class GraphWidget : public CutterDockWidget
{
Q_OBJECT
public:
explicit GraphWidget(MainWindow *main, OverviewWidget *overview, QAction *action = nullptr);
explicit GraphWidget(MainWindow *main, QAction *action = nullptr);
~GraphWidget();
private:
DisassemblerGraphView *graphView;
OverviewWidget *overviewWidget;
void toggleOverview(bool visibility);
void disableOverviewRect();
private slots:
void adjustOverview();
void adjustGraph();
};
#endif // GRAPHWIDGET_H

View File

@ -26,7 +26,7 @@ OverviewView::~OverviewView()
{
}
void OverviewView::adjustScale()
void OverviewView::refreshView()
{
current_scale = (qreal)viewport()->width() / width;
qreal h_scale = (qreal)viewport()->height() / height;
@ -37,13 +37,6 @@ void OverviewView::adjustScale()
viewport()->update();
}
void OverviewView::refreshView()
{
current_scale = 1.0;
viewport()->update();
adjustScale();
}
void OverviewView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
{
int blockX = block.x - offset_x;

View File

@ -97,11 +97,6 @@ private:
*/
void paintEvent(QPaintEvent *event) override;
/*
* \brief apply scale properly on the view
*/
void adjustScale();
/*
* \brief if the mouse is in the rect in Overview.
*/