DiagramDesigner/include/basicGraphicsScene.h

169 lines
4.8 KiB
C
Raw Normal View History

2024-12-03 20:07:25 +08:00
#pragma once
#include <QtCore/QUuid>
#include <QtWidgets/QGraphicsScene>
#include <QtWidgets/QMenu>
#include "abstractGraphModel.h"
#include "abstractNodeGeometry.h"
#include "global.h"
class QUndoStack;
class AbstractGraphModel;
class AbstractNodePainter;
class ConnectionGraphicsObject;
class NodeGraphicsObject;
class NodeStyle;
/// An instance of QGraphicsScene, holds connections and nodes.
class BasicGraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
BasicGraphicsScene(AbstractGraphModel &graphModel, QObject *parent = nullptr);
// Scenes without models are not supported
BasicGraphicsScene() = delete;
~BasicGraphicsScene();
public:
/// @returns associated AbstractGraphModel.
AbstractGraphModel const &graphModel() const;
AbstractGraphModel &graphModel();
AbstractNodeGeometry &nodeGeometry();
AbstractNodePainter &nodePainter();
void setNodePainter(QSharedPointer<AbstractNodePainter> newPainter);
QUndoStack &undoStack();
public:
/// Creates a "draft" instance of ConnectionGraphicsObject.
/**
* The scene caches a "draft" connection which has one loose end.
* After attachment the "draft" instance is deleted and instead a
* normal "full" connection is created.
* Function @returns the "draft" instance for further geometry
* manipulations.
*/
QSharedPointer<ConnectionGraphicsObject> const &makeDraftConnection(
ConnectionId const newConnectionId);
/// Deletes "draft" connection.
/**
* The function is called when user releases the mouse button during
* the construction of the new connection without attaching it to any
* node.
*/
void resetDraftConnection();
/// Deletes all the nodes. Connections are removed automatically.
void clearScene();
public:
/// @returns NodeGraphicsObject associated with the given nodeId.
/**
* @returns nullptr when the object is not found.
*/
NodeGraphicsObject *nodeGraphicsObject(NodeId nodeId);
/// @returns ConnectionGraphicsObject corresponding to `connectionId`.
/**
* @returns `nullptr` when the object is not found.
*/
ConnectionGraphicsObject *connectionGraphicsObject(ConnectionId connectionId);
Qt::Orientation orientation() const { return _orientation; }
void setOrientation(Qt::Orientation const orientation);
public:
/// Can @return an instance of the scene context menu in subclass.
/**
* Default implementation returns `nullptr`.
*/
virtual QMenu *createSceneMenu(QPointF const scenePos);
Q_SIGNALS:
void modified(BasicGraphicsScene *);
void nodeMoved(NodeId const nodeId, QPointF const &newLocation);
void nodeClicked(NodeId const nodeId);
void nodeSelected(NodeId const nodeId);
void nodeDoubleClicked(NodeId const nodeId);
void nodeHovered(NodeId const nodeId, QPoint const screenPos);
void nodeHoverLeft(NodeId const nodeId);
void connectionHovered(ConnectionId const connectionId, QPoint const screenPos);
void connectionHoverLeft(ConnectionId const connectionId);
/// Signal allows showing custom context menu upon clicking a node.
void nodeContextMenu(NodeId const nodeId, QPointF const pos);
private:
/// @brief Creates Node and Connection graphics objects.
/**
* Function is used to populate an empty scene in the constructor. We
* perform depth-first AbstractGraphModel traversal. The connections are
* created by checking non-empty node `Out` ports.
*/
void traverseGraphAndPopulateGraphicsObjects();
/// Redraws adjacent nodes for given `connectionId`
void updateAttachedNodes(ConnectionId const connectionId, PortType const portType);
public Q_SLOTS:
/// Slot called when the `connectionId` is erased form the AbstractGraphModel.
void onConnectionDeleted(ConnectionId const connectionId);
/// Slot called when the `connectionId` is created in the AbstractGraphModel.
void onConnectionCreated(ConnectionId const connectionId);
void onNodeDeleted(NodeId const nodeId);
void onNodeCreated(NodeId const nodeId);
void onNodePositionUpdated(NodeId const nodeId);
void onNodeUpdated(NodeId const nodeId);
void onNodeClicked(NodeId const nodeId);
void onModelReset();
private:
AbstractGraphModel &_graphModel;
using UniqueNodeGraphicsObject = QSharedPointer<NodeGraphicsObject>;
using UniqueConnectionGraphicsObject = QSharedPointer<ConnectionGraphicsObject>;
QMap<NodeId, UniqueNodeGraphicsObject> _nodeGraphicsObjects;
QMap<ConnectionId, UniqueConnectionGraphicsObject> _connectionGraphicsObjects;
QSharedPointer<ConnectionGraphicsObject> _draftConnection;
QSharedPointer<AbstractNodeGeometry> _nodeGeometry;
QSharedPointer<AbstractNodePainter> _nodePainter;
bool _nodeDrag;
QUndoStack *_undoStack;
Qt::Orientation _orientation;
};