#pragma once #include #include #include #include #include #include #include "QUuidStdHash.hpp" #include "Export.hpp" #include "DataModelRegistry.hpp" #include "TypeConverter.hpp" #include "memory.hpp" namespace QtNodes { class NodeDataModel; class FlowItemInterface; class Node; class NodeGraphicsObject; class Connection; class ConnectionGraphicsObject; class NodeStyle; /// Scene holds connections and nodes. class FlowScene : public QGraphicsScene { Q_OBJECT public: FlowScene(std::shared_ptr registry, QObject* parent = Q_NULLPTR); FlowScene(QObject* parent = Q_NULLPTR); ~FlowScene(); public: std::shared_ptr createConnection(PortType connectedPort, Node& node, PortIndex portIndex); std::shared_ptr createConnection(Node& nodeIn, PortIndex portIndexIn, Node& nodeOut, PortIndex portIndexOut, TypeConverter const& converter = TypeConverter{}); std::shared_ptr restoreConnection(QJsonObject const& connectionJson); void deleteConnection(Connection const& connection); Node& createNode(std::unique_ptr&& dataModel); Node& restoreNode(QJsonObject const& nodeJson); void removeNode(Node& node); DataModelRegistry& registry() const; void setRegistry(std::shared_ptr registry); void iterateOverNodes(std::function const& visitor); void iterateOverNodeData(std::function const& visitor); void iterateOverNodeDataDependentOrder(std::function const& visitor); QPointF getNodePosition(Node const& node) const; void setNodePosition(Node& node, QPointF const& pos) const; QSizeF getNodeSize(Node const& node) const; public: std::unordered_map > const& nodes() const; std::unordered_map > const& connections() const; std::vector allNodes() const; std::vector selectedNodes() const; public: void clearScene(); void save() const; void load(); QByteArray saveToMemory() const; void loadFromMemory(const QByteArray& data); Q_SIGNALS: /** * @brief Node has been created but not on the scene yet. * @see nodePlaced() */ void nodeCreated(Node& n); /** * @brief Node has been added to the scene. * @details Connect to this signal if need a correct position of node. * @see nodeCreated() */ void nodePlaced(Node& n); void nodeDeleted(Node& n); void connectionCreated(Connection const& c); void connectionDeleted(Connection const& c); void nodeMoved(Node& n, const QPointF& newLocation); void nodeDoubleClicked(Node& n); void nodeClicked(Node& n); void connectionHovered(Connection& c, QPoint screenPos); void nodeHovered(Node& n, QPoint screenPos); void connectionHoverLeft(Connection& c); void nodeHoverLeft(Node& n); void nodeContextMenu(Node& n, const QPointF& pos); private: using SharedConnection = std::shared_ptr; using UniqueNode = std::unique_ptr; // DO NOT reorder this member to go after the others. // This should outlive all the connections and nodes of // the graph, so that nodes can potentially have pointers into it, // which is why it comes first in the class. std::shared_ptr _registry; std::unordered_map _connections; std::unordered_map _nodes; private Q_SLOTS: void setupConnectionSignals(Connection const& c); void sendConnectionCreatedToNodes(Connection const& c); void sendConnectionDeletedToNodes(Connection const& c); }; Node* locateNodeAt(QPointF scenePoint, FlowScene& scene, QTransform const& viewTransform); }