Commit 6ebf501a authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[ADD #292] now using WQtNetworkArrow for dragging new connections.

parent 786edff4
......@@ -33,6 +33,13 @@
#include <QtGui/QStyleOptionGraphicsItem>
#include <QtGui/QPainterPath>
#include "core/kernel/combiner/WApplyCombiner.h"
#include "../WQt4Gui.h"
#include "../WMainWindow.h"
#include "WQtNetworkScene.h"
#include "WQtNetworkEditor.h"
#include "WQtNetworkInputPort.h"
#include "WQtNetworkOutputPort.h"
......@@ -57,7 +64,10 @@ WQtNetworkArrow::WQtNetworkArrow( WQtNetworkOutputPort *startPort, WQtNetworkInp
WQtNetworkArrow::~WQtNetworkArrow()
{
m_startPort->removeArrow( this );
m_endPort->removeArrow( this );
if( m_endPort )
{
m_endPort->removeArrow( this );
}
}
int WQtNetworkArrow::type() const
......@@ -65,10 +75,53 @@ int WQtNetworkArrow::type() const
return Type;
}
WQtNetworkInputPort* WQtNetworkArrow::findNearestCompatibleInput( QPointF pos, float maxDistance )
{
WQtNetworkScene* scene = WQt4Gui::getMainWindow()->getNetworkEditor()->getScene();
// find items in area:
QList<QGraphicsItem *> items = scene->items( pos.x() - ( maxDistance / 2.0 ),
pos.y() - ( maxDistance / 2.0 ),
maxDistance, maxDistance );
// find all the connectors:
WQtNetworkInputPort* nearest = NULL;
float nearestDist = maxDistance;
for( int i = 0; i < items.size(); ++i )
{
QGraphicsItem* item = items[ i ];
// is this a connector?
WQtNetworkInputPort* con = dynamic_cast< WQtNetworkInputPort* >( item );
if( !con )
{
continue;
}
// is it compatible?
if( !con->getConnector()->connectable( m_startPort->getConnector() ) )
{
continue;
}
// nearer than the previous one?
QPointF conPos = mapFromItem( con, con->rect().bottomRight() * 0.5 );
QPointF vec = pos - conPos;
float dist = sqrt( ( vec.x() * vec.x() ) + ( vec.y() * vec.y() ) );
// as we want euclidean dist:
if( nearestDist >= dist )
{
nearestDist = dist;
nearest = con;
}
}
return nearest;
}
void WQtNetworkArrow::updatePosition( QPointF deviate )
{
QRectF eRect = m_startPort->rect();
updatePosition( mapFromItem( m_endPort, eRect.bottomRight() * 0.5 ), deviate );
updatePosition( mapFromItem( m_endPort, m_startPort->rect().bottomRight() * 0.5 ), deviate );
}
void WQtNetworkArrow::updatePosition( QPointF targetPoint, QPointF deviate )
......@@ -160,7 +213,6 @@ void WQtNetworkArrow::hoverEnterEvent( QGraphicsSceneHoverEvent * event )
Q_UNUSED( event );
changeColor( Qt::black, 3 );
updatePosition();
}
void WQtNetworkArrow::hoverLeaveEvent( QGraphicsSceneHoverEvent * event )
......@@ -205,67 +257,105 @@ void WQtNetworkArrow::mouseDoubleClickEvent( QGraphicsSceneMouseEvent* mouseEven
}
}
void WQtNetworkArrow::mousePressEvent( QGraphicsSceneMouseEvent *mouseEvent )
void WQtNetworkArrow::startDrag( const QPointF& pos )
{
if( mouseEvent->button() != Qt::LeftButton )
{
mouseEvent->ignore();
return;
}
mouseEvent->accept();
m_snappedOff = false;
m_connectionDisconnect = false;
m_connectTo = NULL;
// highlight
changeColor( owGreen, 3 );
// clickPoint
m_clickPoint = mouseEvent->pos();
// click Point
m_clickPoint = pos;
}
void WQtNetworkArrow::mouseMoveEvent( QGraphicsSceneMouseEvent *mouseEvent )
void WQtNetworkArrow::moveDrag( const QPointF& pos )
{
mouseEvent->accept();
m_connectionDisconnect = false;
m_connectTo = NULL;
QPointF currentPoint = mouseEvent->pos();
QPointF currentPoint = pos;
// deviate according to start pos
QPointF deviate = currentPoint - m_clickPoint;
float l = sqrt( ( deviate.x() * deviate.x() ) + ( deviate.y() * deviate.y() ) );
// if moved far enough, snap to mouse
m_snappedOff = m_snappedOff || ( l > 100.0 ); // when snapped of once, never snap on again
// NOTE: always be snapped of if there is no endport
m_snappedOff = !m_endPort || m_snappedOff || ( l > 100.0 ); // when snapped of once, never snap on again
// are we near the original connector?
QPointF diffToConnector = currentPoint - mapFromItem( m_endPort, m_endPort->rect().bottomRight() * 0.5 );
float lDiffToConnector = sqrt( ( diffToConnector.x() * diffToConnector.x() ) + ( diffToConnector.y() * diffToConnector.y() ) );
bool snapBack = ( lDiffToConnector < 50.0 );
if( m_snappedOff && !snapBack )
if( m_snappedOff )
{
updatePosition( currentPoint, QPointF() );
changeColor( owRed, 3 );
// can we snap somewhere?
WQtNetworkInputPort* nearestPort = findNearestCompatibleInput( currentPoint, 50.0 );
if( nearestPort )
{
changeColor( owGreen, 3 );
m_connectTo = nearestPort;
updatePosition( mapFromItem( nearestPort, nearestPort->rect().bottomRight() * 0.5 ), QPointF() );
}
else
{
m_connectionDisconnect = true;
updatePosition( currentPoint, QPointF() );
}
}
else
{
// m_snappedOff is defined to ensure that we have m_endPoint if not snapped
updatePosition( deviate );
}
}
if( snapBack )
void WQtNetworkArrow::doneDrag( const QPointF& /*pos*/ )
{
if( m_endPort && ( m_connectTo == m_endPort ) )
{
changeColor( owGreen, 3 );
updatePosition();
changeColor( Qt::black );
m_connectTo = NULL;
m_connectionDisconnect = false;
return;
}
if( m_snappedOff && !snapBack )
// apply operations
if( m_connectTo )
{
changeColor( owRed, 3 );
m_connectionDisconnect = true;
// connect new
boost::shared_ptr< WApplyCombiner > x = boost::shared_ptr< WApplyCombiner >( new WApplyCombiner(
m_startPort->getConnector()->getModule(),
m_startPort->getConnector()->getName(),
m_connectTo->getConnector()->getModule(),
m_connectTo->getConnector()->getName() ) );
// remove old connection if needed
if( m_endPort )
{
m_startPort->getConnector()->disconnect( m_endPort->getConnector() );
}
// apply combiner
x->run();
return;
}
// disconnect?
if( m_connectionDisconnect && m_endPort )
{
m_startPort->getConnector()->disconnect( m_endPort->getConnector() );
m_connectionDisconnect = false;
return;
}
m_connectionDisconnect = false;
m_connectTo = NULL;
}
void WQtNetworkArrow::mouseReleaseEvent( QGraphicsSceneMouseEvent *mouseEvent )
void WQtNetworkArrow::mousePressEvent( QGraphicsSceneMouseEvent *mouseEvent )
{
if( mouseEvent->button() != Qt::LeftButton )
{
......@@ -274,13 +364,24 @@ void WQtNetworkArrow::mouseReleaseEvent( QGraphicsSceneMouseEvent *mouseEvent )
}
mouseEvent->accept();
updatePosition();
changeColor( Qt::black );
startDrag( mouseEvent->pos() );
}
void WQtNetworkArrow::mouseMoveEvent( QGraphicsSceneMouseEvent *mouseEvent )
{
mouseEvent->accept();
moveDrag( mouseEvent->pos() );
}
// what to do
if( m_connectionDisconnect )
void WQtNetworkArrow::mouseReleaseEvent( QGraphicsSceneMouseEvent *mouseEvent )
{
if( mouseEvent->button() != Qt::LeftButton )
{
m_startPort->getConnector()->disconnect( m_endPort->getConnector() );
mouseEvent->ignore();
return;
}
mouseEvent->accept();
doneDrag( mouseEvent->pos() );
}
......@@ -104,6 +104,16 @@ public:
*/
WQtNetworkInputPort* getEndPort();
/**
* Search the next, compatible input port.
*
* \param pos the current position for which to search
* \param maxDistance the maximum distance
*
* \return the connector, or NULL if none.
*/
WQtNetworkInputPort* findNearestCompatibleInput( QPointF pos, float maxDistance = 100 );
/**
* Reimplementation form QGraphicsItem, because the arrowhead is added
* to the line. Its needed that QGraphicsView knows which area needs to
......@@ -128,6 +138,26 @@ public:
*/
QVariant itemChange( GraphicsItemChange change, const QVariant &value );
/**
* Start Drag.
*
* \param pos the position in scene
*/
void startDrag( const QPointF& pos );
/**
* Update drag position
*
* \param pos the position in scene
*/
void moveDrag( const QPointF& pos );
/**
* Called when releasing the mouse.
*
* \param pos the position in scene
*/
void doneDrag( const QPointF& pos );
protected:
/**
......@@ -214,5 +244,7 @@ private:
bool m_snappedOff; //!< gets true once the arrow was pulled far away from original click position.
bool m_connectionDisconnect; //!< disconnect if true.
WQtNetworkInputPort* m_connectTo; //!< connect to this port after mouse release.
};
#endif // WQTNETWORKARROW_H
......@@ -41,7 +41,7 @@ WQtNetworkPort::WQtNetworkPort()
m_brushNotSet = true;
setAcceptsHoverEvents( true );
m_line = NULL;
m_arrow = NULL;
}
WQtNetworkPort::~WQtNetworkPort()
......@@ -68,24 +68,32 @@ void WQtNetworkPort::paint( QPainter* painter, const QStyleOptionGraphicsItem* o
QGraphicsRectItem::paint( painter, option, widget );
}
void WQtNetworkPort::mousePressEvent( QGraphicsSceneMouseEvent *mouseEvent )
void WQtNetworkPort::mouseDoubleClickEvent( QGraphicsSceneMouseEvent* mouseEvent )
{
QGraphicsItem::mouseDoubleClickEvent( mouseEvent );
// ignore all buttons but the left one
if( mouseEvent->button() != Qt::LeftButton )
{
mouseEvent->ignore();
return;
}
QList<QGraphicsItem *> startItem = scene()->items( mouseEvent->scenePos() );
if( !startItem.isEmpty() )
{
mouseEvent->accept();
if( startItem.first()->type() == WQtNetworkOutputPort::Type &&
startItem.first()->parentItem()->isEnabled() == true )
WQtNetworkOutputPort* outP = dynamic_cast< WQtNetworkOutputPort* >( startItem.first() );
WQtNetworkInputPort* inP = dynamic_cast< WQtNetworkInputPort* >( startItem.first() );
// delete all connections
if( inP )
{
m_line = new QGraphicsLineItem( QLineF( mouseEvent->scenePos(),
mouseEvent->scenePos() ) );
m_line->setPen( QPen( Qt::black, 2 ) );
scene()->addItem( m_line );
inP->getConnector()->disconnectAll();
}
if( outP )
{
outP->getConnector()->disconnectAll();
}
}
else
......@@ -94,31 +102,24 @@ void WQtNetworkPort::mousePressEvent( QGraphicsSceneMouseEvent *mouseEvent )
}
}
void WQtNetworkPort::mouseDoubleClickEvent( QGraphicsSceneMouseEvent* mouseEvent )
void WQtNetworkPort::mousePressEvent( QGraphicsSceneMouseEvent *mouseEvent )
{
QGraphicsItem::mouseDoubleClickEvent( mouseEvent );
// ignore all buttons but the left one
if( mouseEvent->button() != Qt::LeftButton )
{
mouseEvent->ignore();
return;
}
QList<QGraphicsItem *> startItem = scene()->items( mouseEvent->scenePos() );
if( !startItem.isEmpty() )
{
mouseEvent->accept();
WQtNetworkOutputPort* outP = dynamic_cast< WQtNetworkOutputPort* >( startItem.first() );
WQtNetworkInputPort* inP = dynamic_cast< WQtNetworkInputPort* >( startItem.first() );
// delete all connections
if( inP )
{
inP->getConnector()->disconnectAll();
}
if( outP )
if( startItem.first()->type() == WQtNetworkOutputPort::Type &&
startItem.first()->parentItem()->isEnabled() == true )
{
outP->getConnector()->disconnectAll();
// use might have started to drag
m_arrow = new WQtNetworkArrow( qgraphicsitem_cast< WQtNetworkOutputPort* >( startItem.first() ), NULL );
m_arrow->startDrag( mouseEvent->scenePos() );
scene()->addItem( m_arrow );
}
}
else
......@@ -129,57 +130,9 @@ void WQtNetworkPort::mouseDoubleClickEvent( QGraphicsSceneMouseEvent* mouseEvent
void WQtNetworkPort::mouseMoveEvent( QGraphicsSceneMouseEvent *mouseEvent )
{
if( m_line )
if( m_arrow )
{
QLineF newLine( m_line->line().p1(), mouseEvent->scenePos() );
QList<QGraphicsItem *> endItem = scene()->items( mouseEvent->scenePos() );
// because m_line is first item below the curser
if( !endItem.isEmpty() &&
endItem.first()->type() == QGraphicsLineItem::Type )
{
endItem.removeFirst();
}
if( !endItem.isEmpty() )
{
if( endItem.first()->type() == WQtNetworkInputPort::Type )
{
WQtNetworkInputPort *endPort = qgraphicsitem_cast<WQtNetworkInputPort *>( endItem.first() );
QList<QGraphicsItem *> startItems = scene()->items( m_line->line().p1() );
if( startItems.first()->type() == QGraphicsLineItem::Type )
{
startItems.removeFirst();
}
WQtNetworkOutputPort *startPort = qgraphicsitem_cast<WQtNetworkOutputPort *>( startItems.first() );
if( endPort->parentItem() != this->parentItem() &&
endPort->parentItem()->isEnabled() == true &&
endPort->getConnector()->connectable( startPort->getConnector() ) == true
)
{
m_line->setPen( QPen( Qt::green, 2 ) );
}
else
{
m_line->setPen( QPen( Qt::red, 2 ) );
}
}
else if( endItem.first()->type() == WQtNetworkOutputPort::Type )
{
m_line->setPen( QPen( Qt::red, 2 ) );
}
else
{
m_line->setPen( QPen( Qt::black, 2 ) );
}
}
else
{
m_line->setPen( QPen( Qt::black, 2 ) );
}
m_line->setLine( newLine );
m_arrow->moveDrag( mouseEvent->scenePos() );
}
}
......@@ -187,46 +140,11 @@ void WQtNetworkPort::mouseReleaseEvent( QGraphicsSceneMouseEvent *mouseEvent )
{
Q_UNUSED( mouseEvent );
if( m_line != 0 )
if( m_arrow )
{
QList<QGraphicsItem *> startItems = scene()->items( m_line->line().p1() );
QList<QGraphicsItem *> endItems = scene()->items( m_line->line().p2() );
// because m_line is first item below the curser
if( startItems.first()->type() == QGraphicsLineItem::Type )
{
startItems.removeFirst();
}
// because m_line is first item below the curser
if( endItems.first()->type() == QGraphicsLineItem::Type )
{
endItems.removeFirst();
}
// remove current m_line for real connection
scene()->removeItem( m_line );
delete m_line;
if( !endItems.isEmpty() &&
!startItems.isEmpty() &&
endItems.first()->type() == WQtNetworkInputPort::Type &&
endItems.first()->parentItem()->isEnabled() == true &&
startItems.first()->parentItem() != endItems.first()->parentItem() )
{
WQtNetworkOutputPort *startPort = dynamic_cast<WQtNetworkOutputPort *>( startItems.first() );
WQtNetworkInputPort *endPort = dynamic_cast<WQtNetworkInputPort *>( endItems.first() );
if( endPort->getConnector()->connectable( startPort->getConnector() ) == true )
{
boost::shared_ptr< WApplyCombiner > x = boost::shared_ptr< WApplyCombiner >( new WApplyCombiner(
startPort->getConnector()->getModule(),
startPort->getConnector()->getName(),
endPort->getConnector()->getModule(),
endPort->getConnector()->getName() ) );
x->run();
}
}
m_arrow->doneDrag( mouseEvent->scenePos() );
scene()->removeItem( m_arrow );
delete m_arrow;
}
}
......
......@@ -185,7 +185,10 @@ protected:
QString m_name; //!< the portname
private:
QGraphicsLineItem * m_line; //!< the temporary line when you connect two ports
/**
* The arrow used to connect items
*/
WQtNetworkArrow* m_arrow;
bool m_brushNotSet; //!< used to indicate that the correct brush was not yet set.
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment