diff --git a/src/Cutter.pro b/src/Cutter.pro
index 83f97c61..6085c098 100644
--- a/src/Cutter.pro
+++ b/src/Cutter.pro
@@ -128,6 +128,7 @@ SOURCES += \
Main.cpp \
Cutter.cpp \
widgets/DisassemblerGraphView.cpp \
+ widgets/OverviewView.cpp \
common/RichTextPainter.cpp \
dialogs/InitialOptionsDialog.cpp \
dialogs/AboutDialog.cpp \
@@ -192,6 +193,7 @@ SOURCES += \
widgets/CutterDockWidget.cpp \
widgets/CutterTreeWidget.cpp \
widgets/GraphWidget.cpp \
+ widgets/OverviewWidget.cpp \
common/JsonTreeItem.cpp \
common/JsonModel.cpp \
dialogs/VersionInfoDialog.cpp \
@@ -229,6 +231,7 @@ SOURCES += \
HEADERS += \
Cutter.h \
widgets/DisassemblerGraphView.h \
+ widgets/OverviewView.h \
common/RichTextPainter.h \
common/CachedFontMetrics.h \
dialogs/AboutDialog.h \
@@ -294,6 +297,7 @@ HEADERS += \
widgets/CutterDockWidget.h \
widgets/CutterTreeWidget.h \
widgets/GraphWidget.h \
+ widgets/OverviewWidget.h \
common/JsonTreeItem.h \
common/JsonModel.h \
dialogs/VersionInfoDialog.h \
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 1bb4c390..14006399 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -54,7 +54,9 @@
// Widgets Headers
#include "widgets/DisassemblerGraphView.h"
+#include "widgets/GraphView.h"
#include "widgets/GraphWidget.h"
+#include "widgets/OverviewWidget.h"
#include "widgets/FunctionsWidget.h"
#include "widgets/SectionsWidget.h"
#include "widgets/SegmentsWidget.h"
@@ -182,7 +184,17 @@ void MainWindow::initUI()
consoleDock = new ConsoleWidget(this, ui->actionConsole);
// Add graph view as dockable
- graphDock = new GraphWidget(this, ui->actionGraph);
+ 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();
+ }
+ });
sectionsDock = new SectionsWidget(this, ui->actionSections);
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
@@ -558,9 +570,11 @@ void MainWindow::restoreDocks()
{
// In the upper half the functions are the first widget
addDockWidget(Qt::TopDockWidgetArea, functionsDock);
+ addDockWidget(Qt::TopDockWidgetArea, overviewDock);
// Function | Dashboard
- splitDockWidget(functionsDock, dashboardDock, Qt::Horizontal);
+ splitDockWidget(overviewDock, dashboardDock, Qt::Horizontal);
+ splitDockWidget(functionsDock, overviewDock, Qt::Vertical);
// In the lower half the console is the first widget
addDockWidget(Qt::BottomDockWidgetArea, consoleDock);
@@ -688,8 +702,10 @@ void MainWindow::resetToDefaultLayout()
// Ugly workaround to set the default widths of functions docks
// if anyone finds a way to do this cleaner that also works, feel free to change it!
auto restoreFunctionDock = qhelpers::forceWidth(functionsDock->widget(), 200);
+ auto restoreOverviewDock = qhelpers::forceWidth(overviewDock->widget(), 200);
qApp->processEvents();
restoreFunctionDock.restoreWidth(functionsDock->widget());
+ restoreOverviewDock.restoreWidth(overviewDock->widget());
core->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Disassembly);
}
diff --git a/src/MainWindow.h b/src/MainWindow.h
index d288facf..061455c7 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -5,6 +5,8 @@
#include "Cutter.h" // only needed for ut64
#include "widgets/DisassemblyWidget.h"
+#include "widgets/GraphWidget.h"
+#include "widgets/OverviewWidget.h"
#include "widgets/StackWidget.h"
#include "widgets/RegistersWidget.h"
#include "widgets/BacktraceWidget.h"
@@ -103,6 +105,7 @@ public:
void updateDockActionChecked(QAction * action);
+ OverviewWidget *overviewDock = nullptr;
public slots:
void finalizeOpen();
@@ -199,7 +202,7 @@ private:
DisassemblyWidget *disassemblyDock = nullptr;
HexdumpWidget *hexdumpDock = nullptr;
PseudocodeWidget *pseudocodeDock = nullptr;
- QDockWidget *graphDock = nullptr;
+ GraphWidget *graphDock = nullptr;
EntrypointWidget *entrypointDock = nullptr;
FunctionsWidget *functionsDock = nullptr;
ImportsWidget *importsDock = nullptr;
diff --git a/src/MainWindow.ui b/src/MainWindow.ui
index 2af8acfe..b0f8679a 100644
--- a/src/MainWindow.ui
+++ b/src/MainWindow.ui
@@ -194,6 +194,7 @@ QToolTip {
+
@@ -933,6 +934,14 @@ QToolTip {
Graph
+
+
+ true
+
+
+ Graph Overview
+
+
true
diff --git a/src/common/Configuration.cpp b/src/common/Configuration.cpp
index d2181fad..7087d751 100644
--- a/src/common/Configuration.cpp
+++ b/src/common/Configuration.cpp
@@ -196,6 +196,7 @@ void Configuration::loadBaseThemeNative()
setColor("gui.breakpoint_background", QColor(233, 143, 143));
setColor("gui.item_invalid", QColor(155, 155, 155));
setColor("gui.item_unsafe", QColor(255, 129, 123));
+ setColor("gui.overview.node", QColor(200, 200, 200));
}
void Configuration::loadNativeTheme()
@@ -268,6 +269,8 @@ void Configuration::loadBaseThemeDark()
// RIP line selection in debug
setColor("highlightPC", QColor(87, 26, 7));
setColor("gui.breakpoint_background", QColor(140, 76, 76));
+
+ setColor("gui.overview.node", QColor(100, 100, 100));
}
void Configuration::loadDarkTheme()
diff --git a/src/widgets/DisassemblerGraphView.cpp b/src/widgets/DisassemblerGraphView.cpp
index 5c0d6dcd..2bd37639 100644
--- a/src/widgets/DisassemblerGraphView.cpp
+++ b/src/widgets/DisassemblerGraphView.cpp
@@ -157,6 +157,7 @@ void DisassemblerGraphView::refreshView()
initFont();
loadCurrentGraph();
viewport()->update();
+ emit viewRefreshed();
}
void DisassemblerGraphView::loadCurrentGraph()
diff --git a/src/widgets/DisassemblerGraphView.h b/src/widgets/DisassemblerGraphView.h
index 91438ce2..d1ee656d 100644
--- a/src/widgets/DisassemblerGraphView.h
+++ b/src/widgets/DisassemblerGraphView.h
@@ -128,6 +128,10 @@ public:
bool isGraphEmpty();
QTextEdit *header = nullptr;
+ int getWidth() { return width; }
+ int getHeight() { return height; }
+
+ std::unordered_map getBlocks() { return blocks; }
public slots:
void refreshView();
void colorsUpdatedSlot();
@@ -212,6 +216,9 @@ private:
QLabel *emptyText = nullptr;
SyntaxHighlighter *highlighter = nullptr;
+
+signals:
+ void viewRefreshed();
};
#endif // DISASSEMBLERGRAPHVIEW_H
diff --git a/src/widgets/GraphView.cpp b/src/widgets/GraphView.cpp
index ee226b50..76bb31d7 100644
--- a/src/widgets/GraphView.cpp
+++ b/src/widgets/GraphView.cpp
@@ -469,6 +469,7 @@ void GraphView::paintEvent(QPaintEvent *event)
QPen pen(edge.color);
// if(blockSelected)
// pen.setStyle(Qt::DashLine);
+ pen.setWidth(pen.width()/ec.width_scale);
p.setPen(pen);
p.setBrush(edge.color);
p.drawPolyline(edge.polyline);
@@ -482,6 +483,8 @@ void GraphView::paintEvent(QPaintEvent *event)
}
}
}
+
+ emit refreshBlock();
}
// Prepare graph
diff --git a/src/widgets/GraphView.h b/src/widgets/GraphView.h
index 77d15aa7..f48c4710 100644
--- a/src/widgets/GraphView.h
+++ b/src/widgets/GraphView.h
@@ -24,6 +24,10 @@ class GraphView : public QAbstractScrollArea
Wide,
Narrow,
};
+
+signals:
+ void refreshBlock();
+
public:
struct GraphBlock;
@@ -84,6 +88,7 @@ public:
QColor color = QColor(128, 128, 128);
bool start_arrow = false;
bool end_arrow = true;
+ qreal width_scale = 1.0;
};
explicit GraphView(QWidget *parent);
@@ -94,6 +99,12 @@ public:
void showBlock(GraphBlock &block, bool animated = false);
void showBlock(GraphBlock *block, bool animated = false);
+ // Zoom data
+ qreal current_scale = 1.0;
+
+ int unscrolled_render_offset_x = 0;
+ int unscrolled_render_offset_y = 0;
+
protected:
std::unordered_map blocks;
QColor backgroundColor = QColor(Qt::white);
@@ -104,11 +115,6 @@ protected:
// Padding inside the block
int block_padding = 16;
- // Zoom data
- double current_scale = 1.0;
-
- int unscrolled_render_offset_x = 0;
- int unscrolled_render_offset_y = 0;
void addBlock(GraphView::GraphBlock block);
void setEntry(ut64 e);
@@ -127,6 +133,16 @@ protected:
void adjustSize(int new_width, int new_height, QPoint mouse = QPoint(0, 0));
bool event(QEvent *event) override;
+
+ void resizeEvent(QResizeEvent *event) override;
+ // Mouse events
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void mouseDoubleClickEvent(QMouseEvent *event) override;
+
+ int width = 0;
+ int height = 0;
private:
bool checkPointClicked(QPointF &point, int x, int y, bool above_y = false);
@@ -138,8 +154,6 @@ private:
// Layout type
LayoutType layoutType = LayoutType::Medium;
- int width = 0;
- int height = 0;
bool ready = false;
// Scrolling data
@@ -163,15 +177,6 @@ private:
int findVertEdgeIndex(EdgesVector &edges, int col, int min_row, int max_row);
GraphEdge routeEdge(EdgesVector &horiz_edges, EdgesVector &vert_edges, Matrix &edge_valid,
GraphBlock &start, GraphBlock &end, QColor color);
-
-private slots:
- void resizeEvent(QResizeEvent *event) override;
- // Mouse events
- void mousePressEvent(QMouseEvent *event) override;
- void mouseMoveEvent(QMouseEvent *event) override;
- void mouseReleaseEvent(QMouseEvent *event) override;
- void mouseDoubleClickEvent(QMouseEvent *event) override;
-
};
#endif // GRAPHVIEW_H
diff --git a/src/widgets/GraphWidget.cpp b/src/widgets/GraphWidget.cpp
index 6c038daa..5c778811 100644
--- a/src/widgets/GraphWidget.cpp
+++ b/src/widgets/GraphWidget.cpp
@@ -2,14 +2,16 @@
#include "GraphWidget.h"
#include "DisassemblerGraphView.h"
#include "WidgetShortcuts.h"
+#include "OverviewView.h"
-GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
+GraphWidget::GraphWidget(MainWindow *main, OverviewWidget *overview, 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.
@@ -21,12 +23,17 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
});
connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) {
+ toggleOverview(visibility);
if (visibility) {
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph);
this->graphView->header->setFixedWidth(width());
}
});
+ connect(graphView, &DisassemblerGraphView::viewRefreshed, this, [ = ]() {
+ overviewWidget->graphView->setData(graphView->getWidth(), graphView->getHeight(), graphView->getBlocks());
+ });
+
connect(Core(), &CutterCore::raisePrioritizedMemoryWidget,
this, [ = ](CutterCore::MemoryWidgetType type) {
bool emptyGraph = (type == CutterCore::MemoryWidgetType::Graph && Core()->isGraphEmpty());
@@ -39,3 +46,86 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
}
GraphWidget::~GraphWidget() {}
+
+void GraphWidget::toggleOverview(bool visibility)
+{
+ if (!overviewWidget) {
+ return;
+ }
+ if (visibility) {
+ connect(graphView, SIGNAL(refreshBlock()), this, SLOT(adjustOverview()));
+ connect(graphView->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjustOverview()));
+ connect(graphView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjustOverview()));
+ connect(overviewWidget->graphView, SIGNAL(mouseMoved()), this, SLOT(adjustGraph()));
+ } else {
+ disconnect(graphView, SIGNAL(refreshBlock()), this, SLOT(adjustOverview()));
+ disconnect(graphView->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjustOverview()));
+ disconnect(graphView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjustOverview()));
+ disconnect(overviewWidget->graphView, SIGNAL(mouseMoved()), this, SLOT(adjustGraph()));
+ 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;
+ }
+ bool scrollXVisible = graphView->unscrolled_render_offset_x == 0;
+ bool scrollYVisible = graphView->unscrolled_render_offset_y == 0;
+ if (!scrollXVisible && !scrollYVisible) {
+ disableOverviewRect();
+ return;
+ }
+ qreal x = 0;
+ qreal y = 0;
+ qreal w = overviewWidget->graphView->viewport()->width();
+ qreal h = overviewWidget->graphView->viewport()->height();
+ qreal curScale = overviewWidget->graphView->current_scale;
+ qreal xoff = overviewWidget->graphView->unscrolled_render_offset_x;;
+ qreal yoff = overviewWidget->graphView->unscrolled_render_offset_y;;
+
+ w = graphView->viewport()->width();
+ h = graphView->viewport()->height();
+
+ if (scrollXVisible) {
+ x = graphView->horizontalScrollBar()->value();
+ w *= curScale;
+ } else {
+ xoff = 0;
+ }
+
+ if (scrollYVisible) {
+ y = graphView->verticalScrollBar()->value();
+ h *= curScale;
+ } else {
+ yoff = 0;
+ }
+ x *= curScale;
+ y *= curScale;
+ overviewWidget->graphView->rangeRect = QRectF(x + xoff, y + yoff, w, h);
+ overviewWidget->graphView->viewport()->update();
+}
+
+void GraphWidget::adjustGraph()
+{
+ if (!overviewWidget) {
+ return;
+ }
+ int x1 = overviewWidget->graphView->horizontalScrollBar()->value();
+ int y1 = overviewWidget->graphView->verticalScrollBar()->value();
+ qreal x2 = (overviewWidget->graphView->rangeRect.x() - (qreal)overviewWidget->graphView->unscrolled_render_offset_x)/ overviewWidget->graphView->current_scale;
+ qreal y2 = (overviewWidget->graphView->rangeRect.y() - (qreal)overviewWidget->graphView->unscrolled_render_offset_y)/ overviewWidget->graphView->current_scale;
+
+ graphView->horizontalScrollBar()->setValue(x1 + x2);
+ graphView->verticalScrollBar()->setValue(y1 + y2);
+}
diff --git a/src/widgets/GraphWidget.h b/src/widgets/GraphWidget.h
index 314c7a83..f13f14c2 100644
--- a/src/widgets/GraphWidget.h
+++ b/src/widgets/GraphWidget.h
@@ -5,17 +5,24 @@
class MainWindow;
class DisassemblerGraphView;
+class OverviewWidget;
class GraphWidget : public CutterDockWidget
{
Q_OBJECT
public:
- explicit GraphWidget(MainWindow *main, QAction *action = nullptr);
- ~GraphWidget() override;
-
+ explicit GraphWidget(MainWindow *main, OverviewWidget *overview, 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
new file mode 100644
index 00000000..4382793d
--- /dev/null
+++ b/src/widgets/OverviewView.cpp
@@ -0,0 +1,148 @@
+#include "OverviewView.h"
+#include
+#include
+
+#include "Cutter.h"
+#include "common/Colors.h"
+#include "common/Configuration.h"
+#include "common/TempConfig.h"
+
+OverviewView::OverviewView(QWidget *parent)
+ : GraphView(parent)
+{
+ connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
+ colorsUpdatedSlot();
+}
+
+void OverviewView::setData(int baseWidth, int baseHeight, std::unordered_map baseBlocks)
+{
+ width = baseWidth;
+ height = baseHeight;
+ blocks = baseBlocks;
+ refreshView();
+}
+
+OverviewView::~OverviewView()
+{
+}
+
+void OverviewView::adjustScale()
+{
+ if (horizontalScrollBar()->maximum() > 0) {
+ current_scale = (qreal)viewport()->width() / (qreal)(horizontalScrollBar()->maximum() + horizontalScrollBar()->pageStep());
+ }
+ if (verticalScrollBar()->maximum() > 0) {
+ qreal h_scale = (qreal)viewport()->height() / (qreal)(verticalScrollBar()->maximum() + verticalScrollBar()->pageStep());
+ if (current_scale > h_scale) {
+ current_scale = h_scale;
+ }
+ }
+ adjustSize(viewport()->size().width(), viewport()->size().height());
+ viewport()->update();
+}
+
+void OverviewView::refreshView()
+{
+ current_scale = 1.0;
+ viewport()->update();
+ adjustSize(viewport()->size().width(), viewport()->size().height());
+ adjustScale();
+}
+
+void OverviewView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
+{
+ p.setPen(Qt::black);
+ p.setBrush(Qt::gray);
+ p.drawRect(block.x, block.y, block.width, block.height);
+ p.setBrush(QColor(0, 0, 0, 100));
+ p.drawRect(block.x + 2, block.y + 2,
+ block.width, block.height);
+ p.setPen(QPen(graphNodeColor, 1));
+ p.setBrush(disassemblyBackgroundColor);
+ p.drawRect(block.x, block.y,
+ block.width, block.height);
+}
+
+void OverviewView::paintEvent(QPaintEvent *event)
+{
+ GraphView::paintEvent(event);
+ if (rangeRect.width() == 0 && rangeRect.height() == 0) {
+ return;
+ }
+ QPainter p(viewport());
+ p.setPen(Qt::red);
+ p.drawRect(rangeRect);
+}
+
+void OverviewView::mousePressEvent(QMouseEvent *event)
+{
+ if (rangeRect.contains(event->pos())) {
+ mouseActive = true;
+ initialDiff = QPointF(event->localPos().x() - rangeRect.x(), event->localPos().y() - rangeRect.y());
+ return;
+ }
+ qreal w = rangeRect.width();
+ qreal h = rangeRect.height();
+ qreal x = event->localPos().x() - w/2;
+ qreal y = event->localPos().y() - h/2;
+ rangeRect = QRectF(x, y, w, h);
+ viewport()->update();
+ emit mouseMoved();
+ mousePressEvent(event);
+}
+
+void OverviewView::mouseReleaseEvent(QMouseEvent *event)
+{
+ mouseActive = false;
+ GraphView::mouseReleaseEvent(event);
+}
+
+void OverviewView::mouseMoveEvent(QMouseEvent *event)
+{
+ if (!mouseActive) {
+ return;
+ }
+ qreal x = event->localPos().x() - initialDiff.x();
+ qreal y = event->localPos().y() - initialDiff.y();
+ qreal w = rangeRect.width();
+ qreal h = rangeRect.height();
+ qreal real_width = width * current_scale;
+ qreal real_height = height * current_scale;
+ qreal max_right = unscrolled_render_offset_x + real_width;
+ qreal max_bottom = unscrolled_render_offset_y + real_height;
+ qreal rect_right = x + w;
+ qreal rect_bottom = y + h;
+ if (rect_right >= max_right) {
+ x = real_width - w;
+ }
+ if (rect_bottom >= max_bottom) {
+ y = real_height - h;
+ }
+ if (x <= 0) {
+ x = 0;
+ }
+ if (y <= 0) {
+ y = 0;
+ }
+ rangeRect = QRectF(x, y, w, h);
+ viewport()->update();
+ emit mouseMoved();
+}
+
+GraphView::EdgeConfiguration OverviewView::edgeConfiguration(GraphView::GraphBlock &from,
+ GraphView::GraphBlock *to)
+{
+ Q_UNUSED(from);
+ Q_UNUSED(to);
+ EdgeConfiguration ec;
+ ec.width_scale = current_scale;
+ return ec;
+}
+
+void OverviewView::colorsUpdatedSlot()
+{
+ disassemblyBackgroundColor = ConfigColor("gui.overview.node");
+ graphNodeColor = ConfigColor("gui.border");
+ backgroundColor = ConfigColor("gui.background");
+ refreshView();
+}
diff --git a/src/widgets/OverviewView.h b/src/widgets/OverviewView.h
new file mode 100644
index 00000000..6c80770b
--- /dev/null
+++ b/src/widgets/OverviewView.h
@@ -0,0 +1,112 @@
+#ifndef OVERVIEWVIEW_H
+#define OVERVIEWVIEW_H
+
+#include
+#include
+#include
+#include "widgets/GraphView.h"
+
+class OverviewView : public GraphView
+{
+ Q_OBJECT
+
+signals:
+ /**
+ * @brief signal when mouse is pressed or moved so that
+ * Graph can refresh its contents corresponded with Overview
+ */
+ void mouseMoved();
+
+public:
+ OverviewView(QWidget *parent);
+ ~OverviewView() override;
+
+ /**
+ * @brief a rect on Overview to show where you are on Graph
+ */
+ QRectF rangeRect;
+
+ /**
+ * @brief Graph access this function to set minimum set of the data
+ * @param baseWidth width of Graph when it computed the blocks
+ * @param baseHeigh height of Graph when it computed the blocks
+ * @param baseBlocks computed blocks passed by Graph
+ */
+ void setData(int baseWidth, int baseHeight, std::unordered_map baseBlocks);
+
+public slots:
+ /**
+ * @brief refresh the view and adjust the scale
+ */
+ void refreshView();
+
+private slots:
+ /**
+ * @brief update Colors.
+ * for example this will be called when the theme is changed.
+ */
+ void colorsUpdatedSlot();
+
+protected:
+ /**
+ * @brief mousePressEvent to start moving the rect.
+ */
+ void mousePressEvent(QMouseEvent *event) override;
+ /**
+ * @brief mouseReleaseEvent to tell not to move the rect anymore.
+ */
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ /**
+ * @brief mouseMoveEvent to move the rect.
+ */
+ void mouseMoveEvent(QMouseEvent *event) override;
+
+private:
+ /**
+ * @brief this will be handled in mouse events to move the rect properly
+ * along with the mouse.
+ */
+ bool mouseActive = false;
+
+ /**
+ * @brief save the initial distance
+ * between the point where the mouse was pressed and the point of the rect
+ * so as to change the rect point properly along with mouse.
+ */
+ QPointF initialDiff;
+
+ /**
+ * @brief draw the computed blocks passed by Graph
+ */
+ virtual void drawBlock(QPainter &p, GraphView::GraphBlock &block) override;
+
+ /**
+ * @brief override the edgeConfiguration so as to
+ * adjust the width of the edges by the scale
+ * @return EdgeConfiguration
+ */
+ virtual GraphView::EdgeConfiguration edgeConfiguration(GraphView::GraphBlock &from,
+ GraphView::GraphBlock *to) override;
+
+ /**
+ * @brief override the paintEvent to draw the rect on Overview
+ */
+ void paintEvent(QPaintEvent *event) override;
+
+ /**
+ * @brief apply scale properly on the view
+ */
+ void adjustScale();
+
+ /**
+ * @brief base background color changing depending on the theme
+ */
+ QColor disassemblyBackgroundColor;
+
+ /**
+ * @brief color for each node changing depending on the theme
+ */
+ QColor graphNodeColor;
+};
+
+#endif // OVERVIEWVIEW_H
diff --git a/src/widgets/OverviewWidget.cpp b/src/widgets/OverviewWidget.cpp
new file mode 100644
index 00000000..69c51fae
--- /dev/null
+++ b/src/widgets/OverviewWidget.cpp
@@ -0,0 +1,33 @@
+#include "MainWindow.h"
+#include "OverviewWidget.h"
+#include "OverviewView.h"
+
+OverviewWidget::OverviewWidget(MainWindow *main, QAction *action) :
+ CutterDockWidget(main, action)
+{
+ this->setWindowTitle("Graph Overview");
+ this->setObjectName("Graph Overview");
+ this->setAllowedAreas(Qt::AllDockWidgetAreas);
+ this->graphView = new OverviewView(this);
+ this->setWidget(graphView);
+ refreshDeferrer = createRefreshDeferrer([this]() {
+ updateContents();
+ });
+
+ connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) {
+ if (visibility) {
+ Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph);
+ updateContents();
+ }
+ });
+}
+
+OverviewWidget::~OverviewWidget() {}
+
+void OverviewWidget::updateContents()
+{
+ if (!refreshDeferrer->attemptRefresh(nullptr)) {
+ return;
+ }
+ graphView->refreshView();
+}
diff --git a/src/widgets/OverviewWidget.h b/src/widgets/OverviewWidget.h
new file mode 100644
index 00000000..c58c2b01
--- /dev/null
+++ b/src/widgets/OverviewWidget.h
@@ -0,0 +1,28 @@
+#ifndef OVERVIEWWIDGET_H
+#define OVERVIEWWIDGET_H
+
+#include "CutterDockWidget.h"
+
+class MainWindow;
+class OverviewView;
+
+class OverviewWidget : public CutterDockWidget
+{
+ Q_OBJECT
+
+public:
+ explicit OverviewWidget(MainWindow *main, QAction *action = nullptr);
+ ~OverviewWidget();
+ OverviewView *graphView;
+
+private:
+ RefreshDeferrer *refreshDeferrer;
+
+private slots:
+ /**
+ * @brief update the overview
+ */
+ void updateContents();
+};
+
+#endif // OverviewWIDGET_H