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 if( this->m_Conn->port1( ) == NULL )
\r
359 this->m_Conn->setPos1( evt->scenePos( ) );
\r
360 else if( this->m_Conn->port2( ) == NULL )
\r
361 this->m_Conn->setPos2( evt->scenePos( ) );
\r
362 this->m_Conn->updatePath( );
\r
370 case QEvent::GraphicsSceneMousePress:
\r
372 QGraphicsSceneMouseEvent* evt =
\r
373 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
376 switch( evt->button( ) )
\r
378 case Qt::LeftButton:
\r
380 QNEOutputPort* port =
\r
381 dynamic_cast< QNEOutputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
384 if( port->block( ) != NULL )
\r
386 this->m_Conn = new QNEConnection( 0, this->m_Scene );
\r
387 this->m_Conn->setPort1( port );
\r
388 this->m_Conn->setPos1( port->scenePos( ) );
\r
389 this->m_Conn->setPos2( evt->scenePos( ) );
\r
390 this->m_Conn->updatePath( );
\r
398 case Qt::RightButton:
\r
400 QNEInputPort* in_port =
\r
401 dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
402 QNEOutputPort* out_port =
\r
403 dynamic_cast< QNEOutputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
404 if( in_port != NULL )
\r
406 if( in_port->connection( ) == NULL && in_port->block( ) != NULL )
\r
408 this->m_Conn = new QNEConnection( 0, this->m_Scene );
\r
409 this->m_Conn->setPort2( in_port );
\r
410 this->m_Conn->setPos1( evt->scenePos( ) );
\r
411 this->m_Conn->setPos2( in_port->scenePos( ) );
\r
412 this->m_Conn->updatePath( );
\r
417 else if( out_port != NULL && out_port->block( ) != NULL )
\r
419 this->m_Conn = new QNEConnection( 0, this->m_Scene );
\r
420 this->m_Conn->setPort1( out_port );
\r
421 this->m_Conn->setPos1( out_port->scenePos( ) );
\r
422 this->m_Conn->setPos2( evt->scenePos( ) );
\r
423 this->m_Conn->updatePath( );
\r
437 case QEvent::GraphicsSceneMouseRelease:
\r
439 QGraphicsSceneMouseEvent* evt =
\r
440 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
443 if( this->m_Conn != NULL && evt->button( ) == Qt::LeftButton )
\r
445 QNEInputPort* port2 =
\r
446 dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
447 if( port2 != NULL )
\r
449 QNEOutputPort* port1 =
\r
450 dynamic_cast< QNEOutputPort* >( this->m_Conn->port1( ) );
\r
451 if( port1 != NULL )
\r
454 port1->block( ) != port2->block( ) &&
\r
455 !port2->hasConnection( ) &&
\r
456 !port1->isConnected( port2 )
\r
459 this->m_Conn->setPos2( port2->scenePos( ) );
\r
460 this->m_Conn->setPort2( port2 );
\r
461 this->m_Conn->updatePath( );
\r
463 this->m_Workspace->Connect(
\r
464 port1->block( )->namePort( ).toStdString( ),
\r
465 port2->block( )->namePort( ).toStdString( ),
\r
466 port1->name( ).toStdString( ),
\r
467 port2->name( ).toStdString( )
\r
469 this->m_Graph->AddConnection(
\r
470 port1->block( )->namePort( ).toStdString( ),
\r
471 port2->block( )->namePort( ).toStdString( ),
\r
475 this->m_Conn = NULL;
\r
483 delete this->m_Conn;
\r
484 this->m_Conn = NULL;
\r
487 else if( this->m_Conn != NULL && evt->button( ) == Qt::RightButton )
\r
489 QNEOutputPort* port1 = this->m_Conn->port1( );
\r
490 QNEInputPort* port2 = this->m_Conn->port2( );
\r
492 if( port1 != NULL && port2 == NULL )
\r
495 dynamic_cast< QNEInputPort* >(
\r
496 this->itemAt( evt->scenePos( ) )
\r
500 port2 = new QNEInputPort( NULL, this->m_Scene );
\r
501 port2->setName( port1->name( ) );
\r
502 port2->setPos( evt->scenePos( ) );
\r
503 this->m_Conn->setPos2( evt->scenePos( ) );
\r
504 this->m_Conn->setPort2( port2 );
\r
505 this->m_Conn->updatePath( );
\r
508 delete this->m_Conn;
\r
509 this->m_Conn = NULL;
\r
512 else if( port1 == NULL && port2 != NULL )
\r
515 dynamic_cast< QNEOutputPort* >(
\r
516 this->itemAt( evt->scenePos( ) )
\r
520 port1 = new QNEOutputPort( NULL, this->m_Scene );
\r
521 port1->setName( port2->name( ) );
\r
522 port1->setPos( evt->scenePos( ) );
\r
523 this->m_Conn->setPos1( evt->scenePos( ) );
\r
524 this->m_Conn->setPort1( port1 );
\r
525 this->m_Conn->updatePath( );
\r
528 delete this->m_Conn;
\r
529 this->m_Conn = NULL;
\r
539 case QEvent::GraphicsSceneMove:
\r
541 QGraphicsSceneMoveEvent* evt =
\r
542 dynamic_cast< QGraphicsSceneMoveEvent* >( e );
\r
548 case QEvent::GraphicsSceneResize:
\r
550 QGraphicsSceneResizeEvent* evt =
\r
551 dynamic_cast< QGraphicsSceneResizeEvent* >( e );
\r
557 case QEvent::GraphicsSceneWheel:
\r
559 QGraphicsSceneWheelEvent* evt =
\r
560 dynamic_cast< QGraphicsSceneWheelEvent* >( e );
\r
572 QGraphicsSceneMouseEvent* me =
\r
573 dynamic_cast< QGraphicsSceneMouseEvent* >( e );
\r
580 switch( ( int ) e->type( ) )
\r
582 case QEvent::GraphicsSceneMouseMove:
\r
586 this->m_Conn->setPos2( me->scenePos( ) );
\r
587 this->m_Conn->updatePath( );
\r
592 case QEvent::GraphicsSceneMouseRelease:
\r
594 if( this->m_Conn && me->button( ) == Qt::LeftButton )
\r
596 QGraphicsItem* item = itemAt( me->scenePos( ) );
\r
597 if( item && item->type( ) == QNEPort::Type )
\r
599 QNEPort* port1 = this->m_Conn->port1( );
\r
600 QNEPort* port2 = ( QNEPort* ) item;
\r
601 if( port1->block( ) != port2->block( ) && port1->isOutput( ) != port2->isOutput( ) && !port1->isConnected( port2 ) )
\r
603 this->m_Conn->setPos2( port2->scenePos( ) );
\r
604 this->m_Conn->setPort2( port2 );
\r
605 this->m_Conn->updatePath( );
\r
606 this->m_Conn = NULL;
\r
611 delete this->m_Conn;
\r
612 this->m_Conn = NULL;
\r
620 return( this->Superclass::eventFilter( o, e ) );
\r