1 #include <cpBaseQtApplication/Pipeline/Canvas.h>
2 #include <cpBaseQtApplication/Pipeline/EventFilter.h>
3 #include <cpBaseQtApplication/Pipeline/Block.h>
4 #include <cpBaseQtApplication/Pipeline/Connection.h>
5 #include <cpBaseQtApplication/Pipeline/Port.h>
7 #include <QDragEnterEvent>
8 #include <QInputDialog>
10 #include <QWheelEvent>
11 #include <QTreeWidget>
13 // -------------------------------------------------------------------------
14 cpBaseQtApplication::Pipeline::Canvas::
15 Canvas( QWidget* parent )
16 : Superclass( parent ),
18 m_ActualConnection( NULL ),
19 m_OutputPortReceiver( NULL ),
20 m_OutputPortSlot( "" )
22 this->m_Scene = new QGraphicsScene( this );
23 this->setScene( this->m_Scene );
24 this->setRenderHint( QPainter::Antialiasing );
25 this->setAcceptDrops( true );
27 this->m_EventFilter = new EventFilter( this );
28 this->m_EventFilter->setCanvas( this );
29 this->m_EventFilter->install( this->m_Scene );
32 // -------------------------------------------------------------------------
33 cpBaseQtApplication::Pipeline::Canvas::
38 // -------------------------------------------------------------------------
39 void cpBaseQtApplication::Pipeline::Canvas::
42 qDeleteAll( this->m_Scene->items( ) );
43 this->m_Blocks.clear( );
44 this->m_ActualConnection = NULL;
47 // -------------------------------------------------------------------------
48 cpBaseQtApplication::Pipeline::Canvas::
49 TWorkspace* cpBaseQtApplication::Pipeline::Canvas::
52 return( this->m_Workspace );
55 // -------------------------------------------------------------------------
56 const cpBaseQtApplication::Pipeline::Canvas::
57 TWorkspace* cpBaseQtApplication::Pipeline::Canvas::
60 return( this->m_Workspace );
63 // -------------------------------------------------------------------------
64 void cpBaseQtApplication::Pipeline::Canvas::
65 setWorkspace( TWorkspace* ws )
67 if( this->m_Workspace != ws )
70 this->m_Workspace = ws;
73 this->_redrawWorkspace( );
76 // -------------------------------------------------------------------------
77 std::string cpBaseQtApplication::Pipeline::Canvas::
78 addFilter( const std::string& cat, const std::string& fil, const QPointF& pos )
80 auto filter = this->m_Workspace->CreateFilter( cat, fil );
81 Block* b = new Block( filter, NULL, this->m_Scene );
83 if( this->m_OutputPortReceiver != NULL )
84 b->connectOutputPortSlot(
85 this->m_OutputPortReceiver, this->m_OutputPortSlot.c_str( )
87 std::string name = filter->GetName( );
88 this->m_Blocks[ name ] = b;
92 // -------------------------------------------------------------------------
93 bool cpBaseQtApplication::Pipeline::Canvas::
94 connectOutputPortSlot( QObject* receiver, const char* slot )
96 this->m_OutputPortReceiver = receiver;
97 this->m_OutputPortSlot = slot;
99 for( auto b : this->m_Blocks )
100 ok &= b.second->connectOutputPortSlot( receiver, slot );
104 // -------------------------------------------------------------------------
105 void cpBaseQtApplication::Pipeline::Canvas::
106 rename( QGraphicsItem* item )
108 if( this->m_Workspace == NULL )
111 Block* b = dynamic_cast< Block* >( item );
114 std::string old_n = b->filter( )->GetName( );
117 QInputDialog::getText(
118 dynamic_cast< QWidget* >( this->parent( ) ),
119 "Change filter name",
125 if( ok && new_n != "" && old_n != new_n )
127 if( this->m_Workspace->RenameFilter( old_n, new_n ) )
129 auto bIt = this->m_Blocks.find( old_n );
130 this->m_Blocks[ new_n ] = bIt->second;
131 bIt->second->setNamePort( new_n.c_str( ) );
132 this->m_Blocks.erase( bIt );
141 // -------------------------------------------------------------------------
142 void cpBaseQtApplication::Pipeline::Canvas::
143 exposePort( QGraphicsItem* item )
147 // -------------------------------------------------------------------------
148 void cpBaseQtApplication::Pipeline::Canvas::
149 moveConnection( const QPointF& pnt )
151 if( this->m_ActualConnection != NULL )
153 if( this->m_ActualConnection->port1( ) == NULL )
154 this->m_ActualConnection->setPos1( pnt );
155 else if( this->m_ActualConnection->port2( ) == NULL )
156 this->m_ActualConnection->setPos2( pnt );
157 this->m_ActualConnection->updatePath( );
162 // -------------------------------------------------------------------------
163 void cpBaseQtApplication::Pipeline::Canvas::
164 grab( const QPointF& pnt )
166 QGraphicsItem* item = this->m_Scene->itemAt( pnt );
167 OutputPort* oport = dynamic_cast< OutputPort* >( item );
170 // Start new connection
171 this->m_ActualConnection = new Connection( 0, this->m_Scene );
172 this->m_ActualConnection->setPort1( oport );
173 this->m_ActualConnection->setPos1( oport->scenePos( ) );
174 this->m_ActualConnection->setPos2( pnt );
175 this->m_ActualConnection->updatePosFromPorts( );
176 this->m_ActualConnection->updatePath( );
181 // -------------------------------------------------------------------------
182 void cpBaseQtApplication::Pipeline::Canvas::
183 release( const QPointF& pnt )
185 if( this->m_ActualConnection == NULL || this->m_Workspace == NULL )
188 QGraphicsItem* item = this->m_Scene->itemAt( pnt );
189 InputPort* iport = dynamic_cast< InputPort* >( item );
191 dynamic_cast< OutputPort* >( this->m_ActualConnection->port1( ) );
192 if( iport != NULL && oport != NULL )
194 Block* iblock = iport->block( );
195 Block* oblock = oport->block( );
196 std::string ofil = oblock->namePort( ).toStdString( );
197 std::string dfil = iblock->namePort( ).toStdString( );
198 std::string oname = oport->name( ).toStdString( );
199 std::string dname = iport->name( ).toStdString( );
202 if( this->m_Workspace->Connect( ofil, oname, dfil, dname ) )
204 this->m_ActualConnection->setPos2( iport->scenePos( ) );
205 this->m_ActualConnection->setPort2( iport );
206 this->m_ActualConnection->updatePosFromPorts( );
207 this->m_ActualConnection->updatePath( );
210 delete this->m_ActualConnection;
212 catch( std::exception& err )
214 delete this->m_ActualConnection;
215 QMessageBox::critical(
217 QMessageBox::tr( "Error connecting ports" ),
218 QMessageBox::tr( err.what( ) )
222 this->m_ActualConnection = NULL;
226 delete this->m_ActualConnection;
227 this->m_ActualConnection = NULL;
232 // -------------------------------------------------------------------------
233 void cpBaseQtApplication::Pipeline::Canvas::
234 keyPressEvent( QKeyEvent* event )
236 static const int del_key = 16777223;
237 if( this->m_Workspace == NULL )
240 switch( event->key( ) )
244 // Get items to delete
245 auto _items = this->items( );
246 auto i = _items.begin( );
247 std::set< Block* > blocks_to_delete;
248 std::set< Connection* > connections_to_delete;
249 while( i != _items.end( ) )
251 if( ( *i )->isSelected( ) )
253 Block* b = dynamic_cast< Block* >( *i );
254 Connection* c = dynamic_cast< Connection* >( *i );
257 blocks_to_delete.insert( b );
258 auto inputs = b->filter( )->GetInputsNames( );
259 for( auto inIt : inputs )
261 InputPort* p = b->inputPort( inIt.c_str( ) );
262 for( unsigned int j = 0; j < p->numberOfConnections( ); ++j )
263 connections_to_delete.insert( p->connection( j ) );
266 auto outputs = b->filter( )->GetOutputsNames( );
267 for( auto outIt : outputs )
269 OutputPort* p = b->outputPort( outIt.c_str( ) );
270 auto& conns = p->connections( );
271 for( unsigned int j = 0; j < conns.size( ); ++j )
272 connections_to_delete.insert( conns[ j ] );
277 connections_to_delete.insert( c );
284 // Delete connections
285 for( auto conn : connections_to_delete )
287 OutputPort* oport = conn->port1( );
288 InputPort* iport = conn->port2( );
289 Block* oblock = oport->block( );
290 Block* iblock = iport->block( );
292 this->m_Workspace->Disconnect(
293 oblock->namePort( ).toStdString( ),
294 oport->name( ).toStdString( ),
295 iblock->namePort( ).toStdString( ),
296 iport->name( ).toStdString( )
304 for( auto block : blocks_to_delete )
306 this->m_Workspace->RemoveFilter( block->namePort( ).toStdString( ) )
316 // -------------------------------------------------------------------------
317 void cpBaseQtApplication::Pipeline::Canvas::
318 wheelEvent( QWheelEvent* event )
321 std::pow( double( 2 ), event->delta( ) / double( 240 ) )
325 // -------------------------------------------------------------------------
326 void cpBaseQtApplication::Pipeline::Canvas::
327 dragEnterEvent( QDragEnterEvent* event )
329 const QMimeData* mime = event->mimeData( );
330 if( mime->hasFormat( "application/x-qabstractitemmodeldatalist" ) )
331 event->acceptProposedAction( );
334 // -------------------------------------------------------------------------
335 void cpBaseQtApplication::Pipeline::Canvas::
336 dragLeaveEvent( QDragLeaveEvent* event )
340 // -------------------------------------------------------------------------
341 void cpBaseQtApplication::Pipeline::Canvas::
342 dragMoveEvent( QDragMoveEvent* event )
346 // -------------------------------------------------------------------------
347 void cpBaseQtApplication::Pipeline::Canvas::
348 dropEvent( QDropEvent* event )
350 if( this->m_Workspace == NULL )
352 const QMimeData* mime = event->mimeData( );
353 if( !( mime->hasFormat( "application/x-qabstractitemmodeldatalist" ) ) )
355 event->acceptProposedAction( );
356 auto tree = dynamic_cast< QTreeWidget* >( event->source( ) );
360 QPointF p = this->mapToScene( event->pos( ) );
361 QList< QTreeWidgetItem* > items = tree->selectedItems( );
362 for( auto iIt = items.begin( ); iIt != items.end( ); ++iIt )
364 auto parent = ( *iIt )->parent( );
367 parent->text( 0 ).toStdString( ),
368 ( *iIt )->text( 0 ).toStdString( ),
375 // -------------------------------------------------------------------------
376 void cpBaseQtApplication::Pipeline::Canvas::
377 _scaleView( qreal scaleFactor )
379 qreal factor = this->transform( ).
380 scale( scaleFactor, scaleFactor ).
381 mapRect( QRectF( 0, 0, 1, 1 ) ).
383 if( factor < qreal( 0.07 ) || factor > qreal( 100 ) )
385 this->scale( scaleFactor, scaleFactor );
388 // -------------------------------------------------------------------------
389 void cpBaseQtApplication::Pipeline::Canvas::
393 if( this->m_Workspace == NULL )
395 auto fnames = this->m_Workspace->GetFiltersNames( );
398 for( auto fname : fnames )
400 auto filter = this->m_Workspace->GetFilter( fname );
401 Block* b = new Block( filter, NULL, this->m_Scene );
402 b->setPos( filter->GetViewX( ), filter->GetViewY( ) );
403 if( this->m_OutputPortReceiver != NULL )
404 b->connectOutputPortSlot(
405 this->m_OutputPortReceiver, this->m_OutputPortSlot.c_str( )
407 this->m_Blocks[ filter->GetName( ) ] = b;
411 // Create connections
412 for( auto b : this->m_Blocks )
414 auto filter = b.second->filter( );
415 auto inputs = filter->GetInputsNames( );
416 for( auto in : inputs )
418 for( unsigned int id = 0; id < filter->GetInputSize( in ); ++id )
420 auto inData = filter->GetInput( in, id );
423 auto src = inData->GetSource( );
424 auto outputs = src->GetOutputsNames( );
425 std::string outName = "";
426 for( auto out : outputs )
427 if( src->GetOutput( out ) == inData )
429 auto c = this->m_Blocks.find( src->GetName( ) );
430 auto b_src = c->second;
431 auto b_des = b.second;
432 auto oport = b_src->outputPort( outName.c_str( ) );
433 auto iport = b_des->inputPort( in.c_str( ) );
435 auto conn = new Connection( 0, this->m_Scene );
436 conn->setPort1( oport );
437 conn->setPort2( iport );
438 conn->setPos1( oport->scenePos( ) );
439 conn->setPos2( iport->scenePos( ) );
440 conn->updatePosFromPorts( );