loom

Форк
0
/
BasicGraphicsScene.cpp 
298 строк · 7.9 Кб
1
#include "BasicGraphicsScene.hpp"
2

3
#include "AbstractNodeGeometry.hpp"
4
#include "ConnectionGraphicsObject.hpp"
5
#include "ConnectionIdUtils.hpp"
6
#include "DefaultHorizontalNodeGeometry.hpp"
7
#include "DefaultNodePainter.hpp"
8
#include "DefaultVerticalNodeGeometry.hpp"
9
#include "GraphicsView.hpp"
10
#include "NodeGraphicsObject.hpp"
11

12
#include <QUndoStack>
13

14
#include <QtWidgets/QFileDialog>
15
#include <QtWidgets/QGraphicsSceneMoveEvent>
16

17
#include <QtCore/QBuffer>
18
#include <QtCore/QByteArray>
19
#include <QtCore/QDataStream>
20
#include <QtCore/QFile>
21
#include <QtCore/QJsonArray>
22
#include <QtCore/QJsonDocument>
23
#include <QtCore/QJsonObject>
24
#include <QtCore/QtGlobal>
25

26
#include <iostream>
27
#include <stdexcept>
28
#include <unordered_set>
29
#include <utility>
30
#include <queue>
31

32
namespace QtNodes {
33

34
BasicGraphicsScene::BasicGraphicsScene(AbstractGraphModel &graphModel, QObject *parent)
35
    : QGraphicsScene(parent)
36
    , _graphModel(graphModel)
37
    , _nodeGeometry(std::make_unique<DefaultHorizontalNodeGeometry>(_graphModel))
38
    , _nodePainter(std::make_unique<DefaultNodePainter>())
39
    , _nodeDrag(false)
40
    , _undoStack(new QUndoStack(this))
41
    , _orientation(Qt::Horizontal)
42
{
43
    setItemIndexMethod(QGraphicsScene::NoIndex);
44

45
    connect(&_graphModel,
46
            &AbstractGraphModel::connectionCreated,
47
            this,
48
            &BasicGraphicsScene::onConnectionCreated);
49

50
    connect(&_graphModel,
51
            &AbstractGraphModel::connectionDeleted,
52
            this,
53
            &BasicGraphicsScene::onConnectionDeleted);
54

55
    connect(&_graphModel,
56
            &AbstractGraphModel::nodeCreated,
57
            this,
58
            &BasicGraphicsScene::onNodeCreated);
59

60
    connect(&_graphModel,
61
            &AbstractGraphModel::nodeDeleted,
62
            this,
63
            &BasicGraphicsScene::onNodeDeleted);
64

65
    connect(&_graphModel,
66
            &AbstractGraphModel::nodePositionUpdated,
67
            this,
68
            &BasicGraphicsScene::onNodePositionUpdated);
69

70
    connect(&_graphModel,
71
            &AbstractGraphModel::nodeUpdated,
72
            this,
73
            &BasicGraphicsScene::onNodeUpdated);
74

75
    connect(this, &BasicGraphicsScene::nodeClicked, this, &BasicGraphicsScene::onNodeClicked);
76

77
    connect(&_graphModel, &AbstractGraphModel::modelReset, this, &BasicGraphicsScene::onModelReset);
78

79
    traverseGraphAndPopulateGraphicsObjects();
80
}
81

82
BasicGraphicsScene::~BasicGraphicsScene() = default;
83

84
AbstractGraphModel const &BasicGraphicsScene::graphModel() const
85
{
86
    return _graphModel;
87
}
88

89
AbstractGraphModel &BasicGraphicsScene::graphModel()
90
{
91
    return _graphModel;
92
}
93

94
AbstractNodeGeometry &BasicGraphicsScene::nodeGeometry()
95
{
96
    return *_nodeGeometry;
97
}
98

99
AbstractNodePainter &BasicGraphicsScene::nodePainter()
100
{
101
    return *_nodePainter;
102
}
103

104
void BasicGraphicsScene::setNodePainter(std::unique_ptr<AbstractNodePainter> newPainter)
105
{
106
    _nodePainter = std::move(newPainter);
107
}
108

109
QUndoStack &BasicGraphicsScene::undoStack()
110
{
111
    return *_undoStack;
112
}
113

114
std::unique_ptr<ConnectionGraphicsObject> const &BasicGraphicsScene::makeDraftConnection(
115
    ConnectionId const incompleteConnectionId)
116
{
117
    _draftConnection = std::make_unique<ConnectionGraphicsObject>(*this, incompleteConnectionId);
118

119
    _draftConnection->grabMouse();
120

121
    return _draftConnection;
122
}
123

124
void BasicGraphicsScene::resetDraftConnection()
125
{
126
    _draftConnection.reset();
127
}
128

129
void BasicGraphicsScene::clearScene()
130
{
131
    auto const &allNodeIds = graphModel().allNodeIds();
132

133
    for (auto nodeId : allNodeIds) {
134
        graphModel().deleteNode(nodeId);
135
    }
136
}
137

138
NodeGraphicsObject *BasicGraphicsScene::nodeGraphicsObject(NodeId nodeId)
139
{
140
    NodeGraphicsObject *ngo = nullptr;
141
    auto it = _nodeGraphicsObjects.find(nodeId);
142
    if (it != _nodeGraphicsObjects.end()) {
143
        ngo = it->second.get();
144
    }
145

146
    return ngo;
147
}
148

149
ConnectionGraphicsObject *BasicGraphicsScene::connectionGraphicsObject(ConnectionId connectionId)
150
{
151
    ConnectionGraphicsObject *cgo = nullptr;
152
    auto it = _connectionGraphicsObjects.find(connectionId);
153
    if (it != _connectionGraphicsObjects.end()) {
154
        cgo = it->second.get();
155
    }
156

157
    return cgo;
158
}
159

160
void BasicGraphicsScene::setOrientation(Qt::Orientation const orientation)
161
{
162
    if (_orientation != orientation) {
163
        _orientation = orientation;
164

165
        switch (_orientation) {
166
        case Qt::Horizontal:
167
            _nodeGeometry = std::make_unique<DefaultHorizontalNodeGeometry>(_graphModel);
168
            break;
169

170
        case Qt::Vertical:
171
            _nodeGeometry = std::make_unique<DefaultVerticalNodeGeometry>(_graphModel);
172
            break;
173
        }
174

175
        onModelReset();
176
    }
177
}
178

179
QMenu *BasicGraphicsScene::createSceneMenu(QPointF const scenePos)
180
{
181
    Q_UNUSED(scenePos);
182
    return nullptr;
183
}
184

185
void BasicGraphicsScene::traverseGraphAndPopulateGraphicsObjects()
186
{
187
    auto allNodeIds = _graphModel.allNodeIds();
188

189
    // First create all the nodes.
190
    for (NodeId const nodeId : allNodeIds) {
191
        _nodeGraphicsObjects[nodeId] = std::make_unique<NodeGraphicsObject>(*this, nodeId);
192
    }
193

194
    // Then for each node check output connections and insert them.
195
    for (NodeId const nodeId : allNodeIds) {
196
        unsigned int nOutPorts = _graphModel.nodeData<PortCount>(nodeId, NodeRole::OutPortCount);
197

198
        for (PortIndex index = 0; index < nOutPorts; ++index) {
199
            auto const &outConnectionIds = _graphModel.connections(nodeId, PortType::Out, index);
200

201
            for (auto cid : outConnectionIds) {
202
                _connectionGraphicsObjects[cid] = std::make_unique<ConnectionGraphicsObject>(*this,
203
                                                                                             cid);
204
            }
205
        }
206
    }
207
}
208

209
void BasicGraphicsScene::updateAttachedNodes(ConnectionId const connectionId,
210
                                             PortType const portType)
211
{
212
    auto node = nodeGraphicsObject(getNodeId(portType, connectionId));
213

214
    if (node) {
215
        node->update();
216
    }
217
}
218

219
void BasicGraphicsScene::onConnectionDeleted(ConnectionId const connectionId)
220
{
221
    auto it = _connectionGraphicsObjects.find(connectionId);
222
    if (it != _connectionGraphicsObjects.end()) {
223
        _connectionGraphicsObjects.erase(it);
224
    }
225

226
    // TODO: do we need it?
227
    if (_draftConnection && _draftConnection->connectionId() == connectionId) {
228
        _draftConnection.reset();
229
    }
230

231
    updateAttachedNodes(connectionId, PortType::Out);
232
    updateAttachedNodes(connectionId, PortType::In);
233
}
234

235
void BasicGraphicsScene::onConnectionCreated(ConnectionId const connectionId)
236
{
237
    _connectionGraphicsObjects[connectionId]
238
        = std::make_unique<ConnectionGraphicsObject>(*this, connectionId);
239

240
    updateAttachedNodes(connectionId, PortType::Out);
241
    updateAttachedNodes(connectionId, PortType::In);
242
}
243

244
void BasicGraphicsScene::onNodeDeleted(NodeId const nodeId)
245
{
246
    auto it = _nodeGraphicsObjects.find(nodeId);
247
    if (it != _nodeGraphicsObjects.end()) {
248
        _nodeGraphicsObjects.erase(it);
249
    }
250
}
251

252
void BasicGraphicsScene::onNodeCreated(NodeId const nodeId)
253
{
254
    _nodeGraphicsObjects[nodeId] = std::make_unique<NodeGraphicsObject>(*this, nodeId);
255
}
256

257
void BasicGraphicsScene::onNodePositionUpdated(NodeId const nodeId)
258
{
259
    auto node = nodeGraphicsObject(nodeId);
260
    if (node) {
261
        node->setPos(_graphModel.nodeData(nodeId, NodeRole::Position).value<QPointF>());
262
        node->update();
263
        _nodeDrag = true;
264
    }
265
}
266

267
void BasicGraphicsScene::onNodeUpdated(NodeId const nodeId)
268
{
269
    auto node = nodeGraphicsObject(nodeId);
270

271
    if (node) {
272
        node->setGeometryChanged();
273

274
        _nodeGeometry->recomputeSize(nodeId);
275

276
        node->update();
277
        node->moveConnections();
278
    }
279
}
280

281
void BasicGraphicsScene::onNodeClicked(NodeId const nodeId)
282
{
283
    if (_nodeDrag)
284
        Q_EMIT nodeMoved(nodeId, _graphModel.nodeData(nodeId, NodeRole::Position).value<QPointF>());
285
    _nodeDrag = false;
286
}
287

288
void BasicGraphicsScene::onModelReset()
289
{
290
    _connectionGraphicsObjects.clear();
291
    _nodeGraphicsObjects.clear();
292

293
    clear();
294

295
    traverseGraphAndPopulateGraphicsObjects();
296
}
297

298
} // namespace QtNodes
299

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.