X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=appli%2FcpPipelineEditor%2FNode.cxx;h=34c4d96fddc1f314503331b54f1dc7a0d0303fdb;hb=ef8b6e12859181d3faa8019ce7319c539c0f86ec;hp=a1026dc6260e211eeb1255c13a13a2fd6901bc89;hpb=dd763c7c99bb59edcc7035738ff1ad10255e2525;p=cpPlugins.git diff --git a/appli/cpPipelineEditor/Node.cxx b/appli/cpPipelineEditor/Node.cxx index a1026dc..34c4d96 100644 --- a/appli/cpPipelineEditor/Node.cxx +++ b/appli/cpPipelineEditor/Node.cxx @@ -7,9 +7,10 @@ #include #include +#include #include -#define PORT_SIZE 10 +#define PORT_SIZE 15 // ------------------------------------------------------------------------- PipelineEditor::Node:: @@ -17,14 +18,16 @@ Node( GraphCanvas* canvas, cpPlugins::Interface::Object* object ) : 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( ); } // ------------------------------------------------------------------------- @@ -49,49 +52,95 @@ edges( ) const } // ------------------------------------------------------------------------- -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 ); } @@ -100,7 +149,7 @@ QPainterPath PipelineEditor::Node:: shape( ) const { QPainterPath path; - path.addRect( this->boundingRect( ) ); + path.addRect( this->m_Bounds ); return( path ); } @@ -110,49 +159,23 @@ paint( 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 } @@ -161,18 +184,16 @@ paint( 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 ) ); } @@ -180,6 +201,54 @@ itemChange( GraphicsItemChange change, const QVariant& 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 ); } @@ -202,51 +271,121 @@ mouseDoubleClickEvent( QGraphicsSceneMouseEvent* 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$ -*/