forked from paceholder/nodeeditor
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAbstractGraphModel.hpp
More file actions
253 lines (213 loc) · 8.24 KB
/
AbstractGraphModel.hpp
File metadata and controls
253 lines (213 loc) · 8.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#pragma once
#include "ConnectionIdHash.hpp"
#include "Definitions.hpp"
#include "Export.hpp"
#include <QtCore/QJsonObject>
#include <QtCore/QObject>
#include <QtCore/QVariant>
#include <unordered_set>
namespace QtNodes {
/**
* The central class in the Model-View approach. It delivers all kinds
* of information from the backing user data structures that represent
* the graph. The class allows to modify the graph structure: create
* and remove nodes and connections.
*
* We use two types of the unique ids for graph manipulations:
* - NodeId
* - ConnectionId
*/
class NODE_EDITOR_PUBLIC AbstractGraphModel : public QObject
{
Q_OBJECT
public:
/// Generates a new unique NodeId.
virtual NodeId newNodeId() = 0;
/// @brief Returns the full set of unique Node Ids.
/**
* Model creator is responsible for generating unique `unsigned int`
* Ids for all the nodes in the graph. From an Id it should be
* possible to trace back to the model's internal representation of
* the node.
*/
virtual std::unordered_set<NodeId> allNodeIds() const = 0;
/**
* A collection of all input and output connections for the given `nodeId`.
*/
virtual std::unordered_set<ConnectionId> allConnectionIds(NodeId const nodeId) const = 0;
/// @brief Returns all connected Node Ids for given port.
/**
* The returned set of nodes and port indices correspond to the type
* opposite to the given `portType`.
*/
virtual std::unordered_set<ConnectionId> connections(NodeId nodeId,
PortType portType,
PortIndex index) const = 0;
/// Checks if two nodes with the given `connectionId` are connected.
virtual bool connectionExists(ConnectionId const connectionId) const = 0;
/// Creates a new node instance in the derived class.
/**
* The model is responsible for generating a unique `NodeId`.
* @param[in] nodeType is free to be used and interpreted by the
* model on its own, it helps to distinguish between possible node
* types and create a correct instance inside.
*/
virtual NodeId addNode(QString const nodeType = QString()) = 0;
/// Model decides if a conection with a given connection Id possible.
/**
* The default implementation compares corresponding data types.
*
* It is possible to override the function and connect non-equal
* data types.
*/
virtual bool connectionPossible(ConnectionId const connectionId) const = 0;
/// Defines if detaching the connection is possible.
virtual bool detachPossible(ConnectionId const) const { return true; }
/**
* @brief Creates a new connection between two nodes.
*
* Default implementation emits signal
* `connectionCreated(connectionId)`
*
* In the derived classes user must emite the signal to notify the
* scene about the changes.
*/
virtual void addConnection(ConnectionId const connectionId) = 0;
/**
* @returns `true` if there is data in the model associated with the
* given `nodeId`.
*/
virtual bool nodeExists(NodeId const nodeId) const = 0;
/// @brief Returns node-related data for requested NodeRole.
/**
* @returns Node Caption, Node Caption Visibility, Node Position etc.
*/
virtual QVariant nodeData(NodeId nodeId, NodeRole role) const = 0;
/**
* A utility function that unwraps the `QVariant` value returned from the
* standard `QVariant AbstractGraphModel::nodeData(NodeId, NodeRole)` function.
*/
template<typename T>
T nodeData(NodeId nodeId, NodeRole role) const
{
return nodeData(nodeId, role).value<T>();
}
virtual NodeFlags nodeFlags(NodeId nodeId) const
{
Q_UNUSED(nodeId);
return NodeFlag::NoFlags;
}
/**
* @brief Sets node properties.
*
* Sets: Node Caption, Node Caption Visibility,
* Shyle, State, Node Position etc.
* @see NodeRole.
*/
virtual bool setNodeData(NodeId nodeId, NodeRole role, QVariant value) = 0;
/**
* @brief Returns port-related data for requested NodeRole.
*
* @returns Port Data Type, Port Data, Connection Policy, Port
* Caption.
*/
virtual QVariant portData(NodeId nodeId,
PortType portType,
PortIndex index,
PortRole role) const = 0;
/**
* A utility function that unwraps the `QVariant` value returned from the
* standard `QVariant AbstractGraphModel::portData(...)` function.
*/
template<typename T>
T portData(NodeId nodeId, PortType portType, PortIndex index, PortRole role) const
{
return portData(nodeId, portType, index, role).value<T>();
}
virtual bool setPortData(NodeId nodeId,
PortType portType,
PortIndex index,
QVariant const &value,
PortRole role = PortRole::Data)
= 0;
virtual bool deleteConnection(ConnectionId const connectionId) = 0;
virtual bool deleteNode(NodeId const nodeId) = 0;
/**
* Reimplement the function if you want to store/restore the node's
* inner state during undo/redo node deletion operations.
*/
virtual QJsonObject saveNode(NodeId const) const { return {}; }
/**
* Reimplement the function if you want to support:
*
* - graph save/restore operations,
* - undo/redo operations after deleting the node.
*
* QJsonObject must contain following fields:
*
*
* ```json
* {
* id : 5,
* position : { x : 100, y : 200 },
* internal-data {
* "your model specific data here"
* }
* }
* ```
*
* The function must do almost exacly the same thing as the normal addNode().
* The main difference is in a model-specific `inner-data` processing.
*/
virtual void loadNode(QJsonObject const &) {}
virtual bool loopsEnabled() const { return true; }
public:
/**
* Function clears connections attached to the ports that are scheduled to be
* deleted. It must be called right before the model removes its old port data.
*
* @param nodeId Defines the node to be modified
* @param portType Is either PortType::In or PortType::Out
* @param first Index of the first port to be removed
* @param last Index of the last port to be removed
*/
void portsAboutToBeDeleted(NodeId const nodeId,
PortType const portType,
PortIndex const first,
PortIndex const last);
/**
* Signal emitted when model no longer has the old data associated with the
* given port indices and when the node must be repainted.
*/
void portsDeleted();
/**
* Signal emitted when model is about to create new ports on the given node.
* @param first Is the first index of the new port after insertion.
* @param last Is the last index of the new port after insertion.
*
* Function caches existing connections that are located after the `last` port
* index. For such connections the new "post-insertion" addresses are computed
* and stored until the function AbstractGraphModel::portsInserted is called.
*/
void portsAboutToBeInserted(NodeId const nodeId,
PortType const portType,
PortIndex const first,
PortIndex const last);
/**
* Function re-creates the connections that were shifted during the port
* insertion. After that the node is updated.
*/
void portsInserted();
Q_SIGNALS:
void connectionCreated(ConnectionId const connectionId);
void connectionDeleted(ConnectionId const connectionId);
void nodeCreated(NodeId const nodeId);
void nodeDeleted(NodeId const nodeId);
void nodeUpdated(NodeId const nodeId);
void nodeFlagsUpdated(NodeId const nodeId);
void nodePositionUpdated(NodeId const nodeId);
void modelReset();
private:
std::vector<ConnectionId> _shiftedByDynamicPortsConnections;
};
} // namespace QtNodes