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/GraphView.h"
#include "widgets/GraphWidget.h" #include "widgets/GraphWidget.h"
#include "widgets/OverviewWidget.h" #include "widgets/OverviewWidget.h"
#include "widgets/OverviewView.h"
#include "widgets/FunctionsWidget.h" #include "widgets/FunctionsWidget.h"
#include "widgets/SectionsWidget.h" #include "widgets/SectionsWidget.h"
#include "widgets/SegmentsWidget.h" #include "widgets/SegmentsWidget.h"
@ -192,17 +193,8 @@ void MainWindow::initUI()
// Add graph view as dockable // Add graph view as dockable
overviewDock = new OverviewWidget(this, ui->actionOverview); 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); sectionsDock = new SectionsWidget(this, ui->actionSections);
segmentsDock = new SegmentsWidget(this, ui->actionSegments); segmentsDock = new SegmentsWidget(this, ui->actionSegments);
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints); 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() void MainWindow::updateTasksIndicator()
{ {
bool running = core->getAsyncTaskManager()->getTasksRunning(); bool running = core->getAsyncTaskManager()->getTasksRunning();

View File

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

View File

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

View File

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

View File

@ -2,16 +2,14 @@
#include "GraphWidget.h" #include "GraphWidget.h"
#include "DisassemblerGraphView.h" #include "DisassemblerGraphView.h"
#include "WidgetShortcuts.h" #include "WidgetShortcuts.h"
#include "OverviewView.h"
GraphWidget::GraphWidget(MainWindow *main, OverviewWidget *overview, QAction *action) : GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
CutterDockWidget(main, action) CutterDockWidget(main, action)
{ {
this->setObjectName("Graph"); this->setObjectName("Graph");
this->setAllowedAreas(Qt::AllDockWidgetAreas); this->setAllowedAreas(Qt::AllDockWidgetAreas);
this->graphView = new DisassemblerGraphView(this); this->graphView = new DisassemblerGraphView(this);
this->setWidget(graphView); this->setWidget(graphView);
this->overviewWidget = overview;
// getting the name of the class is implementation defined, and cannot be // getting the name of the class is implementation defined, and cannot be
// used reliably across different compilers. // used reliably across different compilers.
@ -23,15 +21,15 @@ GraphWidget::GraphWidget(MainWindow *main, OverviewWidget *overview, QAction *ac
}); });
connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) { connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) {
toggleOverview(visibility); main->toggleOverview(visibility, this);
if (visibility) { if (visibility) {
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph); Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph);
this->graphView->refreshView(); this->graphView->refreshView();
} }
}); });
connect(graphView, &DisassemblerGraphView::viewRefreshed, this, [ = ]() { connect(graphView, &DisassemblerGraphView::graphMoved, this, [ = ]() {
overviewWidget->graphView->setData(graphView->getWidth(), graphView->getHeight(), graphView->getBlocks()); main->toggleOverview(true, this);
}); });
connect(Core(), &CutterCore::raisePrioritizedMemoryWidget, connect(Core(), &CutterCore::raisePrioritizedMemoryWidget,
@ -45,68 +43,3 @@ GraphWidget::GraphWidget(MainWindow *main, OverviewWidget *overview, QAction *ac
} }
GraphWidget::~GraphWidget() {} 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 MainWindow;
class DisassemblerGraphView; class DisassemblerGraphView;
class OverviewWidget;
class GraphWidget : public CutterDockWidget class GraphWidget : public CutterDockWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit GraphWidget(MainWindow *main, OverviewWidget *overview, QAction *action = nullptr); explicit GraphWidget(MainWindow *main, QAction *action = nullptr);
~GraphWidget(); ~GraphWidget();
private:
DisassemblerGraphView *graphView; DisassemblerGraphView *graphView;
OverviewWidget *overviewWidget;
void toggleOverview(bool visibility);
void disableOverviewRect();
private slots:
void adjustOverview();
void adjustGraph();
}; };
#endif // GRAPHWIDGET_H #endif // GRAPHWIDGET_H

View File

@ -26,7 +26,7 @@ OverviewView::~OverviewView()
{ {
} }
void OverviewView::adjustScale() void OverviewView::refreshView()
{ {
current_scale = (qreal)viewport()->width() / width; current_scale = (qreal)viewport()->width() / width;
qreal h_scale = (qreal)viewport()->height() / height; qreal h_scale = (qreal)viewport()->height() / height;
@ -37,13 +37,6 @@ void OverviewView::adjustScale()
viewport()->update(); viewport()->update();
} }
void OverviewView::refreshView()
{
current_scale = 1.0;
viewport()->update();
adjustScale();
}
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;

View File

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