#pragma once #include "Node.hpp" #include "Connection.hpp" namespace QtNodes { class DataModelRegistry; class FlowScene; class NodeDataModel; /// Class performs various operations on the Node and Connection pair. /// An instance should be created on the stack and destroyed when /// the operation is completed class NodeConnectionInteraction { public: NodeConnectionInteraction(Node& node, Connection& connection, FlowScene& scene); /// Can connect when following conditions are met: /// 1) Connection 'requires' a port /// 2) Connection's vacant end is above the node port /// 3) Node port is vacant /// 4) Connection type equals node port type, or there is a registered type conversion that can translate between the two bool canConnect(PortIndex & portIndex, TypeConverter & converter) const; /// 1) Check conditions from 'canConnect' /// 1.5) If the connection is possible but a type conversion is needed, add a converter node to the scene, and connect it properly /// 1.6) Check for cyclic connection. /// 2) Assign node to required port in Connection /// 3) Assign Connection to empty port in NodeState /// 4) Adjust Connection geometry /// 5) Poke model to initiate data transfer bool tryConnect() const; /// 1) Node and Connection should be already connected /// 2) If so, clear Connection entry in the NodeState /// 3) Propagate invalid data to IN node /// 4) Set Connection end to 'requiring a port' bool disconnect(PortType portToDisconnect) const; private: PortType connectionRequiredPort() const; QPointF connectionStartScenePosition(PortType) const; QPointF connectionEndScenePosition(PortType) const; QPointF nodePortScenePosition(PortType portType, PortIndex portIndex) const; PortIndex nodePortIndexUnderScenePoint(PortType portType, QPointF const &p) const; bool nodePortIsEmpty(PortType portType, PortIndex portIndex) const; private: Node* _node; Connection* _connection; FlowScene* _scene; }; }