2017-12-13 22:38:46 +00:00
|
|
|
#ifndef GRAPHVIEW_H
|
|
|
|
#define GRAPHVIEW_H
|
|
|
|
|
|
|
|
#include <QObject>
|
|
|
|
#include <QPainter>
|
|
|
|
#include <QWidget>
|
|
|
|
#include <QAbstractScrollArea>
|
|
|
|
#include <QScrollBar>
|
2017-12-14 21:07:48 +00:00
|
|
|
#include <QElapsedTimer>
|
2017-12-19 16:59:39 +00:00
|
|
|
#include <QHelpEvent>
|
2017-12-13 22:38:46 +00:00
|
|
|
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <unordered_set>
|
|
|
|
#include <queue>
|
|
|
|
|
2018-03-04 17:42:02 +00:00
|
|
|
#include "Cutter.h"
|
2017-12-13 22:38:46 +00:00
|
|
|
|
|
|
|
class GraphView : public QAbstractScrollArea
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
enum class LayoutType {
|
2017-12-13 22:38:46 +00:00
|
|
|
Medium,
|
2017-12-14 21:07:48 +00:00
|
|
|
Wide,
|
2017-12-13 22:38:46 +00:00
|
|
|
Narrow,
|
|
|
|
};
|
|
|
|
public:
|
|
|
|
struct GraphBlock;
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
struct Point {
|
2017-12-13 22:38:46 +00:00
|
|
|
int row; //point[0]
|
|
|
|
int col; //point[1]
|
|
|
|
int index; //point[2]
|
|
|
|
};
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
struct GraphEdge {
|
2017-12-13 22:38:46 +00:00
|
|
|
QColor color;
|
|
|
|
GraphBlock *dest;
|
|
|
|
std::vector<Point> points;
|
|
|
|
int start_index = 0;
|
|
|
|
|
|
|
|
QPolygonF polyline;
|
|
|
|
QPolygonF arrow_start;
|
|
|
|
QPolygonF arrow_end;
|
|
|
|
|
|
|
|
void addPoint(int row, int col, int index = 0)
|
|
|
|
{
|
|
|
|
Point point = {row, col, 0};
|
|
|
|
this->points.push_back(point);
|
2018-03-21 20:32:32 +00:00
|
|
|
if (int(this->points.size()) > 1)
|
2017-12-13 22:38:46 +00:00
|
|
|
this->points[this->points.size() - 2].index = index;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct GraphBlock {
|
|
|
|
qreal x = 0.0;
|
|
|
|
qreal y = 0.0;
|
|
|
|
int width = 0;
|
|
|
|
int height = 0;
|
|
|
|
// This is a unique identifier, e.g. offset in the case of r2 blocks
|
|
|
|
ut64 entry;
|
|
|
|
// This contains unique identifiers to entries
|
|
|
|
// Outgoing edges
|
|
|
|
std::vector<ut64> exits;
|
|
|
|
// Incoming edges
|
|
|
|
std::vector<ut64> incoming;
|
|
|
|
// TODO what is this
|
|
|
|
std::vector<ut64> new_exits;
|
|
|
|
|
|
|
|
// Number of rows in block
|
2017-12-24 12:11:29 +00:00
|
|
|
int row_count = 0;
|
2017-12-13 22:38:46 +00:00
|
|
|
// Number of columns in block
|
2017-12-24 12:11:29 +00:00
|
|
|
int col_count = 0;
|
2017-12-13 22:38:46 +00:00
|
|
|
// Column in which the block is
|
2017-12-24 12:11:29 +00:00
|
|
|
int col = 0;
|
2017-12-13 22:38:46 +00:00
|
|
|
// Row in which the block is
|
2017-12-24 12:11:29 +00:00
|
|
|
int row = 0;
|
2017-12-13 22:38:46 +00:00
|
|
|
|
|
|
|
// Edges
|
|
|
|
std::vector<GraphEdge> edges;
|
|
|
|
};
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
struct EdgeConfiguration {
|
2017-12-13 22:38:46 +00:00
|
|
|
QColor color = QColor(128, 128, 128);
|
|
|
|
bool start_arrow = false;
|
|
|
|
bool end_arrow = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
GraphView(QWidget *parent);
|
|
|
|
~GraphView();
|
2018-03-21 20:32:32 +00:00
|
|
|
void paintEvent(QPaintEvent *event) override;
|
2017-12-13 22:38:46 +00:00
|
|
|
|
|
|
|
// Show a block centered. Animates to it if animated=true
|
2018-03-21 20:32:32 +00:00
|
|
|
void showBlock(GraphBlock &block, bool animated = false);
|
|
|
|
void showBlock(GraphBlock *block, bool animated = false);
|
2017-12-13 22:38:46 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
std::unordered_map<ut64, GraphBlock> blocks;
|
|
|
|
QColor backgroundColor = QColor(Qt::white);
|
|
|
|
// The vertical margin between blocks
|
2017-12-14 22:06:34 +00:00
|
|
|
int block_vertical_margin = 20;
|
2017-12-14 21:07:48 +00:00
|
|
|
int block_horizontal_margin = 10;
|
|
|
|
|
|
|
|
// Padding inside the block
|
|
|
|
int block_padding = 16;
|
2017-12-13 22:38:46 +00:00
|
|
|
|
|
|
|
// Zoom data
|
|
|
|
double current_scale = 1.0;
|
|
|
|
|
2017-12-14 21:07:48 +00:00
|
|
|
int unscrolled_render_offset_x = 0;
|
|
|
|
int unscrolled_render_offset_y = 0;
|
|
|
|
|
2017-12-13 22:38:46 +00:00
|
|
|
void addBlock(GraphView::GraphBlock block);
|
|
|
|
void setEntry(ut64 e);
|
|
|
|
void computeGraph(ut64 entry);
|
|
|
|
|
|
|
|
// Callbacks that should be overridden
|
2018-03-21 20:32:32 +00:00
|
|
|
virtual void drawBlock(QPainter &p, GraphView::GraphBlock &block);
|
2017-12-13 22:38:46 +00:00
|
|
|
virtual void blockClicked(GraphView::GraphBlock &block, QMouseEvent *event, QPoint pos);
|
2017-12-14 21:07:48 +00:00
|
|
|
virtual void blockDoubleClicked(GraphView::GraphBlock &block, QMouseEvent *event, QPoint pos);
|
2017-12-19 16:59:39 +00:00
|
|
|
virtual void blockHelpEvent(GraphView::GraphBlock &block, QHelpEvent *event, QPoint pos);
|
|
|
|
virtual bool helpEvent(QHelpEvent *event);
|
2017-12-13 22:38:46 +00:00
|
|
|
virtual void blockTransitionedTo(GraphView::GraphBlock *to);
|
|
|
|
virtual EdgeConfiguration edgeConfiguration(GraphView::GraphBlock &from, GraphView::GraphBlock *to);
|
|
|
|
|
|
|
|
void adjustSize(int new_width, int new_height);
|
2017-12-19 16:59:39 +00:00
|
|
|
|
2018-03-11 10:29:37 +00:00
|
|
|
bool event(QEvent *event) override;
|
2017-12-13 22:38:46 +00:00
|
|
|
private:
|
2018-03-21 20:32:32 +00:00
|
|
|
bool checkPointClicked(QPointF &point, int x, int y, bool above_y = false);
|
2017-12-13 22:38:46 +00:00
|
|
|
|
|
|
|
ut64 entry;
|
|
|
|
|
|
|
|
void computeGraphLayout(GraphBlock &block);
|
|
|
|
void adjustGraphLayout(GraphBlock &block, int col, int row);
|
|
|
|
|
|
|
|
// Layout type
|
|
|
|
LayoutType layoutType;
|
|
|
|
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
bool ready;
|
|
|
|
|
|
|
|
// Scrolling data
|
|
|
|
int scroll_base_x;
|
|
|
|
int scroll_base_y;
|
|
|
|
bool scroll_mode;
|
|
|
|
|
|
|
|
|
|
|
|
// Todo: remove charheight/charwidth cause it should be handled in child class
|
|
|
|
qreal charWidth = 10.0;
|
|
|
|
|
|
|
|
// Edge computing stuff
|
|
|
|
template<typename T>
|
|
|
|
using Matrix = std::vector<std::vector<T>>;
|
|
|
|
using EdgesVector = Matrix<std::vector<bool>>;
|
|
|
|
std::vector<int> col_edge_x;
|
|
|
|
std::vector<int> row_edge_y;
|
2018-03-21 20:32:32 +00:00
|
|
|
bool isEdgeMarked(EdgesVector &edges, int row, int col, int index);
|
|
|
|
void markEdge(EdgesVector &edges, int row, int col, int index, bool used = true);
|
|
|
|
int findHorizEdgeIndex(EdgesVector &edges, int row, int min_col, int max_col);
|
|
|
|
int findVertEdgeIndex(EdgesVector &edges, int col, int min_row, int max_row);
|
|
|
|
GraphEdge routeEdge(EdgesVector &horiz_edges, EdgesVector &vert_edges, Matrix<bool> &edge_valid,
|
|
|
|
GraphBlock &start, GraphBlock &end, QColor color);
|
2017-12-13 22:38:46 +00:00
|
|
|
|
|
|
|
private slots:
|
2018-03-21 20:32:32 +00:00
|
|
|
void resizeEvent(QResizeEvent *event) override;
|
2017-12-13 22:38:46 +00:00
|
|
|
// Mouse events
|
|
|
|
void mousePressEvent(QMouseEvent *event) override;
|
|
|
|
void mouseMoveEvent(QMouseEvent *event) override;
|
|
|
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
2017-12-14 21:07:48 +00:00
|
|
|
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
2017-12-13 22:38:46 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // GRAPHVIEW_H
|