#include "Edge.h"
#include "Node.h"
+#include <QPainter>
+
// -------------------------------------------------------------------------
PipelineEditor::Edge::
-Edge( PipelineEditor::Node* src, PipelineEditor::Node* des )
- : QGraphicsItem( NULL ),
- m_ArrowSize( 10 )
+Edge(
+ const Node* nsrc, const Node* ndes,
+ const QRectF* rsrc, const QRectF* rdes
+ )
+ : QGraphicsItem( NULL )
{
this->setAcceptedMouseButtons( 0 );
- this->m_Source = src;
- this->m_Destination = des;
- this->m_Source->addEdge( this );
- this->m_Destination->addEdge( this );
- // TODO: this->setToolTip( "Edge!!!" );
+ this->m_SrcNode = nsrc;
+ this->m_DesNode = ndes;
+ this->m_SrcRect = rsrc;
+ this->m_DesRect = rdes;
this->adjust( );
}
}
// -------------------------------------------------------------------------
-PipelineEditor::Node* PipelineEditor::Edge::
-sourceNode( ) const
+const QRectF* PipelineEditor::Edge::
+source( ) const
{
- return( this->m_Source );
+ return( this->m_SrcRect );
}
// -------------------------------------------------------------------------
-PipelineEditor::Node* PipelineEditor::Edge::
-destinationNode( ) const
+const QRectF* PipelineEditor::Edge::
+destination( ) const
{
- return( this->m_Destination );
+ return( this->m_DesRect );
}
// -------------------------------------------------------------------------
void PipelineEditor::Edge::
adjust( )
{
- if( this->m_Source == NULL || this->m_Destination == NULL )
- return;
- QLineF line(
- mapFromItem( this->m_Source, 0, 0 ),
- mapFromItem( this->m_Destination, 0, 0 )
- );
- qreal length = line.length( );
-
- this->prepareGeometryChange( );
-
- if( length > qreal( 20 ) )
- {
- QPointF edgeOffset(
- ( line.dx( ) * qreal( 10 ) ) / length,
- ( line.dy( ) * qreal( 10 ) ) / length
- );
- this->m_SourcePoint = line.p1( ) + edgeOffset;
- this->m_DestinationPoint = line.p2( ) - edgeOffset;
- }
- else
- this->m_SourcePoint = this->m_DestinationPoint = line.p1( );
+ /* TODO
+ if( this->m_Src == NULL || this->m_Des == NULL )
+ return;
+
+ QLineF line(
+ this->mapFromParent( this->m_Src->center( ) ),
+ this->mapFromParent( this->m_Des->center( ) )
+ );
+ // TODO: qreal length = line.length( );
+ this->prepareGeometryChange( );
+ if( length > qreal( 20 ) )
+ {
+ QPointF edgeOffset(
+ ( line.dx( ) * qreal( 10 ) ) / length,
+ ( line.dy( ) * qreal( 10 ) ) / length
+ );
+ this->m_SrcPoint = line.p1( ) + edgeOffset;
+ this->m_DesPoint = line.p2( ) - edgeOffset;
+ }
+ else
+ this->m_SrcPoint = this->m_DesPoint = line.p1( );
+ */
}
// -------------------------------------------------------------------------
QRectF PipelineEditor::Edge::
boundingRect( ) const
{
- if( this->m_Source == NULL || this->m_Destination == NULL )
+ if( this->m_SrcRect == NULL || this->m_DesRect == NULL )
return( QRectF( ) );
- qreal penWidth = 1;
- qreal extra = ( penWidth + this->m_ArrowSize ) / qreal( 2 );
-
+ /*
+ qreal penWidth = 1;
+ qreal extra = ( penWidth + this->m_ArrowSize ) / qreal( 2 );
+ */
+ qreal extra = qreal( 1 );
return(
QRectF(
- this->m_SourcePoint,
+ this->m_SrcRect->center( ),
QSizeF(
- this->m_DestinationPoint.x( ) - this->m_SourcePoint.x( ),
- this->m_DestinationPoint.y( ) - this->m_SourcePoint.y( )
+ this->m_DesRect->center( ).x( ) - this->m_SrcRect->center( ).x( ),
+ this->m_DesRect->center( ).y( ) - this->m_SrcRect->center( ).y( )
)
).normalized( ).adjusted( -extra, -extra, extra, extra )
);
)
{
/* TODO
- if (!source || !dest)
- return;
-
- QLineF line(sourcePoint, destPoint);
- if (qFuzzyCompare(line.length(), qreal(0.)))
- return;
-
- // Draw the line itself
- painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
- painter->drawLine(line);
-
- // Draw the arrows
- double angle = ::acos(line.dx() / line.length());
- if (line.dy() >= 0)
- angle = TwoPi - angle;
-
- QPointF destArrowP1 = destPoint + QPointF(
- sin(angle - Pi / 3) * arrowSize,
- cos(angle - Pi / 3) * arrowSize
- );
- QPointF destArrowP2 = destPoint + QPointF(
- sin(angle - Pi + Pi / 3) * arrowSize,
- cos(angle - Pi + Pi / 3) * arrowSize
- );
- QPointF center = sourcePoint + destPoint;
- center /= 2;
-
- painter->setBrush(Qt::black);
- painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2);
- painter->drawText( center, "Edge!!!" );
+ if( this->m_Src == NULL || this->m_Des == NULL )
+ return;
+ */
+
+ // TODO: QLineF line( this->m_Src->center( ), this->m_Des->center( ) );
+ QLineF line(
+ this->m_SrcNode->mapToScene( this->m_SrcRect->center( ) ),
+ this->m_DesNode->mapToScene( this->m_DesRect->center( ) )
+ );
+
+ if( qFuzzyCompare( line.length(), qreal( 0 ) ) )
+ return;
+
+ // Draw the line itself
+ painter->setPen(
+ QPen( Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin )
+ );
+ painter->drawLine( line );
+
+ /* TODO
+ // Draw the arrows
+ double angle = ::acos(line.dx() / line.length());
+ if (line.dy() >= 0)
+ angle = TwoPi - angle;
+
+ QPointF destArrowP1 = destPoint + QPointF(
+ sin(angle - Pi / 3) * arrowSize,
+ cos(angle - Pi / 3) * arrowSize
+ );
+ QPointF destArrowP2 = destPoint + QPointF(
+ sin(angle - Pi + Pi / 3) * arrowSize,
+ cos(angle - Pi + Pi / 3) * arrowSize
+ );
+ QPointF center = sourcePoint + destPoint;
+ center /= 2;
+
+ painter->setBrush(Qt::black);
+ painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2);
+ painter->drawText( center, "Edge!!!" );
*/
}
#include <QGraphicsSceneHoverEvent>
#include <cpPlugins/Interface/Object.h>
+#include <cpPlugins/Interface/DataObject.h>
#include <cpPlugins/Interface/ProcessObject.h>
-#define PORT_SIZE 10
+#define PORT_SIZE 15
// -------------------------------------------------------------------------
PipelineEditor::Node::
: QGraphicsItem( NULL ),
m_Canvas( canvas ),
m_Object( object ),
- m_UpdatedBounds( false )
+ m_SelectedPort( NULL ),
+ m_DraggingPort( false )
{
- this->setFlag( QGraphicsItem::ItemIsMovable );
- this->setFlag( QGraphicsItem::ItemSendsGeometryChanges );
+ this->setFlag( QGraphicsItem::ItemIsMovable, true );
+ this->setFlag( QGraphicsItem::ItemSendsGeometryChanges, true );
this->setCacheMode( QGraphicsItem::DeviceCoordinateCache );
this->setAcceptHoverEvents( true );
+ this->setAcceptDrops( true );
this->setZValue( -1 );
- this->setToolTip( this->m_Object->GetName( ) );
+ this->updateRepresentation( );
}
// -------------------------------------------------------------------------
}
// -------------------------------------------------------------------------
-QRectF PipelineEditor::Node::
-boundingRect( ) const
+void PipelineEditor::Node::
+updateRepresentation( )
{
+ typedef cpPlugins::Interface::DataObject _TData;
typedef cpPlugins::Interface::ProcessObject _TFilter;
- if( !this->m_UpdatedBounds )
+
+ if( this->m_Object == NULL )
+ return;
+
+ // Try to infere type
+ _TData* d = dynamic_cast< _TData* >( this->m_Object );
+ _TFilter* f = dynamic_cast< _TFilter* >( this->m_Object );
+ if( d == NULL && f == NULL )
+ return;
+
+ // Label and its bounds
+ QFontMetricsF fm( this->m_Canvas->font( ) );
+ this->m_Label = this->m_Object->GetName( );
+ this->m_Label += "\n";
+ this->m_Label += this->m_Object->GetClassName( ).c_str( );
+ this->m_Bounds = fm.boundingRect( this->m_Label );
+
+ // Create ports representation
+ this->m_Inputs.clear( );
+ this->m_Outputs.clear( );
+ this->m_InputPorts.clear( );
+ this->m_OutputPorts.clear( );
+ if( f != NULL )
{
- // Text bounding box
- QFontMetricsF fm( this->m_Canvas->font( ) );
- this->m_Label = this->m_Object->GetName( );
- this->m_Label += "\n";
- this->m_Label += this->m_Object->GetClassName( ).c_str( );
-
- // Ports
- this->m_Bounds = fm.boundingRect( this->m_Label );
- const _TFilter* f = dynamic_cast< const _TFilter* >( this->m_Object );
- if( f != NULL )
+ // Get filter's inputs and outputs
+ f->GetInputsNames( this->m_Inputs );
+ f->GetOutputsNames( this->m_Outputs );
+
+ // Correct height
+ unsigned int nIn = this->m_Inputs.size( );
+ unsigned int nOut = this->m_Outputs.size( );
+ qreal n =
+ qreal( ( ( ( ( nIn > nOut )? nIn: nOut ) << 1 ) + 1 ) * PORT_SIZE );
+ qreal h = this->m_Bounds.height( );
+ if( n > h )
+ this->m_Bounds.setHeight( n );
+
+ // Get bounds values
+ qreal rt = this->m_Bounds.top( ) - qreal( PORT_SIZE );
+ qreal rb = this->m_Bounds.bottom( ) + qreal( PORT_SIZE );
+ qreal rl = this->m_Bounds.left( ) - qreal( PORT_SIZE );
+ qreal rr = this->m_Bounds.right( ) + qreal( PORT_SIZE );
+
+ // Add some space to the geometry
+ this->m_Bounds.setTop( rt );
+ this->m_Bounds.setBottom( rb );
+ this->m_Bounds.setLeft( rl );
+ this->m_Bounds.setRight( rr );
+ qreal rh = this->m_Bounds.height( );
+
+ // Create ports
+ QSizeF ps( qreal( PORT_SIZE ), qreal( PORT_SIZE ) );
+ std::set< std::string >* ports[] =
+ { &( this->m_Inputs ), &( this->m_Outputs ) };
+ for( unsigned int pId = 0; pId < 2; ++pId )
{
- unsigned int nIn = f->GetNumberOfInputs( );
- unsigned int nOut = f->GetNumberOfOutputs( );
- qreal n =
- qreal( ( ( ( ( nIn > nOut )? nIn: nOut ) << 1 ) + 1 ) * PORT_SIZE );
- qreal h = this->m_Bounds.height( );
- if( n > h )
- this->m_Bounds.setHeight( n );
-
- // Let some space for ports
- this->m_Bounds.setLeft(
- this->m_Bounds.left( ) - qreal( PORT_SIZE )
- );
- this->m_Bounds.setTop(
- this->m_Bounds.top( ) - qreal( PORT_SIZE )
- );
- this->m_Bounds.setRight(
- this->m_Bounds.right( ) + qreal( PORT_SIZE )
- );
- this->m_Bounds.setBottom(
- this->m_Bounds.bottom( ) + qreal( PORT_SIZE )
- );
+ qreal h = qreal( ( ( ports[ pId ]->size( ) << 1 ) + 1 ) * PORT_SIZE );
+ qreal off = qreal( PORT_SIZE );
+ if( rh > h )
+ off += ( rh - h ) / qreal( 2 );
+ for( auto i = ports[ pId ]->begin( ); i != ports[ pId ]->end( ); ++i )
+ {
+ if( pId == 0 )
+ this->m_InputPorts[ *i ] =
+ QRectF( QPointF( rl, rt + off ), ps );
+ else
+ this->m_OutputPorts[ *i ] =
+ QRectF( QPointF( rr - qreal( PORT_SIZE ), rt + off ), ps );
+ off += qreal( PORT_SIZE < 1 );
+
+ } // rof
- } // fi
- this->m_UpdatedBounds = true;
+ } // rof
} // fi
+
+ // Some other initializations
+ this->m_SelectedPort = NULL;
+}
+
+// -------------------------------------------------------------------------
+QRectF PipelineEditor::Node::
+boundingRect( ) const
+{
return( this->m_Bounds );
}
shape( ) const
{
QPainterPath path;
- path.addRect( this->boundingRect( ) );
+ path.addRect( this->m_Bounds );
return( path );
}
QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget
)
{
- typedef cpPlugins::Interface::ProcessObject _TFilter;
-
+ // Draw main box
QRectF rect = this->boundingRect( );
painter->drawRect( rect );
painter->drawText( rect, Qt::AlignCenter, this->m_Label );
- // Show ports
- const _TFilter* f = dynamic_cast< const _TFilter* >( this->m_Object );
- if( f != NULL )
- {
- QSizeF port_size( qreal( PORT_SIZE ), qreal( PORT_SIZE ) );
- qreal rh = rect.height( );
- qreal rt = rect.top( );
- qreal rl = rect.left( );
- qreal rr = rect.right( );
-
- std::set< std::string > inputs, outputs;
- f->GetInputsNames( inputs );
- f->GetOutputsNames( outputs );
-
- qreal oh = qreal( ( ( inputs.size( ) << 1 ) + 1 ) * PORT_SIZE );
- qreal off = qreal( PORT_SIZE );
- if( rh > oh )
- off += ( rh - oh ) / qreal( 2 );
- for( auto it = inputs.begin( ); it != inputs.end( ); ++it )
- {
- painter->drawRect( QRectF( QPointF( rl, rt + off ), port_size ) );
- off += qreal( PORT_SIZE < 1 );
+ // Draw ports
+ std::map< std::string, QRectF >* ports[] =
+ { &( this->m_InputPorts ), &( this->m_OutputPorts ) };
+ for( unsigned int pId = 0; pId < 2; ++pId )
+ for( auto i = ports[ pId ]->begin( ); i != ports[ pId ]->end( ); ++i )
+ painter->drawRect( i->second );
- } // rof
-
- oh = qreal( ( ( outputs.size( ) << 1 ) + 1 ) * PORT_SIZE );
- off = qreal( PORT_SIZE );
- if( rh > oh )
- off += ( rh - oh ) / qreal( 2 );
- for( auto it = outputs.begin( ); it != outputs.end( ); ++it )
- {
- painter->drawRect(
- QRectF( QPointF( rr - qreal( PORT_SIZE ), rt + off ), port_size )
- );
- off += qreal( PORT_SIZE < 1 );
-
- } // rof
+ // Draw clicked port
+ if( this->m_SelectedPort != NULL )
+ {
+ painter->setBrush( Qt::green );
+ painter->drawEllipse( *( this->m_SelectedPort ) );
} // fi
}
QVariant PipelineEditor::Node::
itemChange( GraphicsItemChange change, const QVariant& value )
{
- /* TODO
- switch( change )
- {
- case QGraphicsItem::ItemPositionHasChanged:
- foreach( Edge* edge, this->m_Edges )
- edge->adjust( );
- this->m_Canvas->itemMoved( );
- break;
- default:
- break;
- } // hctiws
- */
+ switch( change )
+ {
+ case QGraphicsItem::ItemPositionHasChanged:
+ foreach( Edge* edge, this->m_Edges )
+ edge->update( );
+ this->m_Canvas->itemMoved( );
+ break;
+ default:
+ break;
+ } // hctiws
return( this->QGraphicsItem::itemChange( change, value ) );
}
void PipelineEditor::Node::
mousePressEvent( QGraphicsSceneMouseEvent* event )
{
+ if( this->m_SelectedPort != NULL && this->m_Canvas != NULL )
+ {
+ if( event->button( ) == Qt::LeftButton )
+ {
+ QDrag* drag = new QDrag( this->m_Canvas );
+ QMimeData* mimeData = new QMimeData( );
+
+ // mimeData->setText( "drag_data" );
+ qulonglong address = reinterpret_cast< qulonglong >( this );
+ QByteArray ba;
+ ba.setNum( address );
+ mimeData->setData( "source_node", ba );
+ drag->setMimeData( mimeData );
+ // TODO: drag->setPixmap( iconPixmap );
+
+ this->m_DraggingPort = true;
+ Qt::DropAction dropAction = drag->exec( );
+ this->m_DraggingPort = false;
+
+ } // fi
+ }
+ else
+ {
+ } // fi
+
+ /* TODO
+ Qt::MouseButton btn = event->button( );
+ if( btn == Qt::LeftButton )
+ {
+ std::string name = this->toolTip( ).toStdString( );
+ if( name != this->m_Object->GetName( ) )
+ {
+ // Get clicked port, if any
+ QPointF pos = event->buttonDownPos( btn );
+ auto iIt = this->m_InputPorts.find( name );
+ auto oIt = this->m_OutputPorts.find( name );
+ this->m_SelectedPort = NULL;
+ if( iIt != this->m_InputPorts.end( ) )
+ if( iIt->second.contains( pos ) )
+ this->m_SelectedPort = &( iIt->second );
+ if( this->m_SelectedPort == NULL && oIt != this->m_OutputPorts.end( ) )
+ if( oIt->second.contains( pos ) )
+ this->m_SelectedPort = &( oIt->second );
+
+ } // fi
+
+ } // fi
+ */
this->update( );
this->QGraphicsItem::mousePressEvent( event );
}
void PipelineEditor::Node::
hoverMoveEvent( QGraphicsSceneHoverEvent* event )
{
- QPointF pos = event->pos( );
+ this->_selectPort( event->pos( ) );
}
-/* TODO
- private:
- GraphCanvas* m_Canvas;
- QList< Edge* > m_Edges;
- std::string m_Label;
- };
-
- } // ecapseman
-
- #endif // __PIPELINEEDITOR__NODE__H__
-*/
+// -------------------------------------------------------------------------
+void PipelineEditor::Node::
+hoverLeaveEvent( QGraphicsSceneHoverEvent* event )
+{
+ this->_deselectPort( );
+}
-// eof - $RCSfile$
+// -------------------------------------------------------------------------
+void PipelineEditor::Node::
+dragMoveEvent( QGraphicsSceneDragDropEvent* event )
+{
+ this->_selectPort( event->pos( ) );
+}
+// -------------------------------------------------------------------------
+void PipelineEditor::Node::
+dragLeaveEvent( QGraphicsSceneDragDropEvent* event )
+{
+ this->_deselectPort( );
+}
-/*
-QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
+// -------------------------------------------------------------------------
+void PipelineEditor::Node::
+dropEvent( QGraphicsSceneDragDropEvent* event )
{
- switch (change) {
- case ItemPositionHasChanged:
- foreach (Edge *edge, edgeList)
- edge->adjust();
- graph->itemMoved();
- break;
- default:
- break;
- };
+ // Get vertices and directionality
+ bool ok;
+ qulonglong address =
+ event->mimeData( )->data( "source_node" ).toULongLong( &ok );
+ Node* src = reinterpret_cast< Node* >( address );
+ if( src == NULL )
+ return;
+ Node* des = this;
+ if( src->m_SelectedPortIsInput )
+ {
+ des = src;
+ src = this;
+
+ } // fi
- return QGraphicsItem::itemChange(change, value);
+ // Discard if a loop is detected
+ if( src == des )
+ return;
+
+ // Get edge data
+ const QRectF* srcPort = src->m_SelectedPort;
+ const QRectF* desPort = des->m_SelectedPort;
+ std::string srcName = src->m_Object->GetName( );
+ std::string desName = des->m_Object->GetName( );
+ std::string srcPortName = src->toolTip( ).toStdString( );
+ std::string desPortName = des->toolTip( ).toStdString( );
+
+ Edge* e = new Edge( src, des, srcPort, desPort );
+ src->addEdge( e );
+ des->addEdge( e );
+ if( this->m_Canvas != NULL )
+ this->m_Canvas->scene( )->addItem( e );
}
-void Node::mousePressEvent(QGraphicsSceneMouseEvent *event)
+// -------------------------------------------------------------------------
+void PipelineEditor::Node::
+_selectPort( const QPointF& pos )
{
- update();
- QGraphicsItem::mousePressEvent(event);
+ if( this->m_DraggingPort )
+ return;
+
+ const QRectF* prevPort = this->m_SelectedPort;
+
+ // Check ports
+ std::map< std::string, QRectF >* ports[] =
+ { &( this->m_InputPorts ), &( this->m_OutputPorts ) };
+ bool found = false;
+ for( unsigned int pId = 0; pId < 2 && !found; ++pId )
+ {
+ for(
+ auto i = ports[ pId ]->begin( );
+ i != ports[ pId ]->end( ) && !found;
+ ++i
+ )
+ {
+ if( i->second.contains( pos ) )
+ {
+ this->setToolTip( i->first.c_str( ) );
+ this->m_SelectedPort = &( i->second );
+ this->m_SelectedPortIsInput = ( pId == 0 );
+ found = true;
+
+ } // fi
+
+ } // rof
+
+ } // rof
+ if( !found )
+ {
+ this->setToolTip( this->m_Object->GetName( ) );
+ this->m_SelectedPort = NULL;
+
+ } // fi
+ if( prevPort != this->m_SelectedPort )
+ this->update( );
}
-void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+// -------------------------------------------------------------------------
+void PipelineEditor::Node::
+_deselectPort( )
{
- update();
- QGraphicsItem::mouseReleaseEvent(event);
+ if( !( this->m_DraggingPort ) )
+ {
+ this->m_SelectedPort = NULL;
+ this->update( );
+
+ } // fi
}
// eof - $RCSfile$
-*/