#include "Node.hpp"
#include
#include
#include
#include "FlowScene.hpp"
#include "NodeGraphicsObject.hpp"
#include "NodeDataModel.hpp"
#include "ConnectionGraphicsObject.hpp"
#include "ConnectionState.hpp"
using QtNodes::Node;
using QtNodes::NodeGeometry;
using QtNodes::NodeState;
using QtNodes::NodeData;
using QtNodes::NodeDataType;
using QtNodes::NodeDataModel;
using QtNodes::NodeGraphicsObject;
using QtNodes::PortIndex;
using QtNodes::PortType;
Node::
Node(std::unique_ptr && dataModel)
: _uid(QUuid::createUuid())
, _nodeDataModel(std::move(dataModel))
, _nodeState(_nodeDataModel)
, _nodeGeometry(_nodeDataModel)
, _nodeGraphicsObject(nullptr)
{
_nodeGeometry.recalculateSize();
// propagate data: model => node
connect(_nodeDataModel.get(), &NodeDataModel::dataUpdated,
this, &Node::onDataUpdated);
connect(_nodeDataModel.get(), &NodeDataModel::embeddedWidgetSizeUpdated,
this, &Node::onNodeSizeUpdated );
}
Node::
~Node() = default;
QJsonObject
Node::
save() const
{
QJsonObject nodeJson;
nodeJson["id"] = _uid.toString();
nodeJson["model"] = _nodeDataModel->save();
QJsonObject obj;
obj["x"] = _nodeGraphicsObject->pos().x();
obj["y"] = _nodeGraphicsObject->pos().y();
nodeJson["position"] = obj;
return nodeJson;
}
void
Node::
restore(QJsonObject const& json)
{
_uid = QUuid(json["id"].toString());
QJsonObject positionJson = json["position"].toObject();
QPointF point(positionJson["x"].toDouble(),
positionJson["y"].toDouble());
_nodeGraphicsObject->setPos(point);
_nodeDataModel->restore(json["model"].toObject());
}
QUuid
Node::
id() const
{
return _uid;
}
void
Node::
reactToPossibleConnection(PortType reactingPortType,
NodeDataType const &reactingDataType,
QPointF const &scenePoint)
{
QTransform const t = _nodeGraphicsObject->sceneTransform();
QPointF p = t.inverted().map(scenePoint);
_nodeGeometry.setDraggingPosition(p);
_nodeGraphicsObject->update();
_nodeState.setReaction(NodeState::REACTING,
reactingPortType,
reactingDataType);
}
void
Node::
resetReactionToConnection()
{
_nodeState.setReaction(NodeState::NOT_REACTING);
_nodeGraphicsObject->update();
}
NodeGraphicsObject const &
Node::
nodeGraphicsObject() const
{
return *_nodeGraphicsObject.get();
}
NodeGraphicsObject &
Node::
nodeGraphicsObject()
{
return *_nodeGraphicsObject.get();
}
void
Node::
setGraphicsObject(std::unique_ptr&& graphics)
{
_nodeGraphicsObject = std::move(graphics);
_nodeGeometry.recalculateSize();
}
NodeGeometry&
Node::
nodeGeometry()
{
return _nodeGeometry;
}
NodeGeometry const&
Node::
nodeGeometry() const
{
return _nodeGeometry;
}
NodeState const &
Node::
nodeState() const
{
return _nodeState;
}
NodeState &
Node::
nodeState()
{
return _nodeState;
}
NodeDataModel*
Node::
nodeDataModel() const
{
return _nodeDataModel.get();
}
void
Node::
propagateData(std::shared_ptr nodeData,
PortIndex inPortIndex,
const QUuid& connectionId) const
{
_nodeDataModel->setInData(std::move(nodeData), inPortIndex, connectionId);
//Recalculate the nodes visuals. A data change can result in the node taking more space than before, so this forces a recalculate+repaint on the affected node
_nodeGraphicsObject->setGeometryChanged();
_nodeGeometry.recalculateSize();
_nodeGraphicsObject->update();
_nodeGraphicsObject->moveConnections();
}
void
Node::
onDataUpdated(PortIndex index)
{
auto nodeData = _nodeDataModel->outData(index);
auto connections =
_nodeState.connections(PortType::Out, index);
for (auto const & c : connections)
c.second->propagateData(nodeData);
}
void
Node::
onNodeSizeUpdated()
{
if( nodeDataModel()->embeddedWidget() )
{
nodeDataModel()->embeddedWidget()->adjustSize();
}
nodeGeometry().recalculateSize();
for(PortType type: {PortType::In, PortType::Out})
{
for(auto& conn_set : nodeState().getEntries(type))
{
for(auto& pair: conn_set)
{
Connection* conn = pair.second;
conn->getConnectionGraphicsObject().move();
}
}
}
}