#include #include #include #include #include #include #include #include #include #include // ------------------------------------------------------------------------- cpBaseQtApplication::Pipeline::Canvas:: Canvas( QWidget* parent ) : Superclass( parent ), m_Workspace( NULL ), m_ActualConnection( NULL ), m_OutputPortReceiver( NULL ), m_OutputPortSlot( "" ) { this->m_Scene = new QGraphicsScene( this ); this->setScene( this->m_Scene ); this->setRenderHint( QPainter::Antialiasing ); this->setAcceptDrops( true ); this->m_EventFilter = new EventFilter( this ); this->m_EventFilter->setCanvas( this ); this->m_EventFilter->install( this->m_Scene ); } // ------------------------------------------------------------------------- cpBaseQtApplication::Pipeline::Canvas:: ~Canvas( ) { } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: clear( ) { qDeleteAll( this->m_Scene->items( ) ); this->m_Blocks.clear( ); this->m_ActualConnection = NULL; } // ------------------------------------------------------------------------- cpBaseQtApplication::Pipeline::Canvas:: TWorkspace* cpBaseQtApplication::Pipeline::Canvas:: workspace( ) { return( this->m_Workspace ); } // ------------------------------------------------------------------------- const cpBaseQtApplication::Pipeline::Canvas:: TWorkspace* cpBaseQtApplication::Pipeline::Canvas:: workspace( ) const { return( this->m_Workspace ); } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: setWorkspace( TWorkspace* ws ) { if( this->m_Workspace != ws ) { this->clear( ); this->m_Workspace = ws; } // fi this->_redrawWorkspace( ); } // ------------------------------------------------------------------------- std::string cpBaseQtApplication::Pipeline::Canvas:: addFilter( const std::string& cat, const std::string& fil, const QPointF& pos ) { auto filter = this->m_Workspace->CreateFilter( cat, fil ); Block* b = new Block( filter, NULL, this->m_Scene ); b->setPos( pos ); if( this->m_OutputPortReceiver != NULL ) b->connectOutputPortSlot( this->m_OutputPortReceiver, this->m_OutputPortSlot.c_str( ) ); std::string name = filter->GetName( ); this->m_Blocks[ name ] = b; return( name ); } // ------------------------------------------------------------------------- bool cpBaseQtApplication::Pipeline::Canvas:: connectOutputPortSlot( QObject* receiver, const char* slot ) { this->m_OutputPortReceiver = receiver; this->m_OutputPortSlot = slot; bool ok = true; for( auto b : this->m_Blocks ) ok &= b.second->connectOutputPortSlot( receiver, slot ); return( ok ); } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: rename( QGraphicsItem* item ) { if( this->m_Workspace == NULL ) return; Block* b = dynamic_cast< Block* >( item ); if( b != NULL ) { std::string old_n = b->filter( )->GetName( ); bool ok; std::string new_n = QInputDialog::getText( dynamic_cast< QWidget* >( this->parent( ) ), "Change filter name", "Filter name:", QLineEdit::Normal, old_n.c_str( ), &ok ).toStdString( ); if( ok && new_n != "" && old_n != new_n ) { if( this->m_Workspace->RenameFilter( old_n, new_n ) ) { auto bIt = this->m_Blocks.find( old_n ); this->m_Blocks[ new_n ] = bIt->second; bIt->second->setNamePort( new_n.c_str( ) ); this->m_Blocks.erase( bIt ); } // fi } // fi } // fi } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: exposePort( QGraphicsItem* item ) { } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: moveConnection( const QPointF& pnt ) { if( this->m_ActualConnection != NULL ) { if( this->m_ActualConnection->port1( ) == NULL ) this->m_ActualConnection->setPos1( pnt ); else if( this->m_ActualConnection->port2( ) == NULL ) this->m_ActualConnection->setPos2( pnt ); this->m_ActualConnection->updatePath( ); } // fi } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: grab( const QPointF& pnt ) { QGraphicsItem* item = this->m_Scene->itemAt( pnt ); OutputPort* oport = dynamic_cast< OutputPort* >( item ); if( oport != NULL ) { // Start new connection this->m_ActualConnection = new Connection( 0, this->m_Scene ); this->m_ActualConnection->setPort1( oport ); this->m_ActualConnection->setPos1( oport->scenePos( ) ); this->m_ActualConnection->setPos2( pnt ); this->m_ActualConnection->updatePosFromPorts( ); this->m_ActualConnection->updatePath( ); } // fi } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: release( const QPointF& pnt ) { if( this->m_ActualConnection == NULL || this->m_Workspace == NULL ) return; QGraphicsItem* item = this->m_Scene->itemAt( pnt ); InputPort* iport = dynamic_cast< InputPort* >( item ); OutputPort* oport = dynamic_cast< OutputPort* >( this->m_ActualConnection->port1( ) ); if( iport != NULL && oport != NULL ) { Block* iblock = iport->block( ); Block* oblock = oport->block( ); std::string ofil = oblock->namePort( ).toStdString( ); std::string dfil = iblock->namePort( ).toStdString( ); std::string oname = oport->name( ).toStdString( ); std::string dname = iport->name( ).toStdString( ); try { if( this->m_Workspace->Connect( ofil, oname, dfil, dname ) ) { this->m_ActualConnection->setPos2( iport->scenePos( ) ); this->m_ActualConnection->setPort2( iport ); this->m_ActualConnection->updatePosFromPorts( ); this->m_ActualConnection->updatePath( ); } else delete this->m_ActualConnection; } catch( std::exception& err ) { delete this->m_ActualConnection; QMessageBox::critical( NULL, QMessageBox::tr( "Error connecting ports" ), QMessageBox::tr( err.what( ) ) ); } // yrt this->m_ActualConnection = NULL; } else { delete this->m_ActualConnection; this->m_ActualConnection = NULL; } // fi } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: keyPressEvent( QKeyEvent* event ) { static const int del_key = 16777223; if( this->m_Workspace == NULL ) return; switch( event->key( ) ) { case del_key: { // Get items to delete auto _items = this->items( ); auto i = _items.begin( ); std::set< Block* > blocks_to_delete; std::set< Connection* > connections_to_delete; while( i != _items.end( ) ) { if( ( *i )->isSelected( ) ) { Block* b = dynamic_cast< Block* >( *i ); Connection* c = dynamic_cast< Connection* >( *i ); if( b != NULL ) { blocks_to_delete.insert( b ); auto inputs = b->filter( )->GetInputsNames( ); for( auto inIt : inputs ) { InputPort* p = b->inputPort( inIt.c_str( ) ); for( unsigned int j = 0; j < p->numberOfConnections( ); ++j ) connections_to_delete.insert( p->connection( j ) ); } // rof auto outputs = b->filter( )->GetOutputsNames( ); for( auto outIt : outputs ) { OutputPort* p = b->outputPort( outIt.c_str( ) ); auto& conns = p->connections( ); for( unsigned int j = 0; j < conns.size( ); ++j ) connections_to_delete.insert( conns[ j ] ); } // rof } else if( c != NULL ) connections_to_delete.insert( c ); } // fi i++; } // elihw // Delete connections for( auto conn : connections_to_delete ) { OutputPort* oport = conn->port1( ); InputPort* iport = conn->port2( ); Block* oblock = oport->block( ); Block* iblock = iport->block( ); if( this->m_Workspace->Disconnect( oblock->namePort( ).toStdString( ), oport->name( ).toStdString( ), iblock->namePort( ).toStdString( ), iport->name( ).toStdString( ) ) ) delete conn; } // rof // Delete blocks for( auto block : blocks_to_delete ) if( this->m_Workspace->RemoveFilter( block->namePort( ).toStdString( ) ) ) delete block; } break; default: break; } // hctiws } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: wheelEvent( QWheelEvent* event ) { this->_scaleView( std::pow( double( 2 ), event->delta( ) / double( 240 ) ) ); } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: dragEnterEvent( QDragEnterEvent* event ) { const QMimeData* mime = event->mimeData( ); if( mime->hasFormat( "application/x-qabstractitemmodeldatalist" ) ) event->acceptProposedAction( ); } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: dragLeaveEvent( QDragLeaveEvent* event ) { } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: dragMoveEvent( QDragMoveEvent* event ) { } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: dropEvent( QDropEvent* event ) { if( this->m_Workspace == NULL ) return; const QMimeData* mime = event->mimeData( ); if( !( mime->hasFormat( "application/x-qabstractitemmodeldatalist" ) ) ) return; event->acceptProposedAction( ); auto tree = dynamic_cast< QTreeWidget* >( event->source( ) ); if( tree == NULL ) return; QPointF p = this->mapToScene( event->pos( ) ); QList< QTreeWidgetItem* > items = tree->selectedItems( ); for( auto iIt = items.begin( ); iIt != items.end( ); ++iIt ) { auto parent = ( *iIt )->parent( ); if( parent != NULL ) this->addFilter( parent->text( 0 ).toStdString( ), ( *iIt )->text( 0 ).toStdString( ), p ); } // rof } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: _scaleView( qreal scaleFactor ) { qreal factor = this->transform( ). scale( scaleFactor, scaleFactor ). mapRect( QRectF( 0, 0, 1, 1 ) ). width( ); if( factor < qreal( 0.07 ) || factor > qreal( 100 ) ) return; this->scale( scaleFactor, scaleFactor ); } // ------------------------------------------------------------------------- void cpBaseQtApplication::Pipeline::Canvas:: _redrawWorkspace( ) { // Get filters names if( this->m_Workspace == NULL ) return; auto fnames = this->m_Workspace->GetFiltersNames( ); // Create blocks for( auto fname : fnames ) { auto filter = this->m_Workspace->GetFilter( fname ); Block* b = new Block( filter, NULL, this->m_Scene ); b->setPos( filter->GetViewX( ), filter->GetViewY( ) ); if( this->m_OutputPortReceiver != NULL ) b->connectOutputPortSlot( this->m_OutputPortReceiver, this->m_OutputPortSlot.c_str( ) ); this->m_Blocks[ filter->GetName( ) ] = b; } // rof // Create connections for( auto b : this->m_Blocks ) { auto filter = b.second->filter( ); auto inputs = filter->GetInputsNames( ); for( auto in : inputs ) { for( unsigned int id = 0; id < filter->GetInputSize( in ); ++id ) { auto inData = filter->GetInput( in, id ); if( inData != NULL ) { auto src = inData->GetSource( ); auto outputs = src->GetOutputsNames( ); std::string outName = ""; for( auto out : outputs ) if( src->GetOutput( out ) == inData ) outName = out; auto c = this->m_Blocks.find( src->GetName( ) ); auto b_src = c->second; auto b_des = b.second; auto oport = b_src->outputPort( outName.c_str( ) ); auto iport = b_des->inputPort( in.c_str( ) ); auto conn = new Connection( 0, this->m_Scene ); conn->setPort1( oport ); conn->setPort2( iport ); conn->setPos1( oport->scenePos( ) ); conn->setPos2( iport->scenePos( ) ); conn->updatePosFromPorts( ); conn->updatePath( ); } // fi } // rof } // rof } // rof } // eof - $RCSfile$