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 if( this->m_Workspace == ws )
\r
81 this->m_Workspace = ws;
\r
82 this->m_Graph = TGraph::New( );
\r
85 auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( );
\r
86 auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( );
\r
87 for( ; vIt != vIt_end; ++vIt )
\r
90 dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ),
\r
97 auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( );
\r
98 auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( );
\r
99 for( ; rIt != rIt_end; ++rIt )
\r
101 if( !this->m_Graph->HasVertexIndex( rIt->first ) )
\r
103 QNEBlock* orig = this->m_Graph->GetVertex( rIt->first );
\r
106 QVector< QNEOutputPort* >& oPorts = orig->outputPorts( );
\r
108 auto cIt = rIt->second.begin( );
\r
109 for( ; cIt != rIt->second.end( ); ++cIt )
\r
111 if( !this->m_Graph->HasVertexIndex( cIt->first ) )
\r
113 QNEBlock* dest = this->m_Graph->GetVertex( cIt->first );
\r
116 QVector< QNEInputPort* >& iPorts = dest->inputPorts( );
\r
118 auto eIt = cIt->second.begin( );
\r
119 for( ; eIt != cIt->second.end( ); ++eIt )
\r
121 QNEOutputPort* op = NULL;
\r
122 auto opIt = oPorts.begin( );
\r
123 for( ; opIt != oPorts.end( ) && op == NULL; ++opIt )
\r
124 if( ( *opIt )->name( ).toStdString( ) == eIt->first )
\r
127 QNEInputPort* ip = NULL;
\r
128 auto ipIt = iPorts.begin( );
\r
129 for( ; ipIt != iPorts.end( ) && ip == NULL; ++ipIt )
\r
130 if( ( *ipIt )->name( ).toStdString( ) == eIt->second )
\r
133 if( op == NULL || ip == NULL )
\r
136 QNEConnection* conn = new QNEConnection( 0, this->m_Scene );
\r
137 conn->setPort1( op );
\r
138 conn->setPort2( ip );
\r
139 conn->updatePosFromPorts( );
\r
140 conn->updatePath( );
\r
141 this->m_Graph->AddConnection( rIt->first, cIt->first, conn );
\r
150 // -------------------------------------------------------------------------
\r
151 std::string PipelineEditor::QNodesEditor::
\r
152 createFilter( const std::string& filter, const QPointF& pnt )
\r
154 std::string name = filter;
\r
155 while( this->m_Workspace->HasFilter( name ) )
\r
156 name += std::string( "_" );
\r
157 if( this->m_Workspace->CreateFilter( filter, name ) )
\r
159 this->_CreateBlock( this->m_Workspace->GetFilter( name ), pnt );
\r
166 // -------------------------------------------------------------------------
\r
167 void PipelineEditor::QNodesEditor::
\r
168 install( QGraphicsScene* s )
\r
170 s->installEventFilter( this );
\r
174 // -------------------------------------------------------------------------
\r
175 QGraphicsItem* PipelineEditor::QNodesEditor::
\r
176 itemAt( const QPointF& pos )
\r
178 QList< QGraphicsItem* > items =
\r
179 this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );
\r
181 foreach( QGraphicsItem* item, items )
\r
182 if( item->type( ) > QGraphicsItem::UserType )
\r
187 #include <iostream>
\r
189 // -------------------------------------------------------------------------
\r
190 void PipelineEditor::QNodesEditor::
\r
191 _CreateBlock( TFilter* f, const QPointF& pnt )
\r
197 QNEBlock* b = new QNEBlock( 0, this->m_Scene );
\r
198 b->setNamePort( f->GetName( ) );
\r
199 b->setTypePort( f->GetClassName( ).c_str( ) );
\r
200 // TODO: b->setScenePos( pnt );
\r
203 std::set< std::string > inputs;
\r
204 f->GetInputsNames( inputs );
\r
205 for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt )
\r
206 b->addInputPort( iIt->c_str( ) );
\r
208 // Add output ports
\r
209 std::set< std::string > outputs;
\r
210 f->GetOutputsNames( outputs );
\r
211 for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt )
\r
212 b->addOutputPort( oIt->c_str( ) );
\r
214 // Keep a trace of this visual graph
\r
215 this->m_Graph->InsertVertex( f->GetName( ), b );
\r
218 // -------------------------------------------------------------------------
\r
219 void PipelineEditor::QNodesEditor::
\r
220 _DoubleClick( QGraphicsSceneMouseEvent* evt, QGraphicsItem* item )
\r
222 switch( evt->button( ) )
\r
224 case Qt::LeftButton:
\r
226 QNEBlock* block = dynamic_cast< QNEBlock* >( item );
\r
227 QNEPort* port = dynamic_cast< QNEPort* >( item );
\r
228 QNEConnection* conn = dynamic_cast< QNEConnection* >( item );
\r
230 if( block != NULL )
\r
233 auto ports = block->ports( );
\r
234 std::string name = "";
\r
236 auto pIt = ports.begin( );
\r
237 pIt != ports.end( ) && name == "";
\r
241 ( *pIt )->portFlags( ) && QNEPort::NamePort == QNEPort::NamePort
\r
243 name = ( *pIt )->portName( ).toStdString( );
\r
246 TFilter* filter = this->m_Workspace->GetFilter( name );
\r
247 if( filter != NULL )
\r
252 else if( port != NULL )
\r
255 else if( conn != NULL )
\r
261 case Qt::RightButton:
\r
265 case Qt::MiddleButton:
\r
275 // -------------------------------------------------------------------------
\r
276 bool PipelineEditor::QNodesEditor::
\r
277 eventFilter( QObject* o, QEvent* e )
\r
280 switch( int( e->type( ) ) )
\r
282 case QEvent::GraphicsSceneContextMenu:
\r
284 QGraphicsSceneContextMenuEvent* evt =
\r
285 dynamic_cast< QGraphicsSceneContextMenuEvent* >( e );
\r
291 case QEvent::GraphicsSceneDragEnter:
\r
293 QGraphicsSceneDragDropEvent* evt =
\r
294 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
300 case QEvent::GraphicsSceneDragLeave:
\r
302 QGraphicsSceneDragDropEvent* evt =
\r
303 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
309 case QEvent::GraphicsSceneDragMove:
\r
311 QGraphicsSceneDragDropEvent* evt =
\r
312 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
318 case QEvent::GraphicsSceneDrop:
\r
320 QGraphicsSceneDragDropEvent* evt =
\r
321 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
327 case QEvent::GraphicsSceneHelp:
\r
329 QGraphicsSceneHelpEvent* evt =
\r
330 dynamic_cast< QGraphicsSceneHelpEvent* >( e );
\r
336 case QEvent::GraphicsSceneHoverEnter:
\r
338 QGraphicsSceneHoverEvent* evt =
\r
339 dynamic_cast< QGraphicsSceneHoverEvent* >( e );
\r
345 case QEvent::GraphicsSceneHoverLeave:
\r
347 QGraphicsSceneHoverEvent* evt =
\r
348 dynamic_cast< QGraphicsSceneHoverEvent* >( e );
\r
354 case QEvent::GraphicsSceneHoverMove:
\r
356 QGraphicsSceneHoverEvent* evt =
\r
357 dynamic_cast< QGraphicsSceneHoverEvent* >( e );
\r
363 case QEvent::GraphicsSceneMouseDoubleClick:
\r
365 QGraphicsSceneMouseEvent* evt =
\r
366 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
369 QGraphicsItem* item = this->itemAt( evt->scenePos( ) );
\r
372 this->_DoubleClick( evt, item );
\r
380 case QEvent::GraphicsSceneMouseMove:
\r
382 QGraphicsSceneMouseEvent* evt =
\r
383 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
388 this->m_Conn->setPos2( evt->scenePos( ) );
\r
389 this->m_Conn->updatePath( );
\r
397 case QEvent::GraphicsSceneMousePress:
\r
399 QGraphicsSceneMouseEvent* evt =
\r
400 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
403 switch( evt->button( ) )
\r
405 case Qt::LeftButton:
\r
407 QNEOutputPort* port =
\r
408 dynamic_cast< QNEOutputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
411 this->m_Conn = new QNEConnection( 0, this->m_Scene );
\r
412 this->m_Conn->setPort1( port );
\r
413 this->m_Conn->setPos1( port->scenePos( ) );
\r
414 this->m_Conn->setPos2( evt->scenePos( ) );
\r
415 this->m_Conn->updatePath( );
\r
429 case QEvent::GraphicsSceneMouseRelease:
\r
431 QGraphicsSceneMouseEvent* evt =
\r
432 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
435 if( this->m_Conn != NULL && evt->button( ) == Qt::LeftButton )
\r
437 QNEInputPort* port2 =
\r
438 dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
439 if( port2 != NULL )
\r
441 QNEOutputPort* port1 =
\r
442 dynamic_cast< QNEOutputPort* >( this->m_Conn->port1( ) );
\r
443 if( port1 != NULL )
\r
446 port1->block( ) != port2->block( ) &&
\r
447 !port2->hasConnection( ) &&
\r
448 !port1->isConnected( port2 )
\r
451 this->m_Conn->setPos2( port2->scenePos( ) );
\r
452 this->m_Conn->setPort2( port2 );
\r
453 this->m_Conn->updatePath( );
\r
455 this->m_Workspace->Connect(
\r
456 port1->block( )->namePort( )->name( ).toStdString( ),
\r
457 port2->block( )->namePort( )->name( ).toStdString( ),
\r
458 port1->name( ).toStdString( ),
\r
459 port2->name( ).toStdString( )
\r
461 this->m_Graph->AddConnection(
\r
462 port1->block( )->namePort( )->name( ).toStdString( ),
\r
463 port2->block( )->namePort( )->name( ).toStdString( ),
\r
467 this->m_Conn = NULL;
\r
475 delete this->m_Conn;
\r
476 this->m_Conn = NULL;
\r
484 case QEvent::GraphicsSceneMove:
\r
486 QGraphicsSceneMoveEvent* evt =
\r
487 dynamic_cast< QGraphicsSceneMoveEvent* >( e );
\r
493 case QEvent::GraphicsSceneResize:
\r
495 QGraphicsSceneResizeEvent* evt =
\r
496 dynamic_cast< QGraphicsSceneResizeEvent* >( e );
\r
502 case QEvent::GraphicsSceneWheel:
\r
504 QGraphicsSceneWheelEvent* evt =
\r
505 dynamic_cast< QGraphicsSceneWheelEvent* >( e );
\r
517 QGraphicsSceneMouseEvent* me =
\r
518 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
525 switch( ( int ) e->type( ) )
\r
527 case QEvent::GraphicsSceneMouseMove:
\r
531 this->m_Conn->setPos2( me->scenePos( ) );
\r
532 this->m_Conn->updatePath( );
\r
537 case QEvent::GraphicsSceneMouseRelease:
\r
539 if( this->m_Conn && me->button( ) == Qt::LeftButton )
\r
541 QGraphicsItem* item = itemAt( me->scenePos( ) );
\r
542 if( item && item->type( ) == QNEPort::Type )
\r
544 QNEPort* port1 = this->m_Conn->port1( );
\r
545 QNEPort* port2 = ( QNEPort* ) item;
\r
546 if( port1->block( ) != port2->block( ) && port1->isOutput( ) != port2->isOutput( ) && !port1->isConnected( port2 ) )
\r
548 this->m_Conn->setPos2( port2->scenePos( ) );
\r
549 this->m_Conn->setPort2( port2 );
\r
550 this->m_Conn->updatePath( );
\r
551 this->m_Conn = NULL;
\r
556 delete this->m_Conn;
\r
557 this->m_Conn = NULL;
\r
565 return( this->Superclass::eventFilter( o, e ) );
\r