diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index bd9406db..5f9c8eed 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -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(); diff --git a/src/MainWindow.h b/src/MainWindow.h index 67150309..7e102f8d 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -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 diff --git a/src/widgets/DisassemblerGraphView.cpp b/src/widgets/DisassemblerGraphView.cpp index 6455fcac..4d110f45 100644 --- a/src/widgets/DisassemblerGraphView.cpp +++ b/src/widgets/DisassemblerGraphView.cpp @@ -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(); } diff --git a/src/widgets/DisassemblerGraphView.h b/src/widgets/DisassemblerGraphView.h index 55456317..dd566e2f 100644 --- a/src/widgets/DisassemblerGraphView.h +++ b/src/widgets/DisassemblerGraphView.h @@ -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 diff --git a/src/widgets/GraphWidget.cpp b/src/widgets/GraphWidget.cpp index e92b940a..4ea9cb85 100644 --- a/src/widgets/GraphWidget.cpp +++ b/src/widgets/GraphWidget.cpp @@ -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(); -} diff --git a/src/widgets/GraphWidget.h b/src/widgets/GraphWidget.h index f13f14c2..105fadfb 100644 --- a/src/widgets/GraphWidget.h +++ b/src/widgets/GraphWidget.h @@ -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 diff --git a/src/widgets/OverviewView.cpp b/src/widgets/OverviewView.cpp index d8aa90ba..024bf8e9 100644 --- a/src/widgets/OverviewView.cpp +++ b/src/widgets/OverviewView.cpp @@ -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; diff --git a/src/widgets/OverviewView.h b/src/widgets/OverviewView.h index 87811351..b06781a5 100644 --- a/src/widgets/OverviewView.h +++ b/src/widgets/OverviewView.h @@ -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. */