cutter/src/widgets/GraphView.h

201 lines
5.7 KiB
C
Raw Normal View History

#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>
#include <QHelpEvent>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <memory>
#include "core/Cutter.h"
#include "widgets/GraphLayout.h"
#if defined(QT_NO_OPENGL) || QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
// QOpenGLExtraFunctions were introduced in 5.6
#define CUTTER_NO_OPENGL_GRAPH
#endif
#ifndef CUTTER_NO_OPENGL_GRAPH
2019-04-07 10:53:42 +00:00
class QOpenGLWidget;
#endif
class GraphView : public QAbstractScrollArea
{
Q_OBJECT
signals:
void viewOffsetChanged(QPoint offset);
void viewScaleChanged(qreal scale);
public:
using GraphBlock = GraphLayout::GraphBlock;
using GraphEdge = GraphLayout::GraphEdge;
2019-08-03 13:10:44 +00:00
enum class Layout {
GridNarrow
2019-09-19 05:19:50 +00:00
, GridMedium
, GridWide
2019-08-03 13:10:44 +00:00
#ifdef CUTTER_ENABLE_GRAPHVIZ
2019-09-19 05:19:50 +00:00
, GraphvizOrtho
, GraphvizOrthoLR
, GraphvizPolyline
, GraphvizPolylineLR
2019-08-03 13:10:44 +00:00
#endif
};
2018-03-21 20:32:32 +00:00
struct EdgeConfiguration {
QColor color = QColor(128, 128, 128);
bool start_arrow = false;
bool end_arrow = true;
qreal width_scale = 1.0;
Qt::PenStyle lineStyle = Qt::PenStyle::SolidLine;
};
explicit GraphView(QWidget *parent);
~GraphView() override;
2019-04-07 10:53:42 +00:00
void showBlock(GraphBlock &block, bool anywhere = false);
void showBlock(GraphBlock *block, bool anywhere = false);
/**
* @brief Move view so that area is visible.
* @param rect Rectangle to show
* @param anywhere - set to true for minimizing movement
*/
void showRectangle(const QRect &rect, bool anywhere = false);
/**
* @brief Get block containing specified point logical coordinates.
* @param p positionin graph logical coordinates
* @return Block or nullptr if position is outside all blocks.
*/
GraphView::GraphBlock *getBlockContaining(QPoint p);
QPoint viewToLogicalCoordinates(QPoint p);
2019-08-03 13:10:44 +00:00
void setGraphLayout(Layout layout);
Layout getGraphLayout() const { return graphLayout; }
2019-09-19 05:19:50 +00:00
void paint(QPainter &p, QPoint offset, QRect area, qreal scale = 1.0, bool interactive = true);
void saveAsBitmap(QString path, const char *format = nullptr);
void saveAsSvg(QString path);
protected:
std::unordered_map<ut64, GraphBlock> blocks;
QColor backgroundColor = QColor(Qt::white);
2017-12-14 21:07:48 +00:00
// Padding inside the block
int block_padding = 16;
void setCacheDirty() { cacheDirty = true; }
2017-12-14 21:07:48 +00:00
void addBlock(GraphView::GraphBlock block);
void setEntry(ut64 e);
void computeGraph(ut64 entry);
// Callbacks that should be overridden
2019-09-19 05:19:50 +00:00
/**
* @brief drawBlock
* @param p painter object, not necesarily current widget
* @param block
* @param interactive - can be used for disabling elemnts during export
*/
virtual void drawBlock(QPainter &p, GraphView::GraphBlock &block, bool interactive = true);
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);
virtual void blockHelpEvent(GraphView::GraphBlock &block, QHelpEvent *event, QPoint pos);
virtual bool helpEvent(QHelpEvent *event);
virtual void blockTransitionedTo(GraphView::GraphBlock *to);
virtual void wheelEvent(QWheelEvent *event) override;
2019-09-19 05:19:50 +00:00
virtual EdgeConfiguration edgeConfiguration(GraphView::GraphBlock &from, GraphView::GraphBlock *to,
bool interactive = true);
virtual void blockContextMenuRequested(GraphView::GraphBlock &block, QContextMenuEvent *event,
QPoint pos);
bool event(QEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
// Mouse events
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
void paintEvent(QPaintEvent *event) override;
int width = 0;
int height = 0;
bool scale_thickness_multiplier = false;
void clampViewOffset();
void setViewOffsetInternal(QPoint pos, bool emitSignal = true);
void addViewOffset(QPoint move, bool emitSignal = true);
private:
void centerX(bool emitSignal);
void centerY(bool emitSignal);
2019-04-07 10:53:42 +00:00
void paintGraphCache();
2018-03-21 20:32:32 +00:00
bool checkPointClicked(QPointF &point, int x, int y, bool above_y = false);
// Zoom data
qreal current_scale = 1.0;
QPoint offset = QPoint(0, 0);
ut64 entry;
std::unique_ptr<GraphLayout> graphLayoutSystem;
bool ready = false;
// Scrolling data
int scroll_base_x = 0;
int scroll_base_y = 0;
bool scroll_mode = false;
2019-04-07 10:53:42 +00:00
bool useGL;
/**
* @brief pixmap that caches the graph nodes
*/
QPixmap pixmap;
#ifndef CUTTER_NO_OPENGL_GRAPH
2019-04-07 10:53:42 +00:00
uint32_t cacheTexture;
uint32_t cacheFBO;
QSize cacheSize;
QOpenGLWidget *glWidget;
#endif
2019-08-03 13:10:44 +00:00
Layout graphLayout;
2019-04-07 10:53:42 +00:00
/**
* @brief flag to control if the cache is invalid and should be re-created in the next draw
*/
bool cacheDirty = true;
QSize getCacheSize();
qreal getCacheDevicePixelRatioF();
QSize getRequiredCacheSize();
qreal getRequiredCacheDevicePixelRatioF();
void beginMouseDrag(QMouseEvent *event);
public:
QPoint getViewOffset() const { return offset; }
void setViewOffset(QPoint offset);
qreal getViewScale() const { return current_scale; }
void setViewScale(qreal scale);
void center();
void centerX() { centerX(true); }
void centerY() { centerY(true); }
};
#endif // GRAPHVIEW_H