Skip to content

Commit fb532ca

Browse files
committed
Add save/restore do dynamic port example
1 parent 4ad8391 commit fb532ca

File tree

7 files changed

+246
-54
lines changed

7 files changed

+246
-54
lines changed

examples/dynamic_ports/DynamicPortsModel.cpp

Lines changed: 89 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include <QtNodes/ConnectionIdUtils>
66

7+
#include <QJsonArray>
8+
79
#include <iterator>
810

911

@@ -80,7 +82,8 @@ NodeId
8082
DynamicPortsModel::
8183
addNode(QString const nodeType)
8284
{
83-
NodeId newId = _nextNodeId++;
85+
NodeId newId = newNodeId();
86+
8487
// Create new node.
8588
_nodeIds.insert(newId);
8689

@@ -116,6 +119,22 @@ nodeExists(NodeId const nodeId) const
116119
}
117120

118121

122+
PortAddRemoveWidget*
123+
DynamicPortsModel::
124+
widget(NodeId nodeId) const
125+
{
126+
auto it = _nodeWidgets.find(nodeId);
127+
if (it == _nodeWidgets.end())
128+
{
129+
_nodeWidgets[nodeId] =
130+
new PortAddRemoveWidget(0, 0, nodeId,
131+
*const_cast<DynamicPortsModel*>(this));
132+
}
133+
134+
return _nodeWidgets[nodeId];
135+
}
136+
137+
119138
QVariant
120139
DynamicPortsModel::
121140
nodeData(NodeId nodeId, NodeRole role) const
@@ -166,16 +185,7 @@ nodeData(NodeId nodeId, NodeRole role) const
166185

167186
case NodeRole::Widget:
168187
{
169-
auto it = _nodeWidgets.find(nodeId);
170-
if (it == _nodeWidgets.end())
171-
{
172-
_nodeWidgets[nodeId] =
173-
new PortAddRemoveWidget(_nodePortCounts[nodeId].in,
174-
_nodePortCounts[nodeId].out,
175-
nodeId,
176-
*const_cast<DynamicPortsModel*>(this));
177-
}
178-
result = QVariant::fromValue(_nodeWidgets[nodeId]);
188+
result = QVariant::fromValue(widget(nodeId));
179189
break;
180190
}
181191
}
@@ -227,9 +237,13 @@ setNodeData(NodeId nodeId,
227237
break;
228238

229239
case NodeRole::InPortCount:
240+
_nodePortCounts[nodeId].in = value.toUInt();
241+
widget(nodeId)->populateButtons(PortType::In, value.toUInt());
230242
break;
231243

232244
case NodeRole::OutPortCount:
245+
_nodePortCounts[nodeId].out = value.toUInt();
246+
widget(nodeId)->populateButtons(PortType::Out, value.toUInt());
233247
break;
234248

235249
case NodeRole::Widget:
@@ -332,6 +346,7 @@ deleteNode(NodeId const nodeId)
332346
_nodeIds.erase(nodeId);
333347
_nodeGeometryData.erase(nodeId);
334348
_nodePortCounts.erase(nodeId);
349+
_nodeWidgets.erase(nodeId);
335350

336351
Q_EMIT nodeDeleted(nodeId);
337352

@@ -354,12 +369,40 @@ saveNode(NodeId const nodeId) const
354369
posJson["x"] = pos.x();
355370
posJson["y"] = pos.y();
356371
nodeJson["position"] = posJson;
372+
373+
nodeJson["inPortCount"] = QString::number(_nodePortCounts[nodeId].in);
374+
nodeJson["outPortCount"] = QString::number(_nodePortCounts[nodeId].out);
357375
}
358376

359377
return nodeJson;
360378
}
361379

362380

381+
QJsonObject
382+
DynamicPortsModel::
383+
save() const
384+
{
385+
QJsonObject sceneJson;
386+
387+
QJsonArray nodesJsonArray;
388+
for (auto const nodeId : allNodeIds())
389+
{
390+
nodesJsonArray.append(saveNode(nodeId));
391+
}
392+
sceneJson["nodes"] = nodesJsonArray;
393+
394+
395+
QJsonArray connJsonArray;
396+
for (auto const & cid : _connectivity)
397+
{
398+
connJsonArray.append(QtNodes::toJson(cid));
399+
}
400+
sceneJson["connections"] = connJsonArray;
401+
402+
return sceneJson;
403+
}
404+
405+
363406
void
364407
DynamicPortsModel::
365408
loadNode(QJsonObject const & nodeJson)
@@ -371,7 +414,13 @@ loadNode(QJsonObject const & nodeJson)
371414
// Create new node.
372415
_nodeIds.insert(restoredNodeId);
373416

374-
Q_EMIT nodeCreated(restoredNodeId);
417+
setNodeData(restoredNodeId,
418+
NodeRole::InPortCount,
419+
nodeJson["inPortCount"].toString().toUInt());
420+
421+
setNodeData(restoredNodeId,
422+
NodeRole::OutPortCount,
423+
nodeJson["outPortCount"].toString().toUInt());
375424

376425
{
377426
QJsonObject posJson = nodeJson["position"].toObject();
@@ -381,6 +430,34 @@ loadNode(QJsonObject const & nodeJson)
381430
setNodeData(restoredNodeId,
382431
NodeRole::Position,
383432
pos);
433+
434+
}
435+
436+
Q_EMIT nodeCreated(restoredNodeId);
437+
}
438+
439+
440+
void
441+
DynamicPortsModel::
442+
load(QJsonObject const &jsonDocument)
443+
{
444+
QJsonArray nodesJsonArray = jsonDocument["nodes"].toArray();
445+
446+
for (QJsonValueRef nodeJson : nodesJsonArray)
447+
{
448+
loadNode(nodeJson.toObject());
449+
}
450+
451+
QJsonArray connectionJsonArray = jsonDocument["connections"].toArray();
452+
453+
for (QJsonValueRef connection : connectionJsonArray)
454+
{
455+
QJsonObject connJson = connection.toObject();
456+
457+
ConnectionId connId = QtNodes::fromJson(connJson);
458+
459+
// Restore the connection
460+
addConnection(connId);
384461
}
385462
}
386463

examples/dynamic_ports/DynamicPortsModel.hpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ using PortType = QtNodes::PortType;
1919
using StyleCollection = QtNodes::StyleCollection;
2020
using QtNodes::InvalidNodeId;
2121

22+
class PortAddRemoveWidget;
23+
2224
/**
2325
* The class implements a bare minimum required to demonstrate a model-based
2426
* graph.
@@ -98,6 +100,9 @@ class DynamicPortsModel : public QtNodes::AbstractGraphModel
98100
QJsonObject
99101
saveNode(NodeId const) const override;
100102

103+
QJsonObject
104+
save() const;
105+
101106
/// @brief Creates a new node based on the informatoin in `nodeJson`.
102107
/**
103108
* @param nodeJson conains a `NodeId`, node's position, internal node
@@ -106,6 +111,9 @@ class DynamicPortsModel : public QtNodes::AbstractGraphModel
106111
void
107112
loadNode(QJsonObject const & nodeJson) override;
108113

114+
void
115+
load(QJsonObject const &jsonDocument);
116+
109117
void
110118
addPort(NodeId nodeId,
111119
PortType portType,
@@ -132,12 +140,14 @@ class DynamicPortsModel : public QtNodes::AbstractGraphModel
132140

133141
struct NodePortCount
134142
{
135-
unsigned int in = 1;
136-
unsigned int out = 1;
143+
unsigned int in = 0;
144+
unsigned int out = 0;
137145
};
138146

147+
PortAddRemoveWidget* widget(NodeId) const;
148+
139149
mutable std::unordered_map<NodeId, NodePortCount> _nodePortCounts;
140-
mutable std::unordered_map<NodeId, QWidget*> _nodeWidgets;
150+
mutable std::unordered_map<NodeId, PortAddRemoveWidget*> _nodeWidgets;
141151

142152
/// A convenience variable needed for generating unique node ids.
143153
unsigned int _nextNodeId;

examples/dynamic_ports/PortAddRemoveWidget.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@ PortAddRemoveWidget(unsigned int nInPorts,
3333
hl->addLayout(_left);
3434
hl->addSpacing(50);
3535
hl->addLayout(_right);
36-
37-
populateButtons(_left, nInPorts);
38-
39-
populateButtons(_right, nOutPorts);
4036
}
4137

4238

@@ -48,12 +44,27 @@ PortAddRemoveWidget::
4844

4945
void
5046
PortAddRemoveWidget::
51-
populateButtons(QVBoxLayout* verticalLayout,
47+
populateButtons(PortType portType,
5248
unsigned int nPorts)
5349
{
54-
for (unsigned int i = 0; i < nPorts; ++i)
50+
QVBoxLayout* vl =
51+
(portType == PortType::In) ? _left : _right;
52+
53+
// we use [-1} in the expression `vl->count() - 1` because
54+
// one element - a spacer - is alvays present in this layout.
55+
56+
if (vl->count()-1 < nPorts)
57+
while (vl->count()-1 < nPorts)
58+
{
59+
addButtonGroupToLayout(vl, 0);
60+
}
61+
62+
if (vl->count()-1 > nPorts)
5563
{
56-
addButtonGroupToLayout(verticalLayout, i);
64+
while (vl->count()-1 > nPorts)
65+
{
66+
removeButtonGroupFromLayout(vl, 0);
67+
}
5768
}
5869
}
5970

examples/dynamic_ports/PortAddRemoveWidget.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class PortAddRemoveWidget : public QWidget
5858
* counts.
5959
*/
6060
void
61-
populateButtons(QVBoxLayout* verticalLayout, unsigned int nPorts);
61+
populateButtons(PortType portType, unsigned int nPorts);
6262

6363
/**
6464
* Adds a single `[+][-]` button group to a given layout.

0 commit comments

Comments
 (0)