BasicGraphicsScene.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include "BasicGraphicsScene.hpp"
  2. #include "AbstractNodeGeometry.hpp"
  3. #include "ConnectionGraphicsObject.hpp"
  4. #include "ConnectionIdUtils.hpp"
  5. #include "DefaultHorizontalNodeGeometry.hpp"
  6. #include "DefaultNodePainter.hpp"
  7. #include "DefaultVerticalNodeGeometry.hpp"
  8. #include "GraphicsView.hpp"
  9. #include "NodeGraphicsObject.hpp"
  10. #include <QUndoStack>
  11. #include <QtWidgets/QFileDialog>
  12. #include <QtWidgets/QGraphicsSceneMoveEvent>
  13. #include <QtCore/QBuffer>
  14. #include <QtCore/QByteArray>
  15. #include <QtCore/QDataStream>
  16. #include <QtCore/QFile>
  17. #include <QtCore/QJsonArray>
  18. #include <QtCore/QJsonDocument>
  19. #include <QtCore/QJsonObject>
  20. #include <QtCore/QtGlobal>
  21. #include <iostream>
  22. #include <stdexcept>
  23. #include <unordered_set>
  24. #include <utility>
  25. #include <queue>
  26. namespace QtNodes {
  27. BasicGraphicsScene::BasicGraphicsScene(AbstractGraphModel &graphModel, QObject *parent)
  28. : QGraphicsScene(parent)
  29. , _graphModel(graphModel)
  30. , _nodeGeometry(std::make_unique<DefaultHorizontalNodeGeometry>(_graphModel))
  31. , _nodePainter(std::make_unique<DefaultNodePainter>())
  32. , _nodeDrag(false)
  33. , _undoStack(new QUndoStack(this))
  34. , _orientation(Qt::Horizontal)
  35. {
  36. setItemIndexMethod(QGraphicsScene::NoIndex);
  37. connect(&_graphModel,
  38. &AbstractGraphModel::connectionCreated,
  39. this,
  40. &BasicGraphicsScene::onConnectionCreated);
  41. connect(&_graphModel,
  42. &AbstractGraphModel::connectionDeleted,
  43. this,
  44. &BasicGraphicsScene::onConnectionDeleted);
  45. connect(&_graphModel,
  46. &AbstractGraphModel::nodeCreated,
  47. this,
  48. &BasicGraphicsScene::onNodeCreated);
  49. connect(&_graphModel,
  50. &AbstractGraphModel::nodeDeleted,
  51. this,
  52. &BasicGraphicsScene::onNodeDeleted);
  53. connect(&_graphModel,
  54. &AbstractGraphModel::nodePositionUpdated,
  55. this,
  56. &BasicGraphicsScene::onNodePositionUpdated);
  57. connect(&_graphModel,
  58. &AbstractGraphModel::nodeUpdated,
  59. this,
  60. &BasicGraphicsScene::onNodeUpdated);
  61. connect(this, &BasicGraphicsScene::nodeClicked, this, &BasicGraphicsScene::onNodeClicked);
  62. connect(&_graphModel, &AbstractGraphModel::modelReset, this, &BasicGraphicsScene::onModelReset);
  63. traverseGraphAndPopulateGraphicsObjects();
  64. }
  65. BasicGraphicsScene::~BasicGraphicsScene() = default;
  66. AbstractGraphModel const &BasicGraphicsScene::graphModel() const
  67. {
  68. return _graphModel;
  69. }
  70. AbstractGraphModel &BasicGraphicsScene::graphModel()
  71. {
  72. return _graphModel;
  73. }
  74. AbstractNodeGeometry &BasicGraphicsScene::nodeGeometry()
  75. {
  76. return *_nodeGeometry;
  77. }
  78. AbstractNodePainter &BasicGraphicsScene::nodePainter()
  79. {
  80. return *_nodePainter;
  81. }
  82. void BasicGraphicsScene::setNodePainter(std::unique_ptr<AbstractNodePainter> newPainter)
  83. {
  84. _nodePainter = std::move(newPainter);
  85. }
  86. QUndoStack &BasicGraphicsScene::undoStack()
  87. {
  88. return *_undoStack;
  89. }
  90. std::unique_ptr<ConnectionGraphicsObject> const &BasicGraphicsScene::makeDraftConnection(
  91. ConnectionId const incompleteConnectionId)
  92. {
  93. _draftConnection = std::make_unique<ConnectionGraphicsObject>(*this, incompleteConnectionId);
  94. _draftConnection->grabMouse();
  95. return _draftConnection;
  96. }
  97. void BasicGraphicsScene::resetDraftConnection()
  98. {
  99. _draftConnection.reset();
  100. }
  101. void BasicGraphicsScene::clearScene()
  102. {
  103. auto const &allNodeIds = graphModel().allNodeIds();
  104. for (auto nodeId : allNodeIds) {
  105. graphModel().deleteNode(nodeId);
  106. }
  107. }
  108. NodeGraphicsObject *BasicGraphicsScene::nodeGraphicsObject(NodeId nodeId)
  109. {
  110. NodeGraphicsObject *ngo = nullptr;
  111. auto it = _nodeGraphicsObjects.find(nodeId);
  112. if (it != _nodeGraphicsObjects.end()) {
  113. ngo = it->second.get();
  114. }
  115. return ngo;
  116. }
  117. ConnectionGraphicsObject *BasicGraphicsScene::connectionGraphicsObject(ConnectionId connectionId)
  118. {
  119. ConnectionGraphicsObject *cgo = nullptr;
  120. auto it = _connectionGraphicsObjects.find(connectionId);
  121. if (it != _connectionGraphicsObjects.end()) {
  122. cgo = it->second.get();
  123. }
  124. return cgo;
  125. }
  126. void BasicGraphicsScene::setOrientation(Qt::Orientation const orientation)
  127. {
  128. if (_orientation != orientation) {
  129. _orientation = orientation;
  130. switch (_orientation) {
  131. case Qt::Horizontal:
  132. _nodeGeometry = std::make_unique<DefaultHorizontalNodeGeometry>(_graphModel);
  133. break;
  134. case Qt::Vertical:
  135. _nodeGeometry = std::make_unique<DefaultVerticalNodeGeometry>(_graphModel);
  136. break;
  137. }
  138. onModelReset();
  139. }
  140. }
  141. QMenu *BasicGraphicsScene::createSceneMenu(QPointF const scenePos)
  142. {
  143. Q_UNUSED(scenePos);
  144. return nullptr;
  145. }
  146. void BasicGraphicsScene::traverseGraphAndPopulateGraphicsObjects()
  147. {
  148. auto allNodeIds = _graphModel.allNodeIds();
  149. // First create all the nodes.
  150. for (NodeId const nodeId : allNodeIds) {
  151. _nodeGraphicsObjects[nodeId] = std::make_unique<NodeGraphicsObject>(*this, nodeId);
  152. }
  153. // Then for each node check output connections and insert them.
  154. for (NodeId const nodeId : allNodeIds) {
  155. unsigned int nOutPorts = _graphModel.nodeData<PortCount>(nodeId, NodeRole::OutPortCount);
  156. for (PortIndex index = 0; index < nOutPorts; ++index) {
  157. auto const &outConnectionIds = _graphModel.connections(nodeId, PortType::Out, index);
  158. for (auto cid : outConnectionIds) {
  159. _connectionGraphicsObjects[cid] = std::make_unique<ConnectionGraphicsObject>(*this,
  160. cid);
  161. }
  162. }
  163. }
  164. }
  165. void BasicGraphicsScene::updateAttachedNodes(ConnectionId const connectionId,
  166. PortType const portType)
  167. {
  168. auto node = nodeGraphicsObject(getNodeId(portType, connectionId));
  169. if (node) {
  170. node->update();
  171. }
  172. }
  173. void BasicGraphicsScene::onConnectionDeleted(ConnectionId const connectionId)
  174. {
  175. auto it = _connectionGraphicsObjects.find(connectionId);
  176. if (it != _connectionGraphicsObjects.end()) {
  177. _connectionGraphicsObjects.erase(it);
  178. }
  179. // TODO: do we need it?
  180. if (_draftConnection && _draftConnection->connectionId() == connectionId) {
  181. _draftConnection.reset();
  182. }
  183. updateAttachedNodes(connectionId, PortType::Out);
  184. updateAttachedNodes(connectionId, PortType::In);
  185. }
  186. void BasicGraphicsScene::onConnectionCreated(ConnectionId const connectionId)
  187. {
  188. _connectionGraphicsObjects[connectionId]
  189. = std::make_unique<ConnectionGraphicsObject>(*this, connectionId);
  190. updateAttachedNodes(connectionId, PortType::Out);
  191. updateAttachedNodes(connectionId, PortType::In);
  192. }
  193. void BasicGraphicsScene::onNodeDeleted(NodeId const nodeId)
  194. {
  195. auto it = _nodeGraphicsObjects.find(nodeId);
  196. if (it != _nodeGraphicsObjects.end()) {
  197. _nodeGraphicsObjects.erase(it);
  198. }
  199. }
  200. void BasicGraphicsScene::onNodeCreated(NodeId const nodeId)
  201. {
  202. _nodeGraphicsObjects[nodeId] = std::make_unique<NodeGraphicsObject>(*this, nodeId);
  203. }
  204. void BasicGraphicsScene::onNodePositionUpdated(NodeId const nodeId)
  205. {
  206. auto node = nodeGraphicsObject(nodeId);
  207. if (node) {
  208. node->setPos(_graphModel.nodeData(nodeId, NodeRole::Position).value<QPointF>());
  209. node->update();
  210. _nodeDrag = true;
  211. }
  212. }
  213. void BasicGraphicsScene::onNodeUpdated(NodeId const nodeId)
  214. {
  215. auto node = nodeGraphicsObject(nodeId);
  216. if (node) {
  217. node->setGeometryChanged();
  218. _nodeGeometry->recomputeSize(nodeId);
  219. node->update();
  220. node->moveConnections();
  221. }
  222. }
  223. void BasicGraphicsScene::onNodeClicked(NodeId const nodeId)
  224. {
  225. if (_nodeDrag)
  226. Q_EMIT nodeMoved(nodeId, _graphModel.nodeData(nodeId, NodeRole::Position).value<QPointF>());
  227. _nodeDrag = false;
  228. }
  229. void BasicGraphicsScene::onModelReset()
  230. {
  231. _connectionGraphicsObjects.clear();
  232. _nodeGraphicsObjects.clear();
  233. clear();
  234. traverseGraphAndPopulateGraphicsObjects();
  235. }
  236. } // namespace QtNodes