Split Node and NodeGraphicsObject

This commit is contained in:
Dmitry Pinaev
2015-12-20 17:46:00 +01:00
parent e54247efe5
commit 73577268e2
12 changed files with 289 additions and 420 deletions
+20 -6
View File
@@ -6,10 +6,12 @@
#include <QtWidgets/QtWidgets>
#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<QUuid, int> const &address,
QPointF const& scenePoint)
connectToNode(std::pair<QUuid, int> 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);
+2 -2
View File
@@ -38,8 +38,8 @@ public:
bool tryConnectToNode(Node* node, QPointF const& scenePoint);
/// Node initiates
void connectToNode(std::pair<QUuid, int> const &address,
QPointF const& scenePoint);
void connectToNode(std::pair<QUuid, int> const &address);
//QPointF const& scenePoint);
ConnectionGraphicsObject* getConnectionGraphicsObject() const;
-74
View File
@@ -1,74 +0,0 @@
#include "FlowItemEntry.hpp"
#include <QtGui/QPainter>
#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());
}
-83
View File
@@ -1,83 +0,0 @@
#ifndef FLOW_ITEM_ENTRY_H
#define FLOW_ITEM_ENTRY_H
#include <iostream>
#include <QtWidgets/QGraphicsObject>
#include <QtWidgets/QGraphicsSceneMoveEvent>
#include <QtCore/QUuid>
#include <QtCore/QWeakPointer>
#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
+6 -15
View File
@@ -5,6 +5,8 @@
#include <QtWidgets/QGraphicsSceneMoveEvent>
#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<Node*>(item);
return (dynamic_cast<NodeGraphicsObject*>(item) != nullptr);
});
if (filteredItems.empty())
return nullptr;
Node* flowItem = dynamic_cast<Node*>(filteredItems.front());
return flowItem;
return dynamic_cast<NodeGraphicsObject*>(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();
+130 -2
View File
@@ -1,10 +1,16 @@
#include "Node.hpp"
#include <QtCore/QObject>
#include <iostream>
#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<QUuid, int>
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<QUuid, int>
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;
}
+36 -5
View File
@@ -6,8 +6,11 @@
#include <QtCore/QObject>
#include <QtCore/QUuid>
#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<QUuid, int>
connect(Connection const* connection,
EndType draggingEnd,
int hit);
std::pair<QUuid, int>
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<NodeImpl> _impl;
};
#endif // NODE_HPP
+40 -5
View File
@@ -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;
}
+10 -1
View File
@@ -3,9 +3,12 @@
#include <QtCore/QRectF>
#include <QtCore/QPointF>
#include <QtGui/QTransform>
#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;
+40 -185
View File
@@ -1,18 +1,19 @@
#include "NodeGraphicsObject.hpp"
#include <QtWidgets/QtWidgets>
#include <QtWidgets/QGraphicsEffect>
#include <iostream>
#include <cstdlib>
#include <QtWidgets/QtWidgets>
#include <QtWidgets/QGraphicsEffect>
#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<QUuid, int> 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<QUuid, int>
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<QUuid, int>
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);
}
+3 -38
View File
@@ -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<QUuid, int> 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<QUuid, int>
connect(Connection const* connection,
EndType draggingEnd,
int hit);
std::pair<QUuid, int>
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;
+2 -4
View File
@@ -1,12 +1,10 @@
#include "NodePainter.hpp"
#include <QtCore/QMargins>
#include "NodeGeometry.hpp"
#include "NodeState.hpp"
#include "FlowItemEntry.hpp"
#include <QtCore/QMargins>
void
NodePainter::
paint(QPainter* painter,