3 #include "GraphCanvas.h"
5 #include <QFontMetricsF>
6 #include <QGraphicsWidget>
7 #include <QGraphicsSceneHoverEvent>
9 #include <cpPlugins/Interface/Object.h>
10 #include <cpPlugins/Interface/DataObject.h>
11 #include <cpPlugins/Interface/ProcessObject.h>
15 // -------------------------------------------------------------------------
16 PipelineEditor::Node::
17 Node( GraphCanvas* canvas, cpPlugins::Interface::Object* object )
18 : QGraphicsItem( NULL ),
21 m_SelectedPort( NULL ),
22 m_DraggingPort( false )
24 this->setFlag( QGraphicsItem::ItemIsMovable, true );
25 this->setFlag( QGraphicsItem::ItemSendsGeometryChanges, true );
26 this->setCacheMode( QGraphicsItem::DeviceCoordinateCache );
27 this->setAcceptHoverEvents( true );
28 this->setAcceptDrops( true );
29 this->setZValue( -1 );
30 this->updateRepresentation( );
33 // -------------------------------------------------------------------------
34 PipelineEditor::Node::
39 // -------------------------------------------------------------------------
40 void PipelineEditor::Node::
41 addEdge( PipelineEditor::Edge* edge )
43 this->m_Edges << edge;
47 // -------------------------------------------------------------------------
48 QList< PipelineEditor::Edge* > PipelineEditor::Node::
51 return( this->m_Edges );
54 // -------------------------------------------------------------------------
55 void PipelineEditor::Node::
56 updateRepresentation( )
58 typedef cpPlugins::Interface::DataObject _TData;
59 typedef cpPlugins::Interface::ProcessObject _TFilter;
61 if( this->m_Object == NULL )
65 _TData* d = dynamic_cast< _TData* >( this->m_Object );
66 _TFilter* f = dynamic_cast< _TFilter* >( this->m_Object );
67 if( d == NULL && f == NULL )
70 // Label and its bounds
71 QFontMetricsF fm( this->m_Canvas->font( ) );
72 this->m_Label = this->m_Object->GetName( );
73 this->m_Label += "\n";
74 this->m_Label += this->m_Object->GetClassName( ).c_str( );
75 this->m_Bounds = fm.boundingRect( this->m_Label );
77 // Create ports representation
78 this->m_Inputs.clear( );
79 this->m_Outputs.clear( );
80 this->m_InputPorts.clear( );
81 this->m_OutputPorts.clear( );
84 // Get filter's inputs and outputs
85 f->GetInputsNames( this->m_Inputs );
86 f->GetOutputsNames( this->m_Outputs );
89 unsigned int nIn = this->m_Inputs.size( );
90 unsigned int nOut = this->m_Outputs.size( );
92 qreal( ( ( ( ( nIn > nOut )? nIn: nOut ) << 1 ) + 1 ) * PORT_SIZE );
93 qreal h = this->m_Bounds.height( );
95 this->m_Bounds.setHeight( n );
98 qreal rt = this->m_Bounds.top( ) - qreal( PORT_SIZE );
99 qreal rb = this->m_Bounds.bottom( ) + qreal( PORT_SIZE );
100 qreal rl = this->m_Bounds.left( ) - qreal( PORT_SIZE );
101 qreal rr = this->m_Bounds.right( ) + qreal( PORT_SIZE );
103 // Add some space to the geometry
104 this->m_Bounds.setTop( rt );
105 this->m_Bounds.setBottom( rb );
106 this->m_Bounds.setLeft( rl );
107 this->m_Bounds.setRight( rr );
108 qreal rh = this->m_Bounds.height( );
111 QSizeF ps( qreal( PORT_SIZE ), qreal( PORT_SIZE ) );
112 std::set< std::string >* ports[] =
113 { &( this->m_Inputs ), &( this->m_Outputs ) };
114 for( unsigned int pId = 0; pId < 2; ++pId )
116 qreal h = qreal( ( ( ports[ pId ]->size( ) << 1 ) + 1 ) * PORT_SIZE );
117 qreal off = qreal( PORT_SIZE );
119 off += ( rh - h ) / qreal( 2 );
120 for( auto i = ports[ pId ]->begin( ); i != ports[ pId ]->end( ); ++i )
123 this->m_InputPorts[ *i ] =
124 QRectF( QPointF( rl, rt + off ), ps );
126 this->m_OutputPorts[ *i ] =
127 QRectF( QPointF( rr - qreal( PORT_SIZE ), rt + off ), ps );
128 off += qreal( PORT_SIZE < 1 );
136 // Some other initializations
137 this->m_SelectedPort = NULL;
140 // -------------------------------------------------------------------------
141 QRectF PipelineEditor::Node::
142 boundingRect( ) const
144 return( this->m_Bounds );
147 // -------------------------------------------------------------------------
148 QPainterPath PipelineEditor::Node::
152 path.addRect( this->m_Bounds );
156 // -------------------------------------------------------------------------
157 void PipelineEditor::Node::
159 QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget
163 QRectF rect = this->boundingRect( );
164 painter->drawRect( rect );
165 painter->drawText( rect, Qt::AlignCenter, this->m_Label );
168 std::map< std::string, QRectF >* ports[] =
169 { &( this->m_InputPorts ), &( this->m_OutputPorts ) };
170 for( unsigned int pId = 0; pId < 2; ++pId )
171 for( auto i = ports[ pId ]->begin( ); i != ports[ pId ]->end( ); ++i )
172 painter->drawRect( i->second );
175 if( this->m_SelectedPort != NULL )
177 painter->setBrush( Qt::green );
178 painter->drawEllipse( *( this->m_SelectedPort ) );
183 // -------------------------------------------------------------------------
184 QVariant PipelineEditor::Node::
185 itemChange( GraphicsItemChange change, const QVariant& value )
189 case QGraphicsItem::ItemPositionHasChanged:
190 foreach( Edge* edge, this->m_Edges )
192 this->m_Canvas->itemMoved( );
197 return( this->QGraphicsItem::itemChange( change, value ) );
200 // -------------------------------------------------------------------------
201 void PipelineEditor::Node::
202 mousePressEvent( QGraphicsSceneMouseEvent* event )
204 if( this->m_SelectedPort != NULL && this->m_Canvas != NULL )
206 if( event->button( ) == Qt::LeftButton )
208 QDrag* drag = new QDrag( this->m_Canvas );
209 QMimeData* mimeData = new QMimeData( );
211 // mimeData->setText( "drag_data" );
212 qulonglong address = reinterpret_cast< qulonglong >( this );
214 ba.setNum( address );
215 mimeData->setData( "source_node", ba );
216 drag->setMimeData( mimeData );
217 // TODO: drag->setPixmap( iconPixmap );
219 this->m_DraggingPort = true;
220 Qt::DropAction dropAction = drag->exec( );
221 this->m_DraggingPort = false;
230 Qt::MouseButton btn = event->button( );
231 if( btn == Qt::LeftButton )
233 std::string name = this->toolTip( ).toStdString( );
234 if( name != this->m_Object->GetName( ) )
236 // Get clicked port, if any
237 QPointF pos = event->buttonDownPos( btn );
238 auto iIt = this->m_InputPorts.find( name );
239 auto oIt = this->m_OutputPorts.find( name );
240 this->m_SelectedPort = NULL;
241 if( iIt != this->m_InputPorts.end( ) )
242 if( iIt->second.contains( pos ) )
243 this->m_SelectedPort = &( iIt->second );
244 if( this->m_SelectedPort == NULL && oIt != this->m_OutputPorts.end( ) )
245 if( oIt->second.contains( pos ) )
246 this->m_SelectedPort = &( oIt->second );
253 this->QGraphicsItem::mousePressEvent( event );
256 // -------------------------------------------------------------------------
257 void PipelineEditor::Node::
258 mouseReleaseEvent( QGraphicsSceneMouseEvent* event )
261 this->QGraphicsItem::mouseReleaseEvent( event );
264 // -------------------------------------------------------------------------
265 void PipelineEditor::Node::
266 mouseDoubleClickEvent( QGraphicsSceneMouseEvent* event )
270 // -------------------------------------------------------------------------
271 void PipelineEditor::Node::
272 hoverMoveEvent( QGraphicsSceneHoverEvent* event )
274 this->_selectPort( event->pos( ) );
277 // -------------------------------------------------------------------------
278 void PipelineEditor::Node::
279 hoverLeaveEvent( QGraphicsSceneHoverEvent* event )
281 this->_deselectPort( );
284 // -------------------------------------------------------------------------
285 void PipelineEditor::Node::
286 dragMoveEvent( QGraphicsSceneDragDropEvent* event )
288 this->_selectPort( event->pos( ) );
291 // -------------------------------------------------------------------------
292 void PipelineEditor::Node::
293 dragLeaveEvent( QGraphicsSceneDragDropEvent* event )
295 this->_deselectPort( );
298 // -------------------------------------------------------------------------
299 void PipelineEditor::Node::
300 dropEvent( QGraphicsSceneDragDropEvent* event )
302 // Get vertices and directionality
305 event->mimeData( )->data( "source_node" ).toULongLong( &ok );
306 Node* src = reinterpret_cast< Node* >( address );
310 if( src->m_SelectedPortIsInput )
317 // Discard if a loop is detected
322 const QRectF* srcPort = src->m_SelectedPort;
323 const QRectF* desPort = des->m_SelectedPort;
324 std::string srcName = src->m_Object->GetName( );
325 std::string desName = des->m_Object->GetName( );
326 std::string srcPortName = src->toolTip( ).toStdString( );
327 std::string desPortName = des->toolTip( ).toStdString( );
329 Edge* e = new Edge( src, des, srcPort, desPort );
332 if( this->m_Canvas != NULL )
333 this->m_Canvas->scene( )->addItem( e );
336 // -------------------------------------------------------------------------
337 void PipelineEditor::Node::
338 _selectPort( const QPointF& pos )
340 if( this->m_DraggingPort )
343 const QRectF* prevPort = this->m_SelectedPort;
346 std::map< std::string, QRectF >* ports[] =
347 { &( this->m_InputPorts ), &( this->m_OutputPorts ) };
349 for( unsigned int pId = 0; pId < 2 && !found; ++pId )
352 auto i = ports[ pId ]->begin( );
353 i != ports[ pId ]->end( ) && !found;
357 if( i->second.contains( pos ) )
359 this->setToolTip( i->first.c_str( ) );
360 this->m_SelectedPort = &( i->second );
361 this->m_SelectedPortIsInput = ( pId == 0 );
371 this->setToolTip( this->m_Object->GetName( ) );
372 this->m_SelectedPort = NULL;
375 if( prevPort != this->m_SelectedPort )
379 // -------------------------------------------------------------------------
380 void PipelineEditor::Node::
383 if( !( this->m_DraggingPort ) )
385 this->m_SelectedPort = NULL;