See More

#include "NodeGraphicsObject.hpp" #include #include #include #include #include "ConnectionGraphicsObject.hpp" #include "ConnectionState.hpp" #include "FlowScene.hpp" #include "NodePainter.hpp" #include "Node.hpp" #include "NodeDataModel.hpp" #include "NodeConnectionInteraction.hpp" NodeGraphicsObject:: NodeGraphicsObject(FlowScene &scene, std::shared_ptr& node) : _scene(scene) , _node(node) , _proxyWidget(nullptr) { _scene.addItem(this); setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemIsFocusable, true); setCacheMode( QGraphicsItem::DeviceCoordinateCache ); { auto effect = new QGraphicsDropShadowEffect; effect->setOffset(4, 4); effect->setBlurRadius(20); effect->setColor(QColor(Qt::gray).darker(800)); setGraphicsEffect(effect); setOpacity(_node.lock()->nodeGeometry().opacity()); } setAcceptHoverEvents(true); embedQWidget(); } std::weak_ptr& NodeGraphicsObject:: node() { return _node; } void NodeGraphicsObject:: embedQWidget() { auto node = _node.lock(); QWidget * w = node->nodeDataModel()->embeddedWidget(); if (w) { _proxyWidget = new QGraphicsProxyWidget(); _proxyWidget->setWidget(w); _proxyWidget->setPreferredWidth(5); _proxyWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); w->setVisible(true); _proxyWidget->setParentItem(this); } } QRectF NodeGraphicsObject:: boundingRect() const { return _node.lock()->nodeGeometry().boundingRect(); } void NodeGraphicsObject:: setGeometryChanged() { prepareGeometryChange(); } void NodeGraphicsObject:: moveConnections() const { std::shared_ptr node = _node.lock(); NodeState const & nodeState = node->nodeState(); auto moveConnections = [&](PortType portType) { auto const & connectionsWeak = nodeState.getEntries(portType); size_t portIndex = 0; for (auto const & connection : connectionsWeak) { QPointF scenePos = node->nodeGeometry().portScenePosition(portIndex, portType, sceneTransform()); auto con = connection.lock(); if (con) { QTransform sceneTransform = con->getConnectionGraphicsObject()->sceneTransform(); QPointF connectionPos = sceneTransform.inverted().map(scenePos); con->connectionGeometry().setEndPoint(portType, connectionPos); con->getConnectionGraphicsObject()->setGeometryChanged(); con->getConnectionGraphicsObject()->update(); } ++portIndex; } }; moveConnections(PortType::IN); moveConnections(PortType::OUT); } void NodeGraphicsObject:: paint(QPainter * painter, QStyleOptionGraphicsItem const* option, QWidget* ) { painter->setClipRect(option->exposedRect); auto node = _node.lock(); NodeGeometry & geom = node->nodeGeometry(); if (_proxyWidget) { _proxyWidget->setPos(geom.widgetPosition()); } NodePainter::paint(painter, node); } void NodeGraphicsObject:: mousePressEvent(QGraphicsSceneMouseEvent * event) { auto clickPort = [&](PortType portToCheck) { auto node = _node.lock(); NodeGeometry & nodeGeometry = node->nodeGeometry(); // TODO do not pass sceneTransform int portIndex = nodeGeometry.checkHitScenePoint(portToCheck, event->scenePos(), sceneTransform()); if (portIndex != INVALID) { NodeState const & nodeState = node->nodeState(); std::shared_ptr connection = nodeState.connection(portToCheck, portIndex); // start dragging existing connection if (connection) { NodeConnectionInteraction interaction(node, connection); interaction.disconnect(portToCheck); } // initialize new Connection else { // todo add to FlowScene auto connection = _scene.createConnection(portToCheck, node, portIndex); node->nodeState().setConnection(portToCheck, portIndex, connection); connection->getConnectionGraphicsObject()->grabMouse(); } } }; clickPort(PortType::IN); clickPort(PortType::OUT); event->accept(); } void NodeGraphicsObject:: mouseMoveEvent(QGraphicsSceneMouseEvent * event) { QGraphicsObject::mouseMoveEvent(event); if (event->lastPos() != event->pos()) moveConnections(); event->ignore(); } void NodeGraphicsObject:: mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { QGraphicsObject::mouseReleaseEvent(event); // position connections precisely after fast node move moveConnections(); } void NodeGraphicsObject:: hoverEnterEvent(QGraphicsSceneHoverEvent * event) { _node.lock()->nodeGeometry().setHovered(true); update(); event->accept(); } void NodeGraphicsObject:: hoverLeaveEvent(QGraphicsSceneHoverEvent * event) { _node.lock()->nodeGeometry().setHovered(false); update(); event->accept(); }