Skip to content

Commit 6f9897e

Browse files
committed
add necessary features to loading schema
1 parent bcb0b35 commit 6f9897e

3 files changed

Lines changed: 203 additions & 19 deletions

File tree

include/QtNodes/internal/BasicGraphicsScene.hpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene
138138
* between old and new nodes.
139139
*/
140140
std::pair<std::weak_ptr<NodeGroup>, std::unordered_map<GroupId, GroupId>> restoreGroup(
141-
QJsonObject const &groupJson);
141+
QJsonObject const &groupJson, QHash<NodeId, QJsonObject> const &nodeById);
142142

143143
/**
144144
* @brief Returns a const reference to the mapping of existing groups.
@@ -182,6 +182,51 @@ class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene
182182
*/
183183
void removeNodeFromGroup(NodeId nodeId);
184184

185+
std::unordered_map<QUuid, QUuid> loadItems(const QByteArray &data,
186+
QPointF pastePos,
187+
bool usePastePos = true);
188+
189+
std::unordered_map<QUuid, QUuid> loadFromMemory(const QByteArray &data);
190+
191+
QUuid encodeNodeId(NodeId nodeId)
192+
{
193+
QByteArray bytes(16, 0);
194+
QDataStream stream(&bytes, QIODevice::WriteOnly);
195+
stream << static_cast<quint32>(nodeId);
196+
return QUuid::fromRfc4122(bytes);
197+
}
198+
199+
NodeId decodeNodeUuid(QUuid const &uuid)
200+
{
201+
auto bytes = uuid.toRfc4122();
202+
if (bytes.size() < static_cast<int>(sizeof(quint32)))
203+
return QtNodes::InvalidNodeId;
204+
205+
QDataStream stream(bytes);
206+
quint32 value = 0;
207+
stream >> value;
208+
return static_cast<NodeId>(value);
209+
}
210+
211+
std::unordered_map<NodeId, NodeId> convertMap(std::unordered_map<QUuid, QUuid> const &uuidMap)
212+
{
213+
std::unordered_map<NodeId, NodeId> idMap;
214+
215+
// Iterando pelo mapa de QUuids e convertendo para NodeIds
216+
for (const auto &pair : uuidMap) {
217+
// Decodificando os QUuids para NodeIds
218+
NodeId keyNodeId = decodeNodeUuid(pair.first);
219+
NodeId valueNodeId = decodeNodeUuid(pair.second);
220+
221+
// Inserindo no novo mapa
222+
if (keyNodeId != QtNodes::InvalidNodeId && valueNodeId != QtNodes::InvalidNodeId) {
223+
idMap[keyNodeId] = valueNodeId;
224+
}
225+
}
226+
227+
return idMap;
228+
}
229+
185230
public:
186231
/**
187232
* @returns NodeGraphicsObject associated with the given nodeId.

include/QtNodes/internal/GraphicsView.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class NODE_EDITOR_PUBLIC GraphicsView : public QGraphicsView
4646

4747
double getScale() const;
4848

49+
BasicGraphicsScene *getNodeScene() { return nodeScene(); }
50+
4951
public Q_SLOTS:
5052
void scaleUp();
5153

src/BasicGraphicsScene.cpp

Lines changed: 155 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,109 @@ void BasicGraphicsScene::removeNodeFromGroup(NodeId nodeId)
578578
nodeIt->second->lock(false);
579579
}
580580

581+
std::unordered_map<QUuid, QUuid> BasicGraphicsScene::loadItems(const QByteArray &data,
582+
QPointF pastePos,
583+
bool usePastePos)
584+
{
585+
QJsonObject const jsonDocument = QJsonDocument::fromJson(data).object();
586+
587+
std::unordered_map<QUuid, QUuid> IDMap{};
588+
589+
QPointF offset;
590+
bool offsetInitialized{false};
591+
clearSelection();
592+
593+
QJsonArray nodesJsonArray = jsonDocument.value("nodes").toArray();
594+
QHash<NodeId, QJsonObject> nodeById;
595+
nodeById.reserve(nodesJsonArray.size());
596+
for (const QJsonValue &v : nodesJsonArray) {
597+
QJsonObject o = v.toObject();
598+
NodeId id = static_cast<NodeId>(o.value("id").toInt(InvalidNodeId));
599+
if (id != InvalidNodeId)
600+
nodeById.insert(id, o);
601+
}
602+
603+
QSet<NodeId> createdOldNodeIds;
604+
605+
QJsonArray groupsJsonArray = jsonDocument.value("groups").toArray();
606+
for (const QJsonValue &groupVal : groupsJsonArray) {
607+
auto [groupWeakPtr, groupIDsMap] = restoreGroup(groupVal.toObject(), nodeById);
608+
609+
for (const auto &[oldGroupId, newGroupId] : groupIDsMap) {
610+
NodeId oldNodeId = static_cast<NodeId>(oldGroupId);
611+
NodeId newNodeId = static_cast<NodeId>(newGroupId);
612+
613+
createdOldNodeIds.insert(oldNodeId);
614+
615+
QUuid oldUuid = encodeNodeId(oldNodeId);
616+
QUuid newUuid = encodeNodeId(newNodeId);
617+
IDMap[oldUuid] = newUuid;
618+
}
619+
620+
if (auto groupPtr = groupWeakPtr.lock(); groupPtr) {
621+
auto &ggoRef = groupPtr->groupGraphicsObject();
622+
623+
if (usePastePos && !offsetInitialized) {
624+
offset = pastePos - ggoRef.pos();
625+
offsetInitialized = true;
626+
}
627+
if (usePastePos) {
628+
ggoRef.moveNodes(offset);
629+
}
630+
ggoRef.moveConnections();
631+
ggoRef.setSelected(true);
632+
}
633+
}
634+
635+
for (QJsonValueRef node : nodesJsonArray) {
636+
QJsonObject nodeObj = node.toObject();
637+
NodeId oldNodeId = static_cast<NodeId>(nodeObj.value("id").toInt(InvalidNodeId));
638+
639+
if (createdOldNodeIds.contains(oldNodeId)) {
640+
continue;
641+
}
642+
643+
auto &nodeRef = loadNodeToMap(nodeObj, false);
644+
645+
NodeId newNodeId = nodeRef.nodeId();
646+
QUuid oldId = encodeNodeId(oldNodeId);
647+
QUuid newId = encodeNodeId(newNodeId);
648+
IDMap.insert(std::make_pair(oldId, newId));
649+
650+
if (usePastePos && !offsetInitialized) {
651+
offset = pastePos - nodeRef.pos();
652+
offsetInitialized = true;
653+
}
654+
if (usePastePos) {
655+
nodeRef.moveBy(offset.x(), offset.y());
656+
}
657+
nodeRef.moveConnections();
658+
nodeRef.setSelected(true);
659+
}
660+
661+
QJsonArray connectionJsonArray = jsonDocument.value("connections").toArray();
662+
for (QJsonValueRef connection : connectionJsonArray) {
663+
auto nodeIdMap = convertMap(IDMap);
664+
loadConnectionToMap(connection.toObject(), nodeIdMap);
665+
666+
ConnectionId connId = fromJson(connection.toObject());
667+
auto it = _connectionGraphicsObjects.find(connId);
668+
if (it != _connectionGraphicsObjects.end()) {
669+
UniqueConnectionGraphicsObject &obj = it->second;
670+
obj->setSelected(true);
671+
}
672+
}
673+
674+
return IDMap;
675+
}
676+
677+
std::unordered_map<QUuid, QUuid> BasicGraphicsScene::loadFromMemory(const QByteArray &data)
678+
{
679+
std::unordered_map<QUuid, QUuid> map = loadItems(data, QPointF(), false);
680+
clearSelection();
681+
return map;
682+
}
683+
581684
std::weak_ptr<QtNodes::NodeGroup> BasicGraphicsScene::createGroupFromSelection(QString groupName)
582685
{
583686
if (!_groupingEnabled)
@@ -636,25 +739,48 @@ void BasicGraphicsScene::loadConnectionToMap(QJsonObject const &connectionJson,
636739
}
637740

638741
std::pair<std::weak_ptr<NodeGroup>, std::unordered_map<GroupId, GroupId>>
639-
BasicGraphicsScene::restoreGroup(QJsonObject const &groupJson)
742+
BasicGraphicsScene::restoreGroup(QJsonObject const &groupJson,
743+
QHash<NodeId, QJsonObject> const &nodeById)
744+
640745
{
641746
if (!_groupingEnabled)
642747
return {std::weak_ptr<NodeGroup>(), {}};
643748

644-
// since the new nodes will have the same IDs as in the file and the connections
645-
// need these old IDs to be restored, we must create new IDs and map them to the
646-
// old ones so the connections are properly restored
647749
std::unordered_map<GroupId, GroupId> IDsMap{};
648750
std::unordered_map<NodeId, NodeId> nodeIdMap{};
649-
650751
std::vector<NodeGraphicsObject *> group_children{};
651752

652-
QJsonArray nodesJson = groupJson["nodes"].toArray();
653-
for (const QJsonValueRef nodeJson : nodesJson) {
654-
QJsonObject nodeObject = nodeJson.toObject();
655-
NodeId const oldNodeId = jsonValueToNodeId(nodeObject["id"]);
753+
QJsonArray nodesJson = groupJson.value("nodes").toArray();
754+
for (QJsonValue const &nodeVal : nodesJson) {
755+
QJsonObject nodeObject;
756+
757+
if (nodeVal.isDouble()) {
758+
NodeId const oldNodeId = static_cast<NodeId>(nodeVal.toInt(InvalidNodeId));
759+
if (oldNodeId == InvalidNodeId) {
760+
qWarning() << "restoreGroup(): invalid node id in group:" << nodeVal;
761+
continue;
762+
}
763+
764+
auto it = nodeById.find(oldNodeId);
765+
if (it == nodeById.end()) {
766+
qWarning() << "restoreGroup(): group references missing node id:" << oldNodeId;
767+
continue;
768+
}
769+
770+
nodeObject = it.value();
771+
}
772+
773+
else if (nodeVal.isObject()) {
774+
nodeObject = nodeVal.toObject();
775+
} else {
776+
qWarning() << "restoreGroup(): unexpected node entry type:" << nodeVal;
777+
continue;
778+
}
779+
780+
NodeId const oldNodeId = jsonValueToNodeId(nodeObject.value("id"));
781+
782+
NodeGraphicsObject &nodeRef = loadNodeToMap(nodeObject, /*keepOriginalId=*/false);
656783

657-
NodeGraphicsObject &nodeRef = loadNodeToMap(nodeObject, false);
658784
NodeId const newNodeId = nodeRef.nodeId();
659785

660786
if (oldNodeId != InvalidNodeId) {
@@ -665,12 +791,12 @@ BasicGraphicsScene::restoreGroup(QJsonObject const &groupJson)
665791
group_children.push_back(&nodeRef);
666792
}
667793

668-
QJsonArray connectionJsonArray = groupJson["connections"].toArray();
669-
for (auto connection : connectionJsonArray) {
670-
loadConnectionToMap(connection.toObject(), nodeIdMap);
794+
QJsonArray connectionJsonArray = groupJson.value("connections").toArray();
795+
for (QJsonValue const &connectionVal : connectionJsonArray) {
796+
loadConnectionToMap(connectionVal.toObject(), nodeIdMap);
671797
}
672798

673-
return std::make_pair(createGroup(group_children, groupJson["name"].toString()), IDsMap);
799+
return std::make_pair(createGroup(group_children, groupJson.value("name").toString()), IDsMap);
674800
}
675801

676802
std::unordered_map<GroupId, std::shared_ptr<NodeGroup>> const &BasicGraphicsScene::groups() const
@@ -802,17 +928,28 @@ std::weak_ptr<NodeGroup> BasicGraphicsScene::loadGroupFile()
802928

803929
if (!file.open(QIODevice::ReadOnly)) {
804930
qDebug() << "Error loading group file!";
931+
return std::weak_ptr<NodeGroup>();
805932
}
806933

807934
QDir d = QFileInfo(fileName).absoluteDir();
808-
QString absolute = d.absolutePath();
809-
QDir::setCurrent(absolute);
935+
QDir::setCurrent(d.absolutePath());
810936

811937
QByteArray wholeFile = file.readAll();
812-
813938
const QJsonObject fileJson = QJsonDocument::fromJson(wholeFile).object();
814939

815-
return restoreGroup(fileJson).first;
940+
QHash<NodeId, QJsonObject> nodeById;
941+
942+
QJsonArray nodesArr = fileJson.value("nodes").toArray();
943+
nodeById.reserve(nodesArr.size());
944+
for (QJsonValue const &v : nodesArr) {
945+
QJsonObject o = v.toObject();
946+
NodeId id = jsonValueToNodeId(o.value("id"));
947+
if (id != InvalidNodeId) {
948+
nodeById.insert(id, o);
949+
}
950+
}
951+
952+
return restoreGroup(fileJson, nodeById).first;
816953
}
817954

818955
GroupId BasicGraphicsScene::nextGroupId()

0 commit comments

Comments
 (0)