From 73577268e2fa608f84d692deefde416a801bd3a0 Mon Sep 17 00:00:00 2001 From: Dmitry Pinaev Date: Sun, 20 Dec 2015 17:46:00 +0100 Subject: [PATCH] Split Node and NodeGraphicsObject --- src/Connection.cpp | 26 ++++- src/Connection.hpp | 4 +- src/FlowItemEntry.cpp | 74 ------------ src/FlowItemEntry.hpp | 83 -------------- src/FlowScene.cpp | 21 +--- src/Node.cpp | 132 +++++++++++++++++++++- src/Node.hpp | 41 ++++++- src/NodeGeometry.cpp | 45 +++++++- src/NodeGeometry.hpp | 11 +- src/NodeGraphicsObject.cpp | 225 +++++++------------------------------ src/NodeGraphicsObject.hpp | 41 +------ src/NodePainter.cpp | 6 +- 12 files changed, 289 insertions(+), 420 deletions(-) delete mode 100644 src/FlowItemEntry.cpp delete mode 100644 src/FlowItemEntry.hpp diff --git a/src/Connection.cpp b/src/Connection.cpp index 669de7a..b058d14 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -6,10 +6,12 @@ #include #include "Node.hpp" -#include "FlowItemEntry.hpp" #include "FlowScene.hpp" #include "FlowGraphicsView.hpp" +#include "NodeGeometry.hpp" +#include "NodeGraphicsObject.hpp" + #include "ConnectionGeometry.hpp" #include "ConnectionGraphicsObject.hpp" @@ -175,13 +177,16 @@ tryConnectToNode(Node* node, QPointF const& scenePoint) if (ok) { - auto address = node->connect(this, _impl->_draggingEnd, scenePoint); + auto address = node->connect(this, + _impl->_draggingEnd, + scenePoint); if (!address.first.isNull()) { + //auto p = node->connectionPointScenePosition(address, + //_impl->_draggingEnd); - auto p = node->connectionPointScenePosition(address, _impl->_draggingEnd); - connectToNode(address, p); + connectToNode(address); //------ @@ -195,11 +200,20 @@ tryConnectToNode(Node* node, QPointF const& scenePoint) void Connection:: -connectToNode(std::pair const &address, - QPointF const& scenePoint) +connectToNode(std::pair const &address) { setAddress(_impl->_draggingEnd, address); + Node const* node = FlowScene::instance().getNode(address.first); + + NodeGraphicsObject const* o = node->nodeGraphicsObject(); + NodeGeometry const & nodeGeometry = node->nodeGeometry(); + + QPointF const scenePoint = + nodeGeometry.connectionPointScenePosition(address.second, + _impl->_draggingEnd, + o->sceneTransform()); + auto p = _impl->_connectionGraphicsObject->mapFromScene(scenePoint); _impl->_connectionGeometry.setEndPoint(_impl->_draggingEnd, p); diff --git a/src/Connection.hpp b/src/Connection.hpp index 6604dbf..34e1583 100644 --- a/src/Connection.hpp +++ b/src/Connection.hpp @@ -38,8 +38,8 @@ public: bool tryConnectToNode(Node* node, QPointF const& scenePoint); /// Node initiates - void connectToNode(std::pair const &address, - QPointF const& scenePoint); + void connectToNode(std::pair const &address); + //QPointF const& scenePoint); ConnectionGraphicsObject* getConnectionGraphicsObject() const; diff --git a/src/FlowItemEntry.cpp b/src/FlowItemEntry.cpp deleted file mode 100644 index 99f8d29..0000000 --- a/src/FlowItemEntry.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "FlowItemEntry.hpp" -#include - -#include "Node.hpp" -#include "FlowScene.hpp" - -FlowItemEntry:: -FlowItemEntry(EndType type, - QUuid parentID, - NodeGeometry const& nodeGeom, - QString name, - QUuid connectionID) - : _id(QUuid::createUuid()) - , _parentID(parentID) - , _connectionID(connectionID) - , _type(type) - , _name(name) - , _nodeGeometry(nodeGeom) -{ - Node* flowItem = FlowScene::instance().getNode(_parentID); - - setParentItem(flowItem); -} - - -QUuid -FlowItemEntry:: -id() const { return _id; } - -QUuid -FlowItemEntry:: -parentID() const -{ - return _parentID; -} - - -QRectF -FlowItemEntry:: -boundingRect() const -{ - return _nodeGeometry.entryBoundingRect(); -} - - -void -FlowItemEntry:: -setConnectionID(QUuid connectionID) -{ - _connectionID = connectionID; -} - - -QUuid -FlowItemEntry:: -getConnectionID() const -{ - return _connectionID; -} - - -void -FlowItemEntry:: -paint(QPainter* painter, - QStyleOptionGraphicsItem const*, - QWidget*) -{ - - return; - - painter->setPen(Qt::white); - painter->setBrush(QColor(Qt::darkGray)); - painter->drawRect(boundingRect()); -} diff --git a/src/FlowItemEntry.hpp b/src/FlowItemEntry.hpp deleted file mode 100644 index 159ccd9..0000000 --- a/src/FlowItemEntry.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef FLOW_ITEM_ENTRY_H -#define FLOW_ITEM_ENTRY_H - -#include - -#include -#include - -#include -#include - -#include "Connection.hpp" - -class Node; -class NodeGeometry; - -class FlowItemEntry : public QGraphicsObject -{ - Q_OBJECT - -public: - QUuid id() const; - - QUuid parentID() const; - -public: - FlowItemEntry(EndType type, - QUuid parentID, - NodeGeometry const& nodeGeom, - QString name = QString("Entry"), - QUuid connectionID = QUuid()); - - QRectF boundingRect() const override; - - void setConnectionID(QUuid connectionID); - - QUuid getConnectionID() const; - -protected: // events - - void mousePressEvent(QGraphicsSceneMouseEvent* event) override - { - (void)event; - - event->ignore(); - - //std::cout << "PRESS CHILD" << std::endl; - } - - void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override - { - //double const x = event->pos().x(); - //double const y = event->pos().y(); - //std::cout << "Mouse Event Item " << x << ", " << y << std::endl; - - event->ignore(); - } - -protected: - void paint(QPainter* painter, - QStyleOptionGraphicsItem const* option, - QWidget* widget = 0) override; - -private: - // addressing - - QUuid _id; - - QUuid _parentID; - QUuid _connectionID; - - // structure - - EndType _type; - - QString _name; - - // painting - - NodeGeometry const& _nodeGeometry; -}; - -#endif // FLOW_ITEM_ENTRY_H diff --git a/src/FlowScene.cpp b/src/FlowScene.cpp index d412879..5d00a5b 100644 --- a/src/FlowScene.cpp +++ b/src/FlowScene.cpp @@ -5,6 +5,8 @@ #include #include "Node.hpp" +#include "NodeGraphicsObject.hpp" + #include "FlowItemInterface.hpp" #include "FlowGraphicsView.hpp" @@ -41,15 +43,13 @@ locateNodeAt(QGraphicsSceneMouseEvent * event) std::back_inserter(filteredItems), [](QGraphicsItem * item) { - return dynamic_cast(item); + return (dynamic_cast(item) != nullptr); }); if (filteredItems.empty()) return nullptr; - Node* flowItem = dynamic_cast(filteredItems.front()); - - return flowItem; + return dynamic_cast(filteredItems.front())->node(); } @@ -85,18 +85,9 @@ createNode() { (void)i; - Node* flowItem = new Node(); + Node* node = new Node(); - this->addItem(flowItem); - - _nodes[flowItem->id()] = flowItem; - - flowItem->initializeNode(); - - constexpr int spread = 700; - - flowItem->moveBy(std::rand() % spread - spread / 2, - std::rand() % spread - spread / 2); + _nodes[node->id()] = node; } return QUuid(); diff --git a/src/Node.cpp b/src/Node.cpp index ebd3526..845a26c 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -1,10 +1,16 @@ #include "Node.hpp" +#include + #include #include "FlowScene.hpp" +#include "NodeState.hpp" +#include "NodeGeometry.hpp" + #include "NodeGraphicsObject.hpp" +#include "ConnectionGraphicsObject.hpp" class Node::NodeImpl { @@ -14,7 +20,7 @@ public: , _nodeState(std::rand() % 4 + 2, std::rand() % 4 + 2) , _nodeGraphicsObject(new NodeGraphicsObject(*node, - _nodeState, + _nodeState, _nodeGeometry)) { _nodeGeometry.setNSources(_nodeState.getEntries(EndType::SOURCE).size()); @@ -47,9 +53,11 @@ public: NodeGraphicsObject* _nodeGraphicsObject; }; +//------------------------------------------------------------------------------ + Node:: Node() - : _impl(new NodeGraphicsObject()) + : _impl(new NodeImpl(this)) { // } @@ -60,3 +68,123 @@ Node:: { // } + + +QUuid const +Node:: +id() const +{ + return _impl->_id; +} + + +void +Node:: +reactToPossibleConnection(EndType, + QPointF const &scenePoint) +{ + QTransform const t = _impl->_nodeGraphicsObject->sceneTransform(); + + QPointF p = t.inverted().map(scenePoint); + + _impl->_nodeGeometry.setDraggingPosition(p); +} + + +void +Node:: +update() +{ + _impl->_nodeGraphicsObject->update(); +} + + +bool +Node:: +canConnect(EndType draggingEnd, QPointF const &scenePoint) +{ + auto g = _impl->_nodeGraphicsObject; + int hit = + _impl->_nodeGeometry.checkHitScenePoint(draggingEnd, + scenePoint, + _impl->_nodeState, + g->sceneTransform()); + + return ((hit >= 0) && + _impl->_nodeState.connectionID(draggingEnd, hit).isNull()); +} + + +std::pair +Node:: +connect(Connection const* connection, + EndType draggingEnd, + int hit) +{ + _impl->_nodeState.setConnectionId(draggingEnd, hit, connection->id()); + + QObject::connect(_impl->_nodeGraphicsObject, + &NodeGraphicsObject::itemMoved, + connection->getConnectionGraphicsObject(), + &ConnectionGraphicsObject::onItemMoved); + + connection->getConnectionGraphicsObject()->setZValue(-1.0); + + return std::make_pair(_impl->_id, hit); +} + + +std::pair +Node:: +connect(Connection const* connection, + EndType draggingEnd, + QPointF const & scenePoint) +{ + auto g = _impl->_nodeGraphicsObject; + int hit = + _impl->_nodeGeometry.checkHitScenePoint(draggingEnd, + scenePoint, + _impl->_nodeState, + g->sceneTransform()); + + return connect(connection, draggingEnd, hit); +} + + +void +Node:: +disconnect(Connection const* connection, + EndType endType, + int hit) +{ + QObject::disconnect(_impl->_nodeGraphicsObject, + &NodeGraphicsObject::itemMoved, + connection->getConnectionGraphicsObject(), + &ConnectionGraphicsObject::onItemMoved); + + _impl->_nodeState.setConnectionId(endType, hit, QUuid()); +} + + +NodeGraphicsObject const* +Node:: +nodeGraphicsObject() const +{ + return _impl->_nodeGraphicsObject; +} + + +NodeGeometry& +Node:: +nodeGeometry() +{ + return _impl->_nodeGeometry; +} + + +NodeGeometry const& +Node:: +nodeGeometry() const +{ + return _impl->_nodeGeometry; +} diff --git a/src/Node.hpp b/src/Node.hpp index 45a7ddd..349faa5 100644 --- a/src/Node.hpp +++ b/src/Node.hpp @@ -6,8 +6,11 @@ #include #include -#include "NodeState.hpp" -#include "NodeGeometry.hpp" +#include "EndType.hpp" + +class Connection; +class NodeGeometry; +class NodeGraphicsObject; class Node : public QObject { @@ -20,15 +23,43 @@ public: public: - QUuid id(); + QUuid const id() const; + + void reactToPossibleConnection(EndType, + QPointF const & scenePoint); + + /// Updates graphics + void update(); + + bool canConnect(EndType draggingEnd, + QPointF const &scenePoint); + + std::pair + connect(Connection const* connection, + EndType draggingEnd, + int hit); + + std::pair + connect(Connection const* connection, + EndType draggingEnd, + QPointF const& scenePoint); + + + + void disconnect(Connection const* connection, + EndType endType, + int hit); + + NodeGraphicsObject const* nodeGraphicsObject() const; + + NodeGeometry& nodeGeometry(); + NodeGeometry const& nodeGeometry() const; private: class NodeImpl; std::unique_ptr _impl; - }; - #endif // NODE_HPP diff --git a/src/NodeGeometry.cpp b/src/NodeGeometry.cpp index b5b87b0..923b517 100644 --- a/src/NodeGeometry.cpp +++ b/src/NodeGeometry.cpp @@ -1,5 +1,7 @@ #include "NodeGeometry.hpp" +#include "NodeState.hpp" + NodeGeometry:: NodeGeometry() : _width(100) @@ -60,10 +62,14 @@ recalculateSize() QPointF NodeGeometry:: -connectionPointScenePosition(int index, EndType endType) const +connectionPointScenePosition(int index, + EndType endType, + QTransform t) const { unsigned int step = _entryHeight + _spacing; + QPointF result; + switch (endType) { case EndType::SOURCE: @@ -80,7 +86,7 @@ connectionPointScenePosition(int index, EndType endType) const double x = _width + _connectionPointDiameter; - return QPointF(x, totalHeight); + result = QPointF(x, totalHeight); break; } @@ -95,7 +101,7 @@ connectionPointScenePosition(int index, EndType endType) const double x = 0.0 - _connectionPointDiameter; - return QPointF(x, totalHeight); + result = QPointF(x, totalHeight); break; } @@ -103,8 +109,37 @@ connectionPointScenePosition(int index, EndType endType) const break; } - return QPointF(); + return t.map(result); } -void setDraggingPosition(QPointF const& pos); +int +NodeGeometry:: +checkHitScenePoint(EndType endType, + QPointF const point, + NodeState const& nodeState, + QTransform t) const +{ + int result = -1; + + if (endType == EndType::NONE) + return result; + + double tolerance = 2.0 * _connectionPointDiameter; + + size_t nItems = nodeState.getEntries(endType).size(); + + for (size_t i = 0; i < nItems; ++i) + { + QPointF p = connectionPointScenePosition(i, endType, t) - point; + auto distance = std::sqrt(QPointF::dotProduct(p, p)); + + if (distance < tolerance) + { + result = i; + break; + } + } + + return result; +} diff --git a/src/NodeGeometry.hpp b/src/NodeGeometry.hpp index 12b6299..ea1afdb 100644 --- a/src/NodeGeometry.hpp +++ b/src/NodeGeometry.hpp @@ -3,9 +3,12 @@ #include #include +#include #include "EndType.hpp" +class NodeState; + class NodeGeometry { public: @@ -59,7 +62,13 @@ public: void recalculateSize(); QPointF connectionPointScenePosition(int index, - EndType endType) const; + EndType endType, + QTransform t = QTransform()) const; + + int checkHitScenePoint(EndType endType, + QPointF const point, + NodeState const& nodeState, + QTransform t = QTransform()) const; private: unsigned int _width; diff --git a/src/NodeGraphicsObject.cpp b/src/NodeGraphicsObject.cpp index f8d1d64..8444f12 100644 --- a/src/NodeGraphicsObject.cpp +++ b/src/NodeGraphicsObject.cpp @@ -1,18 +1,19 @@ #include "NodeGraphicsObject.hpp" -#include -#include - #include #include +#include +#include + #include "ConnectionGraphicsObject.hpp" -#include "FlowItemEntry.hpp" #include "FlowScene.hpp" #include "NodePainter.hpp" +#include "Node.hpp" + NodeGraphicsObject:: -NodeGraphicsObject(Node* node, +NodeGraphicsObject(Node& node, NodeState& nodeState, NodeGeometry& nodeGeometry) : _node(node) @@ -24,26 +25,40 @@ NodeGraphicsObject(Node* node, // TODO: Pass state to geometry - auto effect = new QGraphicsDropShadowEffect; - effect->setOffset(4, 4); - effect->setBlurRadius(20); - effect->setColor(QColor(Qt::gray).darker(800)); + { + auto effect = new QGraphicsDropShadowEffect; + effect->setOffset(4, 4); + effect->setBlurRadius(20); + effect->setColor(QColor(Qt::gray).darker(800)); - setGraphicsEffect(effect); + setGraphicsEffect(effect); - setOpacity(_nodeGeometry.opacity()); -} + setOpacity(_nodeGeometry.opacity()); + } + FlowScene &flowScene = FlowScene::instance(); + flowScene.addItem(this); -void -NodeGraphicsObject:: -initializeNode() -{ setAcceptHoverEvents(true); //embedQWidget(); _nodeGeometry.recalculateSize(); + + { + constexpr int spread = 700; + + moveBy(std::rand() % spread - spread / 2, + std::rand() % spread - spread / 2); + } +} + + +Node* +NodeGraphicsObject:: +node() +{ + return &_node; } @@ -70,94 +85,6 @@ boundingRect() const } -QPointF -NodeGraphicsObject:: -connectionPointScenePosition(std::pair address, - EndType endType) const -{ - return mapToScene(_nodeGeometry.connectionPointScenePosition(address.second, - endType)); -} - - -QPointF -NodeGraphicsObject:: -connectionPointScenePosition(int index, - EndType endType) const -{ - return mapToScene(_nodeGeometry.connectionPointScenePosition(index, - endType)); -} - - -void -NodeGraphicsObject:: -reactToPossibleConnection(EndType, - QPointF const &scenePoint) -{ - _nodeGeometry.setDraggingPosition(mapFromScene(scenePoint)); -} - - -bool -NodeGraphicsObject:: -canConnect(EndType draggingEnd, QPointF const &scenePoint) -{ - int hit = checkHitScenePoint(draggingEnd, scenePoint); - - auto &entries = _nodeState.getEntries(draggingEnd); - - return ((hit >= 0) && - _nodeState.connectionID(draggingEnd, hit).isNull()); -} - - -std::pair -NodeGraphicsObject:: -connect(Connection const* connection, - EndType draggingEnd, - int hit) -{ - _nodeState.setConnectionId(draggingEnd, hit, connection->id()); - - QObject::connect(this, &NodeGraphicsObject::itemMoved, - connection->getConnectionGraphicsObject(), - &ConnectionGraphicsObject::onItemMoved); - - connection->getConnectionGraphicsObject()->setZValue(-1.0); - - auto address = std::make_pair(_id, hit); - - return address; -} - - -std::pair -NodeGraphicsObject:: -connect(Connection const* connection, - EndType draggingEnd, - QPointF const & scenePoint) -{ - int hit = checkHitScenePoint(draggingEnd, scenePoint); - - return connect(connection, draggingEnd, hit); -} - - -void -NodeGraphicsObject:: -disconnect(Connection const* connection, - EndType endType, - int hit) -{ - QObject::disconnect(this, &NodeGraphicsObject::itemMoved, - connection->getConnectionGraphicsObject(), - &ConnectionGraphicsObject::onItemMoved); - - _nodeState.setConnectionId(endType, hit, QUuid()); -} - - void NodeGraphicsObject:: paint(QPainter * painter, @@ -170,76 +97,6 @@ paint(QPainter * painter, } -// todo make unsigned, define invalid # -int -NodeGraphicsObject:: -checkHitScenePoint(EndType endType, - QPointF const point) const -{ - - switch (endType) - { - case EndType::SINK: - return checkHitSinkScenePoint(point); - break; - - case EndType::SOURCE: - return checkHitSourceScenePoint(point); - break; - - default: - break; - } - - return -1; -} - - -int -NodeGraphicsObject:: -checkHitSinkScenePoint(const QPointF eventPoint) const -{ - int result = -1; - - auto diameter = _nodeGeometry.connectionPointDiameter(); - double tolerance = 2.0 * diameter; - - for (size_t i = 0; i < _nodeState.getEntries(EndType::SINK).size(); ++i) - { - QPointF p = connectionPointScenePosition(i, EndType::SINK) - eventPoint; - - auto distance = std::sqrt(QPointF::dotProduct(p, p)); - - if (distance < tolerance) - result = i; - } - - return result; -} - - -int -NodeGraphicsObject:: -checkHitSourceScenePoint(const QPointF eventPoint) const -{ - int result = -1; - - auto diameter = _nodeGeometry.connectionPointDiameter(); - double tolerance = 2.0 * diameter; - - for (size_t i = 0; i < _nodeState.getEntries(EndType::SOURCE).size(); ++i) - { - QPointF p = connectionPointScenePosition(i, EndType::SOURCE) - eventPoint; - auto distance = std::sqrt(QPointF::dotProduct(p, p)); - - if (distance < tolerance) - result = i; - } - - return result; -} - - void NodeGraphicsObject:: mousePressEvent(QGraphicsSceneMouseEvent * event) @@ -247,13 +104,13 @@ mousePressEvent(QGraphicsSceneMouseEvent * event) auto clickEnd = [&](EndType endToCheck) { - int hit = checkHitScenePoint(endToCheck, - event->scenePos()); + int hit = _nodeGeometry.checkHitScenePoint(endToCheck, + event->scenePos(), + _nodeState, + sceneTransform()); FlowScene &flowScene = FlowScene::instance(); - std::cout << "HIT " << hit << std::endl; - if (hit >= 0) { QUuid const id = _nodeState.connectionID(endToCheck, hit); @@ -263,14 +120,12 @@ mousePressEvent(QGraphicsSceneMouseEvent * event) // todo add to FlowScene auto connection = flowScene.createConnection(); - connect(connection, endToCheck, hit); + _node.connect(connection, endToCheck, hit); - auto address = std::make_pair(_id, hit); - - auto conPoint = connectionPointScenePosition(address, endToCheck); + auto address = std::make_pair(_node.id(), hit); connection->setDraggingEnd(endToCheck); - connection->connectToNode(address, conPoint); + connection->connectToNode(address); connection->setDraggingEnd(oppositeEnd(endToCheck)); } @@ -278,7 +133,7 @@ mousePressEvent(QGraphicsSceneMouseEvent * event) { auto connection = flowScene.getConnection(id); - disconnect(connection, endToCheck, hit); + _node.disconnect(connection, endToCheck, hit); connection->setDraggingEnd(endToCheck); } @@ -299,7 +154,7 @@ mouseMoveEvent(QGraphicsSceneMouseEvent * event) QPointF d = event->pos() - event->lastPos(); if (event->lastPos() != event->pos()) - emit itemMoved(_id, d); + emit itemMoved(_node.id(), d); QGraphicsObject::mouseMoveEvent(event); } diff --git a/src/NodeGraphicsObject.hpp b/src/NodeGraphicsObject.hpp index 918de64..9c7aaad 100644 --- a/src/NodeGraphicsObject.hpp +++ b/src/NodeGraphicsObject.hpp @@ -16,41 +16,14 @@ class NodeGraphicsObject : public QGraphicsObject Q_OBJECT public: - NodeGraphicsObject(Node* node, + NodeGraphicsObject(Node& node, NodeState& nodeState, NodeGeometry& nodeGeometry); - void initializeNode(); + Node* node(); QRectF boundingRect() const override; -public: - - QPointF connectionPointScenePosition(std::pair address, - EndType endType) const; - - QPointF connectionPointScenePosition(int index, - EndType type) const; - - void reactToPossibleConnection(EndType draggingEnd, - QPointF const &scenePoint); - - bool canConnect(EndType draggingEnd, QPointF const &scenePoint); - - std::pair - connect(Connection const* connection, - EndType draggingEnd, - int hit); - - std::pair - connect(Connection const* connection, - EndType draggingEnd, - QPointF const& scenePoint); - - void disconnect(Connection const* connection, - EndType endType, - int hit); - signals: void itemMoved(QUuid, QPointF const &); @@ -70,18 +43,10 @@ protected: private: void embedQWidget(); - int checkHitScenePoint(EndType endType, - QPointF const eventPoint) const; - - int checkHitSinkScenePoint(QPointF const eventPoint) const; - - int checkHitSourceScenePoint(QPointF const eventPoint) const; - private: // addressing - Node* _node; - + Node& _node; NodeState& _nodeState; diff --git a/src/NodePainter.cpp b/src/NodePainter.cpp index 821c25f..79fa862 100644 --- a/src/NodePainter.cpp +++ b/src/NodePainter.cpp @@ -1,12 +1,10 @@ #include "NodePainter.hpp" +#include + #include "NodeGeometry.hpp" #include "NodeState.hpp" -#include "FlowItemEntry.hpp" - -#include - void NodePainter:: paint(QPainter* painter,