mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-24 05:45:27 +00:00
parent
fc534df099
commit
b25afecc2c
@ -128,6 +128,7 @@ SOURCES += \
|
|||||||
Main.cpp \
|
Main.cpp \
|
||||||
Cutter.cpp \
|
Cutter.cpp \
|
||||||
widgets/DisassemblerGraphView.cpp \
|
widgets/DisassemblerGraphView.cpp \
|
||||||
|
widgets/OverviewView.cpp \
|
||||||
common/RichTextPainter.cpp \
|
common/RichTextPainter.cpp \
|
||||||
dialogs/InitialOptionsDialog.cpp \
|
dialogs/InitialOptionsDialog.cpp \
|
||||||
dialogs/AboutDialog.cpp \
|
dialogs/AboutDialog.cpp \
|
||||||
@ -192,6 +193,7 @@ SOURCES += \
|
|||||||
widgets/CutterDockWidget.cpp \
|
widgets/CutterDockWidget.cpp \
|
||||||
widgets/CutterTreeWidget.cpp \
|
widgets/CutterTreeWidget.cpp \
|
||||||
widgets/GraphWidget.cpp \
|
widgets/GraphWidget.cpp \
|
||||||
|
widgets/OverviewWidget.cpp \
|
||||||
common/JsonTreeItem.cpp \
|
common/JsonTreeItem.cpp \
|
||||||
common/JsonModel.cpp \
|
common/JsonModel.cpp \
|
||||||
dialogs/VersionInfoDialog.cpp \
|
dialogs/VersionInfoDialog.cpp \
|
||||||
@ -229,6 +231,7 @@ SOURCES += \
|
|||||||
HEADERS += \
|
HEADERS += \
|
||||||
Cutter.h \
|
Cutter.h \
|
||||||
widgets/DisassemblerGraphView.h \
|
widgets/DisassemblerGraphView.h \
|
||||||
|
widgets/OverviewView.h \
|
||||||
common/RichTextPainter.h \
|
common/RichTextPainter.h \
|
||||||
common/CachedFontMetrics.h \
|
common/CachedFontMetrics.h \
|
||||||
dialogs/AboutDialog.h \
|
dialogs/AboutDialog.h \
|
||||||
@ -294,6 +297,7 @@ HEADERS += \
|
|||||||
widgets/CutterDockWidget.h \
|
widgets/CutterDockWidget.h \
|
||||||
widgets/CutterTreeWidget.h \
|
widgets/CutterTreeWidget.h \
|
||||||
widgets/GraphWidget.h \
|
widgets/GraphWidget.h \
|
||||||
|
widgets/OverviewWidget.h \
|
||||||
common/JsonTreeItem.h \
|
common/JsonTreeItem.h \
|
||||||
common/JsonModel.h \
|
common/JsonModel.h \
|
||||||
dialogs/VersionInfoDialog.h \
|
dialogs/VersionInfoDialog.h \
|
||||||
|
@ -54,7 +54,9 @@
|
|||||||
|
|
||||||
// Widgets Headers
|
// Widgets Headers
|
||||||
#include "widgets/DisassemblerGraphView.h"
|
#include "widgets/DisassemblerGraphView.h"
|
||||||
|
#include "widgets/GraphView.h"
|
||||||
#include "widgets/GraphWidget.h"
|
#include "widgets/GraphWidget.h"
|
||||||
|
#include "widgets/OverviewWidget.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"
|
||||||
@ -182,7 +184,17 @@ void MainWindow::initUI()
|
|||||||
consoleDock = new ConsoleWidget(this, ui->actionConsole);
|
consoleDock = new ConsoleWidget(this, ui->actionConsole);
|
||||||
|
|
||||||
// Add graph view as dockable
|
// 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);
|
sectionsDock = new SectionsWidget(this, ui->actionSections);
|
||||||
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
|
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
|
||||||
@ -558,9 +570,11 @@ void MainWindow::restoreDocks()
|
|||||||
{
|
{
|
||||||
// In the upper half the functions are the first widget
|
// In the upper half the functions are the first widget
|
||||||
addDockWidget(Qt::TopDockWidgetArea, functionsDock);
|
addDockWidget(Qt::TopDockWidgetArea, functionsDock);
|
||||||
|
addDockWidget(Qt::TopDockWidgetArea, overviewDock);
|
||||||
|
|
||||||
// Function | Dashboard
|
// 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
|
// In the lower half the console is the first widget
|
||||||
addDockWidget(Qt::BottomDockWidgetArea, consoleDock);
|
addDockWidget(Qt::BottomDockWidgetArea, consoleDock);
|
||||||
@ -688,8 +702,10 @@ void MainWindow::resetToDefaultLayout()
|
|||||||
// Ugly workaround to set the default widths of functions docks
|
// 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!
|
// 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 restoreFunctionDock = qhelpers::forceWidth(functionsDock->widget(), 200);
|
||||||
|
auto restoreOverviewDock = qhelpers::forceWidth(overviewDock->widget(), 200);
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
restoreFunctionDock.restoreWidth(functionsDock->widget());
|
restoreFunctionDock.restoreWidth(functionsDock->widget());
|
||||||
|
restoreOverviewDock.restoreWidth(overviewDock->widget());
|
||||||
|
|
||||||
core->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Disassembly);
|
core->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Disassembly);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "Cutter.h" // only needed for ut64
|
#include "Cutter.h" // only needed for ut64
|
||||||
#include "widgets/DisassemblyWidget.h"
|
#include "widgets/DisassemblyWidget.h"
|
||||||
|
#include "widgets/GraphWidget.h"
|
||||||
|
#include "widgets/OverviewWidget.h"
|
||||||
#include "widgets/StackWidget.h"
|
#include "widgets/StackWidget.h"
|
||||||
#include "widgets/RegistersWidget.h"
|
#include "widgets/RegistersWidget.h"
|
||||||
#include "widgets/BacktraceWidget.h"
|
#include "widgets/BacktraceWidget.h"
|
||||||
@ -103,6 +105,7 @@ public:
|
|||||||
|
|
||||||
void updateDockActionChecked(QAction * action);
|
void updateDockActionChecked(QAction * action);
|
||||||
|
|
||||||
|
OverviewWidget *overviewDock = nullptr;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void finalizeOpen();
|
void finalizeOpen();
|
||||||
@ -199,7 +202,7 @@ private:
|
|||||||
DisassemblyWidget *disassemblyDock = nullptr;
|
DisassemblyWidget *disassemblyDock = nullptr;
|
||||||
HexdumpWidget *hexdumpDock = nullptr;
|
HexdumpWidget *hexdumpDock = nullptr;
|
||||||
PseudocodeWidget *pseudocodeDock = nullptr;
|
PseudocodeWidget *pseudocodeDock = nullptr;
|
||||||
QDockWidget *graphDock = nullptr;
|
GraphWidget *graphDock = nullptr;
|
||||||
EntrypointWidget *entrypointDock = nullptr;
|
EntrypointWidget *entrypointDock = nullptr;
|
||||||
FunctionsWidget *functionsDock = nullptr;
|
FunctionsWidget *functionsDock = nullptr;
|
||||||
ImportsWidget *importsDock = nullptr;
|
ImportsWidget *importsDock = nullptr;
|
||||||
|
@ -194,6 +194,7 @@ QToolTip {
|
|||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionDisassembly"/>
|
<addaction name="actionDisassembly"/>
|
||||||
<addaction name="actionGraph"/>
|
<addaction name="actionGraph"/>
|
||||||
|
<addaction name="actionOverview"/>
|
||||||
<addaction name="actionHexdump"/>
|
<addaction name="actionHexdump"/>
|
||||||
<addaction name="actionPseudocode"/>
|
<addaction name="actionPseudocode"/>
|
||||||
<addaction name="actionFunctions"/>
|
<addaction name="actionFunctions"/>
|
||||||
@ -933,6 +934,14 @@ QToolTip {
|
|||||||
<string>Graph</string>
|
<string>Graph</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionOverview">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Graph Overview</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionPseudocode">
|
<action name="actionPseudocode">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -196,6 +196,7 @@ void Configuration::loadBaseThemeNative()
|
|||||||
setColor("gui.breakpoint_background", QColor(233, 143, 143));
|
setColor("gui.breakpoint_background", QColor(233, 143, 143));
|
||||||
setColor("gui.item_invalid", QColor(155, 155, 155));
|
setColor("gui.item_invalid", QColor(155, 155, 155));
|
||||||
setColor("gui.item_unsafe", QColor(255, 129, 123));
|
setColor("gui.item_unsafe", QColor(255, 129, 123));
|
||||||
|
setColor("gui.overview.node", QColor(200, 200, 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Configuration::loadNativeTheme()
|
void Configuration::loadNativeTheme()
|
||||||
@ -268,6 +269,8 @@ void Configuration::loadBaseThemeDark()
|
|||||||
// RIP line selection in debug
|
// RIP line selection in debug
|
||||||
setColor("highlightPC", QColor(87, 26, 7));
|
setColor("highlightPC", QColor(87, 26, 7));
|
||||||
setColor("gui.breakpoint_background", QColor(140, 76, 76));
|
setColor("gui.breakpoint_background", QColor(140, 76, 76));
|
||||||
|
|
||||||
|
setColor("gui.overview.node", QColor(100, 100, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Configuration::loadDarkTheme()
|
void Configuration::loadDarkTheme()
|
||||||
|
@ -157,6 +157,7 @@ void DisassemblerGraphView::refreshView()
|
|||||||
initFont();
|
initFont();
|
||||||
loadCurrentGraph();
|
loadCurrentGraph();
|
||||||
viewport()->update();
|
viewport()->update();
|
||||||
|
emit viewRefreshed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblerGraphView::loadCurrentGraph()
|
void DisassemblerGraphView::loadCurrentGraph()
|
||||||
|
@ -128,6 +128,10 @@ public:
|
|||||||
bool isGraphEmpty();
|
bool isGraphEmpty();
|
||||||
QTextEdit *header = nullptr;
|
QTextEdit *header = nullptr;
|
||||||
|
|
||||||
|
int getWidth() { return width; }
|
||||||
|
int getHeight() { return height; }
|
||||||
|
|
||||||
|
std::unordered_map<ut64, GraphBlock> getBlocks() { return blocks; }
|
||||||
public slots:
|
public slots:
|
||||||
void refreshView();
|
void refreshView();
|
||||||
void colorsUpdatedSlot();
|
void colorsUpdatedSlot();
|
||||||
@ -212,6 +216,9 @@ private:
|
|||||||
|
|
||||||
QLabel *emptyText = nullptr;
|
QLabel *emptyText = nullptr;
|
||||||
SyntaxHighlighter *highlighter = nullptr;
|
SyntaxHighlighter *highlighter = nullptr;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void viewRefreshed();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DISASSEMBLERGRAPHVIEW_H
|
#endif // DISASSEMBLERGRAPHVIEW_H
|
||||||
|
@ -469,6 +469,7 @@ void GraphView::paintEvent(QPaintEvent *event)
|
|||||||
QPen pen(edge.color);
|
QPen pen(edge.color);
|
||||||
// if(blockSelected)
|
// if(blockSelected)
|
||||||
// pen.setStyle(Qt::DashLine);
|
// pen.setStyle(Qt::DashLine);
|
||||||
|
pen.setWidth(pen.width()/ec.width_scale);
|
||||||
p.setPen(pen);
|
p.setPen(pen);
|
||||||
p.setBrush(edge.color);
|
p.setBrush(edge.color);
|
||||||
p.drawPolyline(edge.polyline);
|
p.drawPolyline(edge.polyline);
|
||||||
@ -482,6 +483,8 @@ void GraphView::paintEvent(QPaintEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit refreshBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare graph
|
// Prepare graph
|
||||||
|
@ -24,6 +24,10 @@ class GraphView : public QAbstractScrollArea
|
|||||||
Wide,
|
Wide,
|
||||||
Narrow,
|
Narrow,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void refreshBlock();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct GraphBlock;
|
struct GraphBlock;
|
||||||
|
|
||||||
@ -84,6 +88,7 @@ public:
|
|||||||
QColor color = QColor(128, 128, 128);
|
QColor color = QColor(128, 128, 128);
|
||||||
bool start_arrow = false;
|
bool start_arrow = false;
|
||||||
bool end_arrow = true;
|
bool end_arrow = true;
|
||||||
|
qreal width_scale = 1.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit GraphView(QWidget *parent);
|
explicit GraphView(QWidget *parent);
|
||||||
@ -94,6 +99,12 @@ public:
|
|||||||
void showBlock(GraphBlock &block, bool animated = false);
|
void showBlock(GraphBlock &block, bool animated = false);
|
||||||
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:
|
protected:
|
||||||
std::unordered_map<ut64, GraphBlock> blocks;
|
std::unordered_map<ut64, GraphBlock> blocks;
|
||||||
QColor backgroundColor = QColor(Qt::white);
|
QColor backgroundColor = QColor(Qt::white);
|
||||||
@ -104,11 +115,6 @@ protected:
|
|||||||
// Padding inside the block
|
// Padding inside the block
|
||||||
int block_padding = 16;
|
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 addBlock(GraphView::GraphBlock block);
|
||||||
void setEntry(ut64 e);
|
void setEntry(ut64 e);
|
||||||
@ -127,6 +133,16 @@ protected:
|
|||||||
void adjustSize(int new_width, int new_height, QPoint mouse = QPoint(0, 0));
|
void adjustSize(int new_width, int new_height, QPoint mouse = QPoint(0, 0));
|
||||||
|
|
||||||
bool event(QEvent *event) override;
|
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:
|
private:
|
||||||
bool checkPointClicked(QPointF &point, int x, int y, bool above_y = false);
|
bool checkPointClicked(QPointF &point, int x, int y, bool above_y = false);
|
||||||
|
|
||||||
@ -138,8 +154,6 @@ private:
|
|||||||
// Layout type
|
// Layout type
|
||||||
LayoutType layoutType = LayoutType::Medium;
|
LayoutType layoutType = LayoutType::Medium;
|
||||||
|
|
||||||
int width = 0;
|
|
||||||
int height = 0;
|
|
||||||
bool ready = false;
|
bool ready = false;
|
||||||
|
|
||||||
// Scrolling data
|
// Scrolling data
|
||||||
@ -163,15 +177,6 @@ private:
|
|||||||
int findVertEdgeIndex(EdgesVector &edges, int col, int min_row, int max_row);
|
int findVertEdgeIndex(EdgesVector &edges, int col, int min_row, int max_row);
|
||||||
GraphEdge routeEdge(EdgesVector &horiz_edges, EdgesVector &vert_edges, Matrix<bool> &edge_valid,
|
GraphEdge routeEdge(EdgesVector &horiz_edges, EdgesVector &vert_edges, Matrix<bool> &edge_valid,
|
||||||
GraphBlock &start, GraphBlock &end, QColor color);
|
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
|
#endif // GRAPHVIEW_H
|
||||||
|
@ -2,14 +2,16 @@
|
|||||||
#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, QAction *action) :
|
GraphWidget::GraphWidget(MainWindow *main, OverviewWidget *overview, 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.
|
||||||
@ -21,12 +23,17 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) {
|
connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) {
|
||||||
|
toggleOverview(visibility);
|
||||||
if (visibility) {
|
if (visibility) {
|
||||||
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph);
|
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph);
|
||||||
this->graphView->header->setFixedWidth(width());
|
this->graphView->header->setFixedWidth(width());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(graphView, &DisassemblerGraphView::viewRefreshed, this, [ = ]() {
|
||||||
|
overviewWidget->graphView->setData(graphView->getWidth(), graphView->getHeight(), graphView->getBlocks());
|
||||||
|
});
|
||||||
|
|
||||||
connect(Core(), &CutterCore::raisePrioritizedMemoryWidget,
|
connect(Core(), &CutterCore::raisePrioritizedMemoryWidget,
|
||||||
this, [ = ](CutterCore::MemoryWidgetType type) {
|
this, [ = ](CutterCore::MemoryWidgetType type) {
|
||||||
bool emptyGraph = (type == CutterCore::MemoryWidgetType::Graph && Core()->isGraphEmpty());
|
bool emptyGraph = (type == CutterCore::MemoryWidgetType::Graph && Core()->isGraphEmpty());
|
||||||
@ -39,3 +46,86 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
GraphWidget::~GraphWidget() {}
|
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);
|
||||||
|
}
|
||||||
|
@ -5,17 +5,24 @@
|
|||||||
|
|
||||||
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, QAction *action = nullptr);
|
explicit GraphWidget(MainWindow *main, OverviewWidget *overview, QAction *action = nullptr);
|
||||||
~GraphWidget() override;
|
~GraphWidget();
|
||||||
|
|
||||||
private:
|
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
|
||||||
|
148
src/widgets/OverviewView.cpp
Normal file
148
src/widgets/OverviewView.cpp
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#include "OverviewView.h"
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
|
#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<ut64, GraphBlock> 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();
|
||||||
|
}
|
112
src/widgets/OverviewView.h
Normal file
112
src/widgets/OverviewView.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#ifndef OVERVIEWVIEW_H
|
||||||
|
#define OVERVIEWVIEW_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QRect>
|
||||||
|
#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<ut64, GraphBlock> 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
|
33
src/widgets/OverviewWidget.cpp
Normal file
33
src/widgets/OverviewWidget.cpp
Normal file
@ -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();
|
||||||
|
}
|
28
src/widgets/OverviewWidget.h
Normal file
28
src/widgets/OverviewWidget.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user