1 /* Copyright (c) 2012, STANISLAW ADASZEWSKI
\r
4 Redistribution and use in source and binary forms, with or without
\r
5 modification, are permitted provided that the following conditions are met:
\r
6 * Redistributions of source code must retain the above copyright
\r
7 notice, this list of conditions and the following disclaimer.
\r
8 * Redistributions in binary form must reproduce the above copyright
\r
9 notice, this list of conditions and the following disclaimer in the
\r
10 documentation and/or other materials provided with the distribution.
\r
11 * Neither the name of STANISLAW ADASZEWSKI nor the
\r
12 names of its contributors may be used to endorse or promote products
\r
13 derived from this software without specific prior written permission.
\r
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
\r
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
\r
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
\r
18 DISCLAIMED. IN NO EVENT SHALL STANISLAW ADASZEWSKI BE LIABLE FOR ANY
\r
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
\r
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
\r
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
\r
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
\r
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 #include "QNodesEditor.h"
\r
29 #include <QGraphicsScene>
\r
31 #include <QGraphicsSceneContextMenuEvent>
\r
32 #include <QGraphicsSceneDragDropEvent>
\r
33 #include <QGraphicsSceneHelpEvent>
\r
34 #include <QGraphicsSceneHoverEvent>
\r
35 #include <QGraphicsSceneMouseEvent>
\r
36 #include <QGraphicsSceneMoveEvent>
\r
37 #include <QGraphicsSceneResizeEvent>
\r
38 #include <QGraphicsSceneWheelEvent>
\r
40 #include "QNEPort.h"
\r
41 #include "QNEConnection.h"
\r
42 #include "QNEBlock.h"
\r
44 // -------------------------------------------------------------------------
\r
45 PipelineEditor::QNodesEditor::
\r
46 QNodesEditor( QObject* parent )
\r
47 : Superclass( parent ),
\r
53 // -------------------------------------------------------------------------
\r
54 PipelineEditor::QNodesEditor::
\r
59 // -------------------------------------------------------------------------
\r
60 PipelineEditor::QNodesEditor::
\r
61 TWorkspace* PipelineEditor::QNodesEditor::
\r
64 return( this->m_Workspace );
\r
67 // -------------------------------------------------------------------------
\r
68 const PipelineEditor::QNodesEditor::
\r
69 TWorkspace* PipelineEditor::QNodesEditor::
\r
72 return( this->m_Workspace );
\r
75 // -------------------------------------------------------------------------
\r
76 void PipelineEditor::QNodesEditor::
\r
77 setWorkspace( TWorkspace* ws )
\r
79 this->m_Workspace = ws;
\r
80 this->m_Graph = TGraph::New( );
\r
83 auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( );
\r
84 auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( );
\r
85 for( ; vIt != vIt_end; ++vIt )
\r
88 dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ),
\r
95 auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( );
\r
96 auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( );
\r
97 for( ; rIt != rIt_end; ++rIt )
\r
99 if( !this->m_Graph->HasVertexIndex( rIt->first ) )
\r
101 QNEBlock* orig = this->m_Graph->GetVertex( rIt->first );
\r
104 QVector< QNEOutputPort* >& oPorts = orig->outputPorts( );
\r
106 auto cIt = rIt->second.begin( );
\r
107 for( ; cIt != rIt->second.end( ); ++cIt )
\r
109 if( !this->m_Graph->HasVertexIndex( cIt->first ) )
\r
111 QNEBlock* dest = this->m_Graph->GetVertex( cIt->first );
\r
114 QVector< QNEInputPort* >& iPorts = dest->inputPorts( );
\r
116 auto eIt = cIt->second.begin( );
\r
117 for( ; eIt != cIt->second.end( ); ++eIt )
\r
119 QNEOutputPort* op = NULL;
\r
120 auto opIt = oPorts.begin( );
\r
121 for( ; opIt != oPorts.end( ) && op == NULL; ++opIt )
\r
122 if( ( *opIt )->name( ).toStdString( ) == eIt->first )
\r
125 QNEInputPort* ip = NULL;
\r
126 auto ipIt = iPorts.begin( );
\r
127 for( ; ipIt != iPorts.end( ) && ip == NULL; ++ipIt )
\r
128 if( ( *ipIt )->name( ).toStdString( ) == eIt->second )
\r
131 if( op == NULL || ip == NULL )
\r
134 QNEConnection* conn = new QNEConnection( 0, this->m_Scene );
\r
135 conn->setPort1( op );
\r
136 conn->setPort2( ip );
\r
137 conn->updatePosFromPorts( );
\r
138 conn->updatePath( );
\r
139 this->m_Graph->AddConnection( rIt->first, cIt->first, conn );
\r
148 // -------------------------------------------------------------------------
\r
149 std::string PipelineEditor::QNodesEditor::
\r
150 createFilter( const std::string& filter, const QPointF& pnt )
\r
152 std::string name = filter;
\r
153 while( this->m_Workspace->HasFilter( name ) )
\r
154 name += std::string( "_" );
\r
155 if( this->m_Workspace->CreateFilter( filter, name ) )
\r
157 this->_CreateBlock( this->m_Workspace->GetFilter( name ), pnt );
\r
164 // -------------------------------------------------------------------------
\r
165 void PipelineEditor::QNodesEditor::
\r
166 install( QGraphicsScene* s )
\r
168 s->installEventFilter( this );
\r
172 // -------------------------------------------------------------------------
\r
173 QGraphicsItem* PipelineEditor::QNodesEditor::
\r
174 itemAt( const QPointF& pos )
\r
176 QList< QGraphicsItem* > items =
\r
177 this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );
\r
179 foreach( QGraphicsItem* item, items )
\r
180 if( item->type( ) > QGraphicsItem::UserType )
\r
185 // -------------------------------------------------------------------------
\r
186 void PipelineEditor::QNodesEditor::
\r
187 _CreateBlock( TFilter* f, const QPointF& pnt )
\r
193 QNEBlock* b = new QNEBlock( 0, this->m_Scene );
\r
194 b->setNamePort( f->GetName( ) );
\r
195 b->setTypePort( f->GetClassName( ) );
\r
196 // TODO: b->setScenePos( pnt );
\r
199 std::set< std::string > inputs;
\r
200 f->GetInputsNames( inputs );
\r
201 for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt )
\r
202 b->addInputPort( iIt->c_str( ) );
\r
204 // Add output ports
\r
205 std::set< std::string > outputs;
\r
206 f->GetOutputsNames( outputs );
\r
207 for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt )
\r
208 b->addOutputPort( oIt->c_str( ) );
\r
210 // Keep a trace of this visual graph
\r
211 this->m_Graph->SetVertex( f->GetName( ), b );
\r
214 // -------------------------------------------------------------------------
\r
215 void PipelineEditor::QNodesEditor::
\r
216 _DoubleClick( QGraphicsSceneMouseEvent* evt, QGraphicsItem* item )
\r
218 switch( evt->button( ) )
\r
220 case Qt::LeftButton:
\r
222 QNEBlock* block = dynamic_cast< QNEBlock* >( item );
\r
223 QNEPort* port = dynamic_cast< QNEPort* >( item );
\r
224 QNEConnection* conn = dynamic_cast< QNEConnection* >( item );
\r
226 if( block != NULL )
\r
229 auto ports = block->ports( );
\r
230 std::string name = "";
\r
232 auto pIt = ports.begin( );
\r
233 pIt != ports.end( ) && name == "";
\r
237 ( *pIt )->portFlags( ) && QNEPort::NamePort == QNEPort::NamePort
\r
239 name = ( *pIt )->portName( ).toStdString( );
\r
242 TFilter* filter = this->m_Workspace->GetFilter( name );
\r
243 if( filter != NULL )
\r
248 else if( port != NULL )
\r
251 else if( conn != NULL )
\r
257 case Qt::RightButton:
\r
261 case Qt::MiddleButton:
\r
271 // -------------------------------------------------------------------------
\r
272 bool PipelineEditor::QNodesEditor::
\r
273 eventFilter( QObject* o, QEvent* e )
\r
276 switch( int( e->type( ) ) )
\r
278 case QEvent::GraphicsSceneContextMenu:
\r
280 QGraphicsSceneContextMenuEvent* evt =
\r
281 dynamic_cast< QGraphicsSceneContextMenuEvent* >( e );
\r
287 case QEvent::GraphicsSceneDragEnter:
\r
289 QGraphicsSceneDragDropEvent* evt =
\r
290 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
296 case QEvent::GraphicsSceneDragLeave:
\r
298 QGraphicsSceneDragDropEvent* evt =
\r
299 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
305 case QEvent::GraphicsSceneDragMove:
\r
307 QGraphicsSceneDragDropEvent* evt =
\r
308 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
314 case QEvent::GraphicsSceneDrop:
\r
316 QGraphicsSceneDragDropEvent* evt =
\r
317 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
323 case QEvent::GraphicsSceneHelp:
\r
325 QGraphicsSceneHelpEvent* evt =
\r
326 dynamic_cast< QGraphicsSceneHelpEvent* >( e );
\r
332 case QEvent::GraphicsSceneHoverEnter:
\r
334 QGraphicsSceneHoverEvent* evt =
\r
335 dynamic_cast< QGraphicsSceneHoverEvent* >( e );
\r
341 case QEvent::GraphicsSceneHoverLeave:
\r
343 QGraphicsSceneHoverEvent* evt =
\r
344 dynamic_cast< QGraphicsSceneHoverEvent* >( e );
\r
350 case QEvent::GraphicsSceneHoverMove:
\r
352 QGraphicsSceneHoverEvent* evt =
\r
353 dynamic_cast< QGraphicsSceneHoverEvent* >( e );
\r
359 case QEvent::GraphicsSceneMouseDoubleClick:
\r
361 QGraphicsSceneMouseEvent* evt =
\r
362 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
365 QGraphicsItem* item = this->itemAt( evt->scenePos( ) );
\r
368 this->_DoubleClick( evt, item );
\r
376 case QEvent::GraphicsSceneMouseMove:
\r
378 QGraphicsSceneMouseEvent* evt =
\r
379 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
384 this->m_Conn->setPos2( evt->scenePos( ) );
\r
385 this->m_Conn->updatePath( );
\r
393 case QEvent::GraphicsSceneMousePress:
\r
395 QGraphicsSceneMouseEvent* evt =
\r
396 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
399 switch( evt->button( ) )
\r
401 case Qt::LeftButton:
\r
403 QNEOutputPort* port =
\r
404 dynamic_cast< QNEOutputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
407 this->m_Conn = new QNEConnection( 0, this->m_Scene );
\r
408 this->m_Conn->setPort1( port );
\r
409 this->m_Conn->setPos1( port->scenePos( ) );
\r
410 this->m_Conn->setPos2( evt->scenePos( ) );
\r
411 this->m_Conn->updatePath( );
\r
425 case QEvent::GraphicsSceneMouseRelease:
\r
427 QGraphicsSceneMouseEvent* evt =
\r
428 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
431 if( this->m_Conn != NULL && evt->button( ) == Qt::LeftButton )
\r
433 QNEInputPort* port2 =
\r
434 dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
435 if( port2 != NULL )
\r
437 QNEOutputPort* port1 =
\r
438 dynamic_cast< QNEOutputPort* >( this->m_Conn->port1( ) );
\r
439 if( port1 != NULL )
\r
442 port1->block( ) != port2->block( ) &&
\r
443 !port2->hasConnection( ) &&
\r
444 !port1->isConnected( port2 )
\r
447 this->m_Conn->setPos2( port2->scenePos( ) );
\r
448 this->m_Conn->setPort2( port2 );
\r
449 this->m_Conn->updatePath( );
\r
451 this->m_Workspace->Connect(
\r
452 port1->block( )->namePort( )->name( ).toStdString( ),
\r
453 port2->block( )->namePort( )->name( ).toStdString( ),
\r
454 port1->name( ).toStdString( ),
\r
455 port2->name( ).toStdString( )
\r
457 this->m_Graph->AddConnection(
\r
458 port1->block( )->namePort( )->name( ).toStdString( ),
\r
459 port2->block( )->namePort( )->name( ).toStdString( ),
\r
463 this->m_Conn = NULL;
\r
471 delete this->m_Conn;
\r
472 this->m_Conn = NULL;
\r
480 case QEvent::GraphicsSceneMove:
\r
482 QGraphicsSceneMoveEvent* evt =
\r
483 dynamic_cast< QGraphicsSceneMoveEvent* >( e );
\r
489 case QEvent::GraphicsSceneResize:
\r
491 QGraphicsSceneResizeEvent* evt =
\r
492 dynamic_cast< QGraphicsSceneResizeEvent* >( e );
\r
498 case QEvent::GraphicsSceneWheel:
\r
500 QGraphicsSceneWheelEvent* evt =
\r
501 dynamic_cast< QGraphicsSceneWheelEvent* >( e );
\r
513 QGraphicsSceneMouseEvent* me =
\r
514 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
521 switch( ( int ) e->type( ) )
\r
523 case QEvent::GraphicsSceneMouseMove:
\r
527 this->m_Conn->setPos2( me->scenePos( ) );
\r
528 this->m_Conn->updatePath( );
\r
533 case QEvent::GraphicsSceneMouseRelease:
\r
535 if( this->m_Conn && me->button( ) == Qt::LeftButton )
\r
537 QGraphicsItem* item = itemAt( me->scenePos( ) );
\r
538 if( item && item->type( ) == QNEPort::Type )
\r
540 QNEPort* port1 = this->m_Conn->port1( );
\r
541 QNEPort* port2 = ( QNEPort* ) item;
\r
542 if( port1->block( ) != port2->block( ) && port1->isOutput( ) != port2->isOutput( ) && !port1->isConnected( port2 ) )
\r
544 this->m_Conn->setPos2( port2->scenePos( ) );
\r
545 this->m_Conn->setPort2( port2 );
\r
546 this->m_Conn->updatePath( );
\r
547 this->m_Conn = NULL;
\r
552 delete this->m_Conn;
\r
553 this->m_Conn = NULL;
\r
561 return( this->Superclass::eventFilter( o, e ) );
\r