DataFlowGraphModel.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. #include "DataFlowGraphModel.hpp"
  2. #include "ConnectionIdHash.hpp"
  3. #include <QJsonArray>
  4. #include <stdexcept>
  5. namespace QtNodes {
  6. DataFlowGraphModel::DataFlowGraphModel(std::shared_ptr<NodeDelegateModelRegistry> registry)
  7. : _registry(std::move(registry)), _nextNodeId { 0 }
  8. {
  9. }
  10. std::unordered_set<NodeId> DataFlowGraphModel::allNodeIds() const
  11. {
  12. std::unordered_set<NodeId> nodeIds;
  13. for_each(_models.begin(), _models.end(), [&nodeIds](auto const &p) { nodeIds.insert(p.first); });
  14. return nodeIds;
  15. }
  16. std::unordered_set<ConnectionId> DataFlowGraphModel::allConnectionIds(NodeId const nodeId) const
  17. {
  18. std::unordered_set<ConnectionId> result;
  19. std::copy_if(_connectivity.begin(), _connectivity.end(), std::inserter(result, std::end(result)),
  20. [&nodeId](ConnectionId const &cid) { return cid.inNodeId == nodeId || cid.outNodeId == nodeId; });
  21. return result;
  22. }
  23. std::unordered_set<ConnectionId> DataFlowGraphModel::connections(NodeId nodeId, PortType portType,
  24. PortIndex portIndex) const
  25. {
  26. std::unordered_set<ConnectionId> result;
  27. std::copy_if(_connectivity.begin(), _connectivity.end(), std::inserter(result, std::end(result)),
  28. [&portType, &portIndex, &nodeId](ConnectionId const &cid) {
  29. return (getNodeId(portType, cid) == nodeId && getPortIndex(portType, cid) == portIndex);
  30. });
  31. return result;
  32. }
  33. bool DataFlowGraphModel::connectionExists(ConnectionId const connectionId) const
  34. {
  35. return (_connectivity.find(connectionId) != _connectivity.end());
  36. }
  37. NodeId DataFlowGraphModel::addNode(QString const nodeType)
  38. {
  39. std::unique_ptr<NodeDelegateModel> model = _registry->create(nodeType);
  40. if (model) {
  41. NodeId newId = newNodeId();
  42. connect(model.get(), &NodeDelegateModel::dataUpdated,
  43. [newId, this](PortIndex const portIndex) { onOutPortDataUpdated(newId, portIndex); });
  44. connect(model.get(), &NodeDelegateModel::portsAboutToBeDeleted, this,
  45. [newId, this](PortType const portType, PortIndex const first, PortIndex const last) {
  46. portsAboutToBeDeleted(newId, portType, first, last);
  47. });
  48. connect(model.get(), &NodeDelegateModel::portsDeleted, this, &DataFlowGraphModel::portsDeleted);
  49. connect(model.get(), &NodeDelegateModel::portsAboutToBeInserted, this,
  50. [newId, this](PortType const portType, PortIndex const first, PortIndex const last) {
  51. portsAboutToBeInserted(newId, portType, first, last);
  52. });
  53. connect(model.get(), &NodeDelegateModel::portsInserted, this, &DataFlowGraphModel::portsInserted);
  54. _models[newId] = std::move(model);
  55. Q_EMIT nodeCreated(newId);
  56. return newId;
  57. }
  58. return InvalidNodeId;
  59. }
  60. bool DataFlowGraphModel::connectionPossible(ConnectionId const connectionId) const
  61. {
  62. auto getDataType = [&](PortType const portType) {
  63. return portData(getNodeId(portType, connectionId), portType, getPortIndex(portType, connectionId),
  64. PortRole::DataType)
  65. .value<NodeDataType>();
  66. };
  67. auto portVacant = [&](PortType const portType) {
  68. NodeId const nodeId = getNodeId(portType, connectionId);
  69. PortIndex const portIndex = getPortIndex(portType, connectionId);
  70. auto const connected = connections(nodeId, portType, portIndex);
  71. auto policy = portData(nodeId, portType, portIndex, PortRole::ConnectionPolicyRole).value<ConnectionPolicy>();
  72. return connected.empty() || (policy == ConnectionPolicy::Many);
  73. };
  74. return getDataType(PortType::Out).id == getDataType(PortType::In).id && portVacant(PortType::Out)
  75. && portVacant(PortType::In);
  76. }
  77. void DataFlowGraphModel::addConnection(ConnectionId const connectionId)
  78. {
  79. _connectivity.insert(connectionId);
  80. sendConnectionCreation(connectionId);
  81. QVariant const portDataToPropagate =
  82. portData(connectionId.outNodeId, PortType::Out, connectionId.outPortIndex, PortRole::Data);
  83. setPortData(connectionId.inNodeId, PortType::In, connectionId.inPortIndex, portDataToPropagate, PortRole::Data);
  84. }
  85. void DataFlowGraphModel::sendConnectionCreation(ConnectionId const connectionId)
  86. {
  87. Q_EMIT connectionCreated(connectionId);
  88. auto iti = _models.find(connectionId.inNodeId);
  89. auto ito = _models.find(connectionId.outNodeId);
  90. if (iti != _models.end() && ito != _models.end()) {
  91. auto &modeli = iti->second;
  92. auto &modelo = ito->second;
  93. modeli->inputConnectionCreated(connectionId);
  94. modelo->outputConnectionCreated(connectionId);
  95. }
  96. }
  97. void DataFlowGraphModel::sendConnectionDeletion(ConnectionId const connectionId)
  98. {
  99. Q_EMIT connectionDeleted(connectionId);
  100. auto iti = _models.find(connectionId.inNodeId);
  101. auto ito = _models.find(connectionId.outNodeId);
  102. if (iti != _models.end() && ito != _models.end()) {
  103. auto &modeli = iti->second;
  104. auto &modelo = ito->second;
  105. modeli->inputConnectionDeleted(connectionId);
  106. modelo->outputConnectionDeleted(connectionId);
  107. }
  108. }
  109. bool DataFlowGraphModel::nodeExists(NodeId const nodeId) const
  110. {
  111. return (_models.find(nodeId) != _models.end());
  112. }
  113. QVariant DataFlowGraphModel::nodeData(NodeId nodeId, NodeRole role) const
  114. {
  115. QVariant result;
  116. auto it = _models.find(nodeId);
  117. if (it == _models.end())
  118. return result;
  119. auto &model = it->second;
  120. switch (role) {
  121. case NodeRole::Type:
  122. result = model->name();
  123. break;
  124. case NodeRole::Position:
  125. result = _nodeGeometryData[nodeId].pos;
  126. break;
  127. case NodeRole::Size:
  128. result = _nodeGeometryData[nodeId].size;
  129. break;
  130. case NodeRole::CaptionVisible:
  131. result = model->captionVisible();
  132. break;
  133. case NodeRole::Caption:
  134. // result = model->caption();
  135. result = _captionData[nodeId];
  136. break;
  137. case NodeRole::Style: {
  138. auto style = StyleCollection::nodeStyle();
  139. result = style.toJson().toVariantMap();
  140. } break;
  141. case NodeRole::InternalData: {
  142. QJsonObject nodeJson;
  143. nodeJson["internal-data"] = _models.at(nodeId)->save();
  144. result = nodeJson.toVariantMap();
  145. break;
  146. }
  147. case NodeRole::InPortCount:
  148. result = model->nPorts(PortType::In);
  149. // result = _inPorts[nodeId];
  150. break;
  151. case NodeRole::OutPortCount:
  152. result = model->nPorts(PortType::Out);
  153. // result = _outPorts[nodeId];
  154. break;
  155. case NodeRole::Widget: {
  156. // auto w = model->embeddedWidget();
  157. QWidget *w = _widgetData[nodeId];
  158. result = QVariant::fromValue(w);
  159. } break;
  160. }
  161. return result;
  162. }
  163. NodeFlags DataFlowGraphModel::nodeFlags(NodeId nodeId) const
  164. {
  165. auto it = _models.find(nodeId);
  166. if (it != _models.end() && it->second->resizable())
  167. return NodeFlag::Resizable;
  168. return NodeFlag::NoFlags;
  169. }
  170. bool DataFlowGraphModel::setNodeData(NodeId nodeId, NodeRole role, QVariant value)
  171. {
  172. Q_UNUSED(nodeId);
  173. Q_UNUSED(role);
  174. Q_UNUSED(value);
  175. bool result = false;
  176. switch (role) {
  177. case NodeRole::Type:
  178. break;
  179. case NodeRole::Position: {
  180. _nodeGeometryData[nodeId].pos = value.value<QPointF>();
  181. Q_EMIT nodePositionUpdated(nodeId);
  182. result = true;
  183. } break;
  184. case NodeRole::Size: {
  185. _nodeGeometryData[nodeId].size = value.value<QSize>();
  186. result = true;
  187. } break;
  188. case NodeRole::CaptionVisible:
  189. break;
  190. case NodeRole::Caption:
  191. _captionData[nodeId] = value.value<QString>();
  192. Q_EMIT nodeCreated(nodeId);
  193. result = true;
  194. break;
  195. case NodeRole::Style:
  196. break;
  197. case NodeRole::InternalData:
  198. break;
  199. case NodeRole::InPortCount:
  200. _inPorts[nodeId] = value.value<unsigned int>();
  201. Q_EMIT nodeCreated(nodeId);
  202. break;
  203. case NodeRole::OutPortCount:
  204. _outPorts[nodeId] = value.value<unsigned int>();
  205. Q_EMIT nodeCreated(nodeId);
  206. break;
  207. case NodeRole::Widget:
  208. _widgetData[nodeId] = value.value<QWidget *>();
  209. Q_EMIT nodeCreated(nodeId);
  210. return true;
  211. break;
  212. }
  213. return result;
  214. }
  215. QVariant DataFlowGraphModel::portData(NodeId nodeId, PortType portType, PortIndex portIndex, PortRole role) const
  216. {
  217. QVariant result;
  218. auto it = _models.find(nodeId);
  219. if (it == _models.end())
  220. return result;
  221. auto &model = it->second;
  222. switch (role) {
  223. case PortRole::Data:
  224. if (portType == PortType::Out)
  225. result = QVariant::fromValue(model->outData(portIndex));
  226. break;
  227. case PortRole::DataType:
  228. result = QVariant::fromValue(model->dataType(portType, portIndex));
  229. break;
  230. case PortRole::ConnectionPolicyRole:
  231. result = QVariant::fromValue(model->portConnectionPolicy(portType, portIndex));
  232. break;
  233. case PortRole::CaptionVisible:
  234. result = model->portCaptionVisible(portType, portIndex);
  235. break;
  236. case PortRole::Caption:
  237. result = model->portCaption(portType, portIndex);
  238. break;
  239. }
  240. return result;
  241. }
  242. bool DataFlowGraphModel::setPortData(NodeId nodeId, PortType portType, PortIndex portIndex, QVariant const &value,
  243. PortRole role)
  244. {
  245. Q_UNUSED(nodeId);
  246. QVariant result;
  247. auto it = _models.find(nodeId);
  248. if (it == _models.end())
  249. return false;
  250. auto &model = it->second;
  251. switch (role) {
  252. case PortRole::Data:
  253. if (portType == PortType::In) {
  254. model->setInData(value.value<std::shared_ptr<NodeData>>(), portIndex);
  255. // Triggers repainting on the scene.
  256. Q_EMIT inPortDataWasSet(nodeId, portType, portIndex);
  257. }
  258. break;
  259. default:
  260. break;
  261. }
  262. return false;
  263. }
  264. bool DataFlowGraphModel::deleteConnection(ConnectionId const connectionId)
  265. {
  266. bool disconnected = false;
  267. auto it = _connectivity.find(connectionId);
  268. if (it != _connectivity.end()) {
  269. disconnected = true;
  270. _connectivity.erase(it);
  271. }
  272. if (disconnected) {
  273. sendConnectionDeletion(connectionId);
  274. propagateEmptyDataTo(getNodeId(PortType::In, connectionId), getPortIndex(PortType::In, connectionId));
  275. }
  276. return disconnected;
  277. }
  278. bool DataFlowGraphModel::deleteNode(NodeId const nodeId)
  279. {
  280. // Delete connections to this node first.
  281. auto connectionIds = allConnectionIds(nodeId);
  282. for (auto &cId : connectionIds) {
  283. deleteConnection(cId);
  284. }
  285. _nodeGeometryData.erase(nodeId);
  286. _models.erase(nodeId);
  287. Q_EMIT nodeDeleted(nodeId);
  288. return true;
  289. }
  290. QJsonObject DataFlowGraphModel::saveNode(NodeId const nodeId) const
  291. {
  292. QJsonObject nodeJson;
  293. nodeJson["id"] = static_cast<qint64>(nodeId);
  294. nodeJson["internal-data"] = _models.at(nodeId)->save();
  295. {
  296. QPointF const pos = nodeData(nodeId, NodeRole::Position).value<QPointF>();
  297. QJsonObject posJson;
  298. posJson["x"] = pos.x();
  299. posJson["y"] = pos.y();
  300. nodeJson["position"] = posJson;
  301. }
  302. return nodeJson;
  303. }
  304. QJsonObject DataFlowGraphModel::save() const
  305. {
  306. QJsonObject sceneJson;
  307. QJsonArray nodesJsonArray;
  308. for (auto const nodeId : allNodeIds()) {
  309. nodesJsonArray.append(saveNode(nodeId));
  310. }
  311. sceneJson["nodes"] = nodesJsonArray;
  312. QJsonArray connJsonArray;
  313. for (auto const &cid : _connectivity) {
  314. connJsonArray.append(toJson(cid));
  315. }
  316. sceneJson["connections"] = connJsonArray;
  317. return sceneJson;
  318. }
  319. void DataFlowGraphModel::loadNode(QJsonObject const &nodeJson)
  320. {
  321. // Possibility of the id clash when reading it from json and not generating a
  322. // new value.
  323. // 1. When restoring a scene from a file.
  324. // Conflict is not possible because the scene must be cleared by the time of
  325. // loading.
  326. // 2. When undoing the deletion command. Conflict is not possible
  327. // because all the new ids were created past the removed nodes.
  328. NodeId restoredNodeId = nodeJson["id"].toInt();
  329. _nextNodeId = std::max(_nextNodeId, restoredNodeId + 1);
  330. QJsonObject const internalDataJson = nodeJson["internal-data"].toObject();
  331. QString delegateModelName = internalDataJson["model-name"].toString();
  332. std::unique_ptr<NodeDelegateModel> model = _registry->create(delegateModelName);
  333. if (model) {
  334. connect(model.get(), &NodeDelegateModel::dataUpdated,
  335. [restoredNodeId, this](PortIndex const portIndex) { onOutPortDataUpdated(restoredNodeId, portIndex); });
  336. _models[restoredNodeId] = std::move(model);
  337. Q_EMIT nodeCreated(restoredNodeId);
  338. QJsonObject posJson = nodeJson["position"].toObject();
  339. QPointF const pos(posJson["x"].toDouble(), posJson["y"].toDouble());
  340. setNodeData(restoredNodeId, NodeRole::Position, pos);
  341. _models[restoredNodeId]->load(internalDataJson);
  342. } else {
  343. throw std::logic_error(std::string("No registered model with name ") + delegateModelName.toLocal8Bit().data());
  344. }
  345. }
  346. void DataFlowGraphModel::load(QJsonObject const &jsonDocument)
  347. {
  348. QJsonArray nodesJsonArray = jsonDocument["nodes"].toArray();
  349. for (QJsonValueRef nodeJson : nodesJsonArray) {
  350. loadNode(nodeJson.toObject());
  351. }
  352. QJsonArray connectionJsonArray = jsonDocument["connections"].toArray();
  353. for (QJsonValueRef connection : connectionJsonArray) {
  354. QJsonObject connJson = connection.toObject();
  355. ConnectionId connId = fromJson(connJson);
  356. // Restore the connection
  357. addConnection(connId);
  358. }
  359. }
  360. void DataFlowGraphModel::onOutPortDataUpdated(NodeId const nodeId, PortIndex const portIndex)
  361. {
  362. std::unordered_set<ConnectionId> const &connected = connections(nodeId, PortType::Out, portIndex);
  363. QVariant const portDataToPropagate = portData(nodeId, PortType::Out, portIndex, PortRole::Data);
  364. for (auto const &cn : connected) {
  365. setPortData(cn.inNodeId, PortType::In, cn.inPortIndex, portDataToPropagate, PortRole::Data);
  366. }
  367. }
  368. void DataFlowGraphModel::propagateEmptyDataTo(NodeId const nodeId, PortIndex const portIndex)
  369. {
  370. QVariant emptyData {};
  371. setPortData(nodeId, PortType::In, portIndex, emptyData, PortRole::Data);
  372. }
  373. } // namespace QtNodes