BasicGraphicsScene.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #pragma once
  2. #include <QtCore/QUuid>
  3. #include <QtWidgets/QGraphicsScene>
  4. #include <QtWidgets/QMenu>
  5. #include <functional>
  6. #include <memory>
  7. #include <tuple>
  8. #include <unordered_map>
  9. #include "AbstractGraphModel.hpp"
  10. #include "AbstractNodeGeometry.hpp"
  11. #include "ConnectionIdHash.hpp"
  12. #include "Definitions.hpp"
  13. #include "Export.hpp"
  14. #include "QUuidStdHash.hpp"
  15. class QUndoStack;
  16. namespace QtNodes {
  17. class AbstractGraphModel;
  18. class AbstractNodePainter;
  19. class ConnectionGraphicsObject;
  20. class NodeGraphicsObject;
  21. class NodeStyle;
  22. /// An instance of QGraphicsScene, holds connections and nodes.
  23. class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene
  24. {
  25. Q_OBJECT
  26. public:
  27. BasicGraphicsScene(AbstractGraphModel &graphModel, QObject *parent = nullptr);
  28. // Scenes without models are not supported
  29. BasicGraphicsScene() = delete;
  30. ~BasicGraphicsScene();
  31. public:
  32. /// @returns associated AbstractGraphModel.
  33. AbstractGraphModel const &graphModel() const;
  34. AbstractGraphModel &graphModel();
  35. AbstractNodeGeometry &nodeGeometry();
  36. AbstractNodePainter &nodePainter();
  37. void setNodePainter(std::unique_ptr<AbstractNodePainter> newPainter);
  38. QUndoStack &undoStack();
  39. public:
  40. /// Creates a "draft" instance of ConnectionGraphicsObject.
  41. /**
  42. * The scene caches a "draft" connection which has one loose end.
  43. * After attachment the "draft" instance is deleted and instead a
  44. * normal "full" connection is created.
  45. * Function @returns the "draft" instance for further geometry
  46. * manipulations.
  47. */
  48. std::unique_ptr<ConnectionGraphicsObject> const &makeDraftConnection(
  49. ConnectionId const newConnectionId);
  50. /// Deletes "draft" connection.
  51. /**
  52. * The function is called when user releases the mouse button during
  53. * the construction of the new connection without attaching it to any
  54. * node.
  55. */
  56. void resetDraftConnection();
  57. /// Deletes all the nodes. Connections are removed automatically.
  58. void clearScene();
  59. public:
  60. /// @returns NodeGraphicsObject associated with the given nodeId.
  61. /**
  62. * @returns nullptr when the object is not found.
  63. */
  64. NodeGraphicsObject *nodeGraphicsObject(NodeId nodeId);
  65. /// @returns ConnectionGraphicsObject corresponding to `connectionId`.
  66. /**
  67. * @returns `nullptr` when the object is not found.
  68. */
  69. ConnectionGraphicsObject *connectionGraphicsObject(ConnectionId connectionId);
  70. Qt::Orientation orientation() const { return _orientation; }
  71. void setOrientation(Qt::Orientation const orientation);
  72. public:
  73. /// Can @return an instance of the scene context menu in subclass.
  74. /**
  75. * Default implementation returns `nullptr`.
  76. */
  77. virtual QMenu *createSceneMenu(QPointF const scenePos);
  78. Q_SIGNALS:
  79. void nodeMoved(NodeId const nodeId, QPointF const &newLocation);
  80. void nodeClicked(NodeId const nodeId);
  81. void nodeSelected(NodeId const nodeId);
  82. void nodeDoubleClicked(NodeId const nodeId);
  83. void nodeHovered(NodeId const nodeId, QPoint const screenPos);
  84. void nodeHoverLeft(NodeId const nodeId);
  85. void connectionHovered(ConnectionId const connectionId, QPoint const screenPos);
  86. void connectionHoverLeft(ConnectionId const connectionId);
  87. /// Signal allows showing custom context menu upon clicking a node.
  88. void nodeContextMenu(NodeId const nodeId, QPointF const pos);
  89. private:
  90. /// @brief Creates Node and Connection graphics objects.
  91. /**
  92. * Function is used to populate an empty scene in the constructor. We
  93. * perform depth-first AbstractGraphModel traversal. The connections are
  94. * created by checking non-empty node `Out` ports.
  95. */
  96. void traverseGraphAndPopulateGraphicsObjects();
  97. /// Redraws adjacent nodes for given `connectionId`
  98. void updateAttachedNodes(ConnectionId const connectionId, PortType const portType);
  99. public Q_SLOTS:
  100. /// Slot called when the `connectionId` is erased form the AbstractGraphModel.
  101. void onConnectionDeleted(ConnectionId const connectionId);
  102. /// Slot called when the `connectionId` is created in the AbstractGraphModel.
  103. void onConnectionCreated(ConnectionId const connectionId);
  104. void onNodeDeleted(NodeId const nodeId);
  105. void onNodeCreated(NodeId const nodeId);
  106. void onNodePositionUpdated(NodeId const nodeId);
  107. void onNodeUpdated(NodeId const nodeId);
  108. void onNodeClicked(NodeId const nodeId);
  109. void onModelReset();
  110. private:
  111. AbstractGraphModel &_graphModel;
  112. using UniqueNodeGraphicsObject = std::unique_ptr<NodeGraphicsObject>;
  113. using UniqueConnectionGraphicsObject = std::unique_ptr<ConnectionGraphicsObject>;
  114. std::unordered_map<NodeId, UniqueNodeGraphicsObject> _nodeGraphicsObjects;
  115. std::unordered_map<ConnectionId, UniqueConnectionGraphicsObject> _connectionGraphicsObjects;
  116. std::unique_ptr<ConnectionGraphicsObject> _draftConnection;
  117. std::unique_ptr<AbstractNodeGeometry> _nodeGeometry;
  118. std::unique_ptr<AbstractNodePainter> _nodePainter;
  119. bool _nodeDrag;
  120. QUndoStack *_undoStack;
  121. Qt::Orientation _orientation;
  122. };
  123. } // namespace QtNodes