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
39 #include <QInputDialog>
\r
41 #include "QNEPort.h"
\r
42 #include "QNEConnection.h"
\r
43 #include "QNEBlock.h"
\r
45 // -------------------------------------------------------------------------
\r
46 PipelineEditor::QNodesEditor::
\r
47 QNodesEditor( QObject* parent )
\r
48 : Superclass( parent ),
\r
54 // -------------------------------------------------------------------------
\r
55 PipelineEditor::QNodesEditor::
\r
60 // -------------------------------------------------------------------------
\r
61 PipelineEditor::QNodesEditor::
\r
62 TWorkspace* PipelineEditor::QNodesEditor::
\r
65 return( this->m_Workspace );
\r
68 // -------------------------------------------------------------------------
\r
69 const PipelineEditor::QNodesEditor::
\r
70 TWorkspace* PipelineEditor::QNodesEditor::
\r
73 return( this->m_Workspace );
\r
76 // -------------------------------------------------------------------------
\r
77 void PipelineEditor::QNodesEditor::
\r
78 setWorkspace( TWorkspace* ws )
\r
80 this->m_Workspace = ws;
\r
81 this->m_Graph = TGraph::New( );
\r
84 auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( );
\r
85 auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( );
\r
86 for( ; vIt != vIt_end; ++vIt )
\r
89 dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ),
\r
90 QPointF( vIt->second->GetViewX( ), vIt->second->GetViewY( ) )
\r
96 auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( );
\r
97 auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( );
\r
98 for( ; rIt != rIt_end; ++rIt )
\r
100 QNEBlock* orig = this->m_Graph->GetVertex( rIt->first );
\r
101 auto cIt = rIt->second.begin( );
\r
102 for( ; cIt != rIt->second.end( ); ++cIt )
\r
104 QNEBlock* dest = this->m_Graph->GetVertex( cIt->first );
\r
105 auto eIt = cIt->second.begin( );
\r
106 for( ; eIt != cIt->second.end( ); ++eIt )
\r
108 QNEOutputPort* op = orig->outputPort( eIt->first.c_str( ) );
\r
109 QNEInputPort* ip = dest->inputPort( eIt->second.c_str( ) );
\r
110 if( op == NULL || ip == NULL )
\r
113 QNEConnection* c = new QNEConnection( 0, this->m_Scene );
\r
116 c->updatePosFromPorts( );
\r
118 this->m_Graph->AddConnection( rIt->first, cIt->first, c );
\r
127 // -------------------------------------------------------------------------
\r
128 std::string PipelineEditor::QNodesEditor::
\r
129 createFilter( const std::string& filter, const QPointF& pnt )
\r
131 std::string name = filter;
\r
132 while( this->m_Workspace->HasFilter( name ) )
\r
133 name += std::string( "_" );
\r
134 if( this->m_Workspace->CreateFilter( filter, name ) )
\r
136 this->_CreateBlock( this->m_Workspace->GetFilter( name ), pnt );
\r
143 // -------------------------------------------------------------------------
\r
144 void PipelineEditor::QNodesEditor::
\r
145 install( QGraphicsScene* s )
\r
147 s->installEventFilter( this );
\r
151 // -------------------------------------------------------------------------
\r
152 QGraphicsItem* PipelineEditor::QNodesEditor::
\r
153 itemAt( const QPointF& pos )
\r
155 QList< QGraphicsItem* > items =
\r
156 this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );
\r
158 foreach( QGraphicsItem* item, items )
\r
159 if( item->type( ) > QGraphicsItem::UserType )
\r
164 // -------------------------------------------------------------------------
\r
165 void PipelineEditor::QNodesEditor::
\r
166 _CreateBlock( TFilter* f, const QPointF& pnt )
\r
172 QNEBlock* b = new QNEBlock( f, 0, this->m_Scene );
\r
175 // Keep a trace of this visual graph
\r
176 this->m_Graph->SetVertex( f->GetName( ), b );
\r
179 // -------------------------------------------------------------------------
\r
180 void PipelineEditor::QNodesEditor::
\r
181 _DoubleClick( QGraphicsSceneMouseEvent* evt, QGraphicsItem* item )
\r
183 switch( evt->button( ) )
\r
185 case Qt::LeftButton:
\r
187 QNEBlock* block = dynamic_cast< QNEBlock* >( item );
\r
188 QNEPort* port = dynamic_cast< QNEPort* >( item );
\r
189 QNEConnection* conn = dynamic_cast< QNEConnection* >( item );
\r
191 if( block != NULL )
\r
193 QString old_name = block->namePort( );
\r
196 QInputDialog::getText(
\r
197 dynamic_cast< QWidget* >( this->parent( ) ),
\r
198 "Change filter name",
\r
204 if( ok && !new_name.isEmpty( ) && old_name != new_name )
\r
206 ok = this->m_Graph->RenameVertex(
\r
207 old_name.toStdString( ),
\r
208 new_name.toStdString( )
\r
212 block->setNamePort( new_name );
\r
213 this->m_Workspace->GetGraph( )->RenameVertex(
\r
214 old_name.toStdString( ),
\r
215 new_name.toStdString( )
\r
222 else if( port != NULL )
\r
225 else if( conn != NULL )
\r
231 case Qt::RightButton:
\r
235 case Qt::MiddleButton:
\r
245 // -------------------------------------------------------------------------
\r
246 bool PipelineEditor::QNodesEditor::
\r
247 eventFilter( QObject* o, QEvent* e )
\r
250 switch( int( e->type( ) ) )
\r
252 case QEvent::GraphicsSceneContextMenu:
\r
254 QGraphicsSceneContextMenuEvent* evt =
\r
255 dynamic_cast< QGraphicsSceneContextMenuEvent* >( e );
\r
261 case QEvent::GraphicsSceneDragEnter:
\r
263 QGraphicsSceneDragDropEvent* evt =
\r
264 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
270 case QEvent::GraphicsSceneDragLeave:
\r
272 QGraphicsSceneDragDropEvent* evt =
\r
273 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
279 case QEvent::GraphicsSceneDragMove:
\r
281 QGraphicsSceneDragDropEvent* evt =
\r
282 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
288 case QEvent::GraphicsSceneDrop:
\r
290 QGraphicsSceneDragDropEvent* evt =
\r
291 dynamic_cast< QGraphicsSceneDragDropEvent* >( e );
\r
297 case QEvent::GraphicsSceneHelp:
\r
299 QGraphicsSceneHelpEvent* evt =
\r
300 dynamic_cast< QGraphicsSceneHelpEvent* >( e );
\r
306 case QEvent::GraphicsSceneHoverEnter:
\r
308 QGraphicsSceneHoverEvent* evt =
\r
309 dynamic_cast< QGraphicsSceneHoverEvent* >( e );
\r
315 case QEvent::GraphicsSceneHoverLeave:
\r
317 QGraphicsSceneHoverEvent* evt =
\r
318 dynamic_cast< QGraphicsSceneHoverEvent* >( e );
\r
324 case QEvent::GraphicsSceneHoverMove:
\r
326 QGraphicsSceneHoverEvent* evt =
\r
327 dynamic_cast< QGraphicsSceneHoverEvent* >( e );
\r
333 case QEvent::GraphicsSceneMouseDoubleClick:
\r
335 QGraphicsSceneMouseEvent* evt =
\r
336 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
339 QGraphicsItem* item = this->itemAt( evt->scenePos( ) );
\r
342 this->_DoubleClick( evt, item );
\r
350 case QEvent::GraphicsSceneMouseMove:
\r
352 QGraphicsSceneMouseEvent* evt =
\r
353 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
358 this->m_Conn->setPos2( evt->scenePos( ) );
\r
359 this->m_Conn->updatePath( );
\r
367 case QEvent::GraphicsSceneMousePress:
\r
369 QGraphicsSceneMouseEvent* evt =
\r
370 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
373 switch( evt->button( ) )
\r
375 case Qt::LeftButton:
\r
377 QNEOutputPort* port =
\r
378 dynamic_cast< QNEOutputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
381 this->m_Conn = new QNEConnection( 0, this->m_Scene );
\r
382 this->m_Conn->setPort1( port );
\r
383 this->m_Conn->setPos1( port->scenePos( ) );
\r
384 this->m_Conn->setPos2( evt->scenePos( ) );
\r
385 this->m_Conn->updatePath( );
\r
391 case Qt::RightButton:
\r
393 QNEInputPort* in_port =
\r
394 dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
395 QNEOutputPort* out_port =
\r
396 dynamic_cast< QNEOutputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
397 if( in_port != NULL )
\r
399 if( in_port->connection( ) == NULL )
\r
401 this->m_Conn = new QNEConnection( 0, this->m_Scene );
\r
402 this->m_Conn->setPort2( in_port );
\r
403 this->m_Conn->setPos1( evt->scenePos( ) );
\r
404 this->m_Conn->setPos2( in_port->scenePos( ) );
\r
405 this->m_Conn->updatePath( );
\r
410 else if( out_port != NULL )
\r
412 this->m_Conn = new QNEConnection( 0, this->m_Scene );
\r
413 this->m_Conn->setPort1( out_port );
\r
414 this->m_Conn->setPos1( out_port->scenePos( ) );
\r
415 this->m_Conn->setPos2( evt->scenePos( ) );
\r
416 this->m_Conn->updatePath( );
\r
430 case QEvent::GraphicsSceneMouseRelease:
\r
432 QGraphicsSceneMouseEvent* evt =
\r
433 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
436 if( this->m_Conn != NULL && evt->button( ) == Qt::LeftButton )
\r
438 QNEInputPort* port2 =
\r
439 dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
440 if( port2 != NULL )
\r
442 QNEOutputPort* port1 =
\r
443 dynamic_cast< QNEOutputPort* >( this->m_Conn->port1( ) );
\r
444 if( port1 != NULL )
\r
447 port1->block( ) != port2->block( ) &&
\r
448 !port2->hasConnection( ) &&
\r
449 !port1->isConnected( port2 )
\r
452 this->m_Conn->setPos2( port2->scenePos( ) );
\r
453 this->m_Conn->setPort2( port2 );
\r
454 this->m_Conn->updatePath( );
\r
456 this->m_Workspace->Connect(
\r
457 port1->block( )->namePort( ).toStdString( ),
\r
458 port2->block( )->namePort( ).toStdString( ),
\r
459 port1->name( ).toStdString( ),
\r
460 port2->name( ).toStdString( )
\r
462 this->m_Graph->AddConnection(
\r
463 port1->block( )->namePort( ).toStdString( ),
\r
464 port2->block( )->namePort( ).toStdString( ),
\r
468 this->m_Conn = NULL;
\r
476 delete this->m_Conn;
\r
477 this->m_Conn = NULL;
\r
480 else if( this->m_Conn != NULL && evt->button( ) == Qt::RightButton )
\r
482 QNEOutputPort* port1 = this->m_Conn->port1( );
\r
483 QNEInputPort* port2 = this->m_Conn->port2( );
\r
485 if( port1 != NULL && port2 == NULL )
\r
488 dynamic_cast< QNEInputPort* >(
\r
489 this->itemAt( evt->scenePos( ) )
\r
493 port2 = new QNEInputPort( NULL, this->m_Scene );
\r
494 port2->setName( port1->name( ) );
\r
495 port2->setPos( evt->scenePos( ) );
\r
496 this->m_Conn->setPos2( evt->scenePos( ) );
\r
497 this->m_Conn->setPort2( port2 );
\r
498 this->m_Conn->updatePath( );
\r
501 delete this->m_Conn;
\r
502 this->m_Conn = NULL;
\r
505 else if( port1 == NULL && port2 != NULL )
\r
508 dynamic_cast< QNEOutputPort* >(
\r
509 this->itemAt( evt->scenePos( ) )
\r
512 port2->connection( ) == NULL*/
\r
515 port1 = new QNEOutputPort( NULL, this->m_Scene );
\r
516 port1->setName( port2->name( ) );
\r
517 port1->setPos( evt->scenePos( ) );
\r
518 this->m_Conn->setPos1( evt->scenePos( ) );
\r
519 this->m_Conn->setPort1( port1 );
\r
520 this->m_Conn->updatePath( );
\r
523 delete this->m_Conn;
\r
524 this->m_Conn = NULL;
\r
534 case QEvent::GraphicsSceneMove:
\r
536 QGraphicsSceneMoveEvent* evt =
\r
537 dynamic_cast< QGraphicsSceneMoveEvent* >( e );
\r
543 case QEvent::GraphicsSceneResize:
\r
545 QGraphicsSceneResizeEvent* evt =
\r
546 dynamic_cast< QGraphicsSceneResizeEvent* >( e );
\r
552 case QEvent::GraphicsSceneWheel:
\r
554 QGraphicsSceneWheelEvent* evt =
\r
555 dynamic_cast< QGraphicsSceneWheelEvent* >( e );
\r
567 QGraphicsSceneMouseEvent* me =
\r
568 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
575 switch( ( int ) e->type( ) )
\r
577 case QEvent::GraphicsSceneMouseMove:
\r
581 this->m_Conn->setPos2( me->scenePos( ) );
\r
582 this->m_Conn->updatePath( );
\r
587 case QEvent::GraphicsSceneMouseRelease:
\r
589 if( this->m_Conn && me->button( ) == Qt::LeftButton )
\r
591 QGraphicsItem* item = itemAt( me->scenePos( ) );
\r
592 if( item && item->type( ) == QNEPort::Type )
\r
594 QNEPort* port1 = this->m_Conn->port1( );
\r
595 QNEPort* port2 = ( QNEPort* ) item;
\r
596 if( port1->block( ) != port2->block( ) && port1->isOutput( ) != port2->isOutput( ) && !port1->isConnected( port2 ) )
\r
598 this->m_Conn->setPos2( port2->scenePos( ) );
\r
599 this->m_Conn->setPort2( port2 );
\r
600 this->m_Conn->updatePath( );
\r
601 this->m_Conn = NULL;
\r
606 delete this->m_Conn;
\r
607 this->m_Conn = NULL;
\r
615 return( this->Superclass::eventFilter( o, e ) );
\r