123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- #include "BasicGraphicsScene.hpp"
- #include "AbstractNodeGeometry.hpp"
- #include "ConnectionGraphicsObject.hpp"
- #include "ConnectionIdUtils.hpp"
- #include "DefaultHorizontalNodeGeometry.hpp"
- #include "DefaultNodePainter.hpp"
- #include "DefaultVerticalNodeGeometry.hpp"
- #include "GraphicsView.hpp"
- #include "NodeGraphicsObject.hpp"
- #include <QUndoStack>
- #include <QtWidgets/QFileDialog>
- #include <QtWidgets/QGraphicsSceneMoveEvent>
- #include <QtCore/QBuffer>
- #include <QtCore/QByteArray>
- #include <QtCore/QDataStream>
- #include <QtCore/QFile>
- #include <QtCore/QJsonArray>
- #include <QtCore/QJsonDocument>
- #include <QtCore/QJsonObject>
- #include <QtCore/QtGlobal>
- #include <iostream>
- #include <stdexcept>
- #include <unordered_set>
- #include <utility>
- #include <queue>
- namespace QtNodes {
- BasicGraphicsScene::BasicGraphicsScene(AbstractGraphModel &graphModel, QObject *parent)
- : QGraphicsScene(parent)
- , _graphModel(graphModel)
- , _nodeGeometry(std::make_unique<DefaultHorizontalNodeGeometry>(_graphModel))
- , _nodePainter(std::make_unique<DefaultNodePainter>())
- , _nodeDrag(false)
- , _undoStack(new QUndoStack(this))
- , _orientation(Qt::Horizontal)
- {
- setItemIndexMethod(QGraphicsScene::NoIndex);
- connect(&_graphModel,
- &AbstractGraphModel::connectionCreated,
- this,
- &BasicGraphicsScene::onConnectionCreated);
- connect(&_graphModel,
- &AbstractGraphModel::connectionDeleted,
- this,
- &BasicGraphicsScene::onConnectionDeleted);
- connect(&_graphModel,
- &AbstractGraphModel::nodeCreated,
- this,
- &BasicGraphicsScene::onNodeCreated);
- connect(&_graphModel,
- &AbstractGraphModel::nodeDeleted,
- this,
- &BasicGraphicsScene::onNodeDeleted);
- connect(&_graphModel,
- &AbstractGraphModel::nodePositionUpdated,
- this,
- &BasicGraphicsScene::onNodePositionUpdated);
- connect(&_graphModel,
- &AbstractGraphModel::nodeUpdated,
- this,
- &BasicGraphicsScene::onNodeUpdated);
- connect(this, &BasicGraphicsScene::nodeClicked, this, &BasicGraphicsScene::onNodeClicked);
- connect(&_graphModel, &AbstractGraphModel::modelReset, this, &BasicGraphicsScene::onModelReset);
- traverseGraphAndPopulateGraphicsObjects();
- }
- BasicGraphicsScene::~BasicGraphicsScene() = default;
- AbstractGraphModel const &BasicGraphicsScene::graphModel() const
- {
- return _graphModel;
- }
- AbstractGraphModel &BasicGraphicsScene::graphModel()
- {
- return _graphModel;
- }
- AbstractNodeGeometry &BasicGraphicsScene::nodeGeometry()
- {
- return *_nodeGeometry;
- }
- AbstractNodePainter &BasicGraphicsScene::nodePainter()
- {
- return *_nodePainter;
- }
- void BasicGraphicsScene::setNodePainter(std::unique_ptr<AbstractNodePainter> newPainter)
- {
- _nodePainter = std::move(newPainter);
- }
- QUndoStack &BasicGraphicsScene::undoStack()
- {
- return *_undoStack;
- }
- std::unique_ptr<ConnectionGraphicsObject> const &BasicGraphicsScene::makeDraftConnection(
- ConnectionId const incompleteConnectionId)
- {
- _draftConnection = std::make_unique<ConnectionGraphicsObject>(*this, incompleteConnectionId);
- _draftConnection->grabMouse();
- return _draftConnection;
- }
- void BasicGraphicsScene::resetDraftConnection()
- {
- _draftConnection.reset();
- }
- void BasicGraphicsScene::clearScene()
- {
- auto const &allNodeIds = graphModel().allNodeIds();
- for (auto nodeId : allNodeIds) {
- graphModel().deleteNode(nodeId);
- }
- }
- NodeGraphicsObject *BasicGraphicsScene::nodeGraphicsObject(NodeId nodeId)
- {
- NodeGraphicsObject *ngo = nullptr;
- auto it = _nodeGraphicsObjects.find(nodeId);
- if (it != _nodeGraphicsObjects.end()) {
- ngo = it->second.get();
- }
- return ngo;
- }
- ConnectionGraphicsObject *BasicGraphicsScene::connectionGraphicsObject(ConnectionId connectionId)
- {
- ConnectionGraphicsObject *cgo = nullptr;
- auto it = _connectionGraphicsObjects.find(connectionId);
- if (it != _connectionGraphicsObjects.end()) {
- cgo = it->second.get();
- }
- return cgo;
- }
- void BasicGraphicsScene::setOrientation(Qt::Orientation const orientation)
- {
- if (_orientation != orientation) {
- _orientation = orientation;
- switch (_orientation) {
- case Qt::Horizontal:
- _nodeGeometry = std::make_unique<DefaultHorizontalNodeGeometry>(_graphModel);
- break;
- case Qt::Vertical:
- _nodeGeometry = std::make_unique<DefaultVerticalNodeGeometry>(_graphModel);
- break;
- }
- onModelReset();
- }
- }
- QMenu *BasicGraphicsScene::createSceneMenu(QPointF const scenePos)
- {
- Q_UNUSED(scenePos);
- return nullptr;
- }
- void BasicGraphicsScene::traverseGraphAndPopulateGraphicsObjects()
- {
- auto allNodeIds = _graphModel.allNodeIds();
- // First create all the nodes.
- for (NodeId const nodeId : allNodeIds) {
- _nodeGraphicsObjects[nodeId] = std::make_unique<NodeGraphicsObject>(*this, nodeId);
- }
- // Then for each node check output connections and insert them.
- for (NodeId const nodeId : allNodeIds) {
- unsigned int nOutPorts = _graphModel.nodeData<PortCount>(nodeId, NodeRole::OutPortCount);
- for (PortIndex index = 0; index < nOutPorts; ++index) {
- auto const &outConnectionIds = _graphModel.connections(nodeId, PortType::Out, index);
- for (auto cid : outConnectionIds) {
- _connectionGraphicsObjects[cid] = std::make_unique<ConnectionGraphicsObject>(*this,
- cid);
- }
- }
- }
- }
- void BasicGraphicsScene::updateAttachedNodes(ConnectionId const connectionId,
- PortType const portType)
- {
- auto node = nodeGraphicsObject(getNodeId(portType, connectionId));
- if (node) {
- node->update();
- }
- }
- void BasicGraphicsScene::onConnectionDeleted(ConnectionId const connectionId)
- {
- auto it = _connectionGraphicsObjects.find(connectionId);
- if (it != _connectionGraphicsObjects.end()) {
- _connectionGraphicsObjects.erase(it);
- }
- // TODO: do we need it?
- if (_draftConnection && _draftConnection->connectionId() == connectionId) {
- _draftConnection.reset();
- }
- updateAttachedNodes(connectionId, PortType::Out);
- updateAttachedNodes(connectionId, PortType::In);
- }
- void BasicGraphicsScene::onConnectionCreated(ConnectionId const connectionId)
- {
- _connectionGraphicsObjects[connectionId]
- = std::make_unique<ConnectionGraphicsObject>(*this, connectionId);
- updateAttachedNodes(connectionId, PortType::Out);
- updateAttachedNodes(connectionId, PortType::In);
- }
- void BasicGraphicsScene::onNodeDeleted(NodeId const nodeId)
- {
- auto it = _nodeGraphicsObjects.find(nodeId);
- if (it != _nodeGraphicsObjects.end()) {
- _nodeGraphicsObjects.erase(it);
- }
- }
- void BasicGraphicsScene::onNodeCreated(NodeId const nodeId)
- {
- _nodeGraphicsObjects[nodeId] = std::make_unique<NodeGraphicsObject>(*this, nodeId);
- }
- void BasicGraphicsScene::onNodePositionUpdated(NodeId const nodeId)
- {
- auto node = nodeGraphicsObject(nodeId);
- if (node) {
- node->setPos(_graphModel.nodeData(nodeId, NodeRole::Position).value<QPointF>());
- node->update();
- _nodeDrag = true;
- }
- }
- void BasicGraphicsScene::onNodeUpdated(NodeId const nodeId)
- {
- auto node = nodeGraphicsObject(nodeId);
- if (node) {
- node->setGeometryChanged();
- _nodeGeometry->recomputeSize(nodeId);
- node->update();
- node->moveConnections();
- }
- }
- void BasicGraphicsScene::onNodeClicked(NodeId const nodeId)
- {
- if (_nodeDrag)
- Q_EMIT nodeMoved(nodeId, _graphModel.nodeData(nodeId, NodeRole::Position).value<QPointF>());
- _nodeDrag = false;
- }
- void BasicGraphicsScene::onModelReset()
- {
- _connectionGraphicsObjects.clear();
- _nodeGraphicsObjects.clear();
- clear();
- traverseGraphAndPopulateGraphicsObjects();
- }
- } // namespace QtNodes
|