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 #define PipelineEditor_QNodesEditor_Callback_SWITCH( E, e ) \
\r
49 Q##E##Event* evt = dynamic_cast< Q##E##Event* >( e ); \
\r
51 this->_##E##_cbk( evt ); \
\r
55 // -------------------------------------------------------------------------
\r
56 #define PipelineEditor_QNodesEditor_Callback_CODE( E ) \
\r
57 void PipelineEditor::QNodesEditor::_##E##_cbk( Q##E##Event* evt )
\r
59 // -------------------------------------------------------------------------
\r
60 PipelineEditor::QNodesEditor::
\r
61 QNodesEditor( QObject* parent )
\r
62 : Superclass( parent ),
\r
68 // -------------------------------------------------------------------------
\r
69 PipelineEditor::QNodesEditor::
\r
74 // -------------------------------------------------------------------------
\r
75 PipelineEditor::QNodesEditor::
\r
76 TWorkspace* PipelineEditor::QNodesEditor::
\r
79 return( this->m_Workspace );
\r
82 // -------------------------------------------------------------------------
\r
83 const PipelineEditor::QNodesEditor::
\r
84 TWorkspace* PipelineEditor::QNodesEditor::
\r
87 return( this->m_Workspace );
\r
90 // -------------------------------------------------------------------------
\r
91 void PipelineEditor::QNodesEditor::
\r
92 setWorkspace( TWorkspace* ws )
\r
94 this->m_Workspace = ws;
\r
95 this->m_Graph = TGraph::New( );
\r
98 auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( );
\r
99 auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( );
\r
100 for( ; vIt != vIt_end; ++vIt )
\r
102 this->_CreateBlock(
\r
103 dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ),
\r
104 QPointF( vIt->second->GetViewX( ), vIt->second->GetViewY( ) )
\r
110 auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( );
\r
111 auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( );
\r
112 for( ; rIt != rIt_end; ++rIt )
\r
114 QNEBlock* orig = this->m_Graph->GetVertex( rIt->first );
\r
115 auto cIt = rIt->second.begin( );
\r
116 for( ; cIt != rIt->second.end( ); ++cIt )
\r
118 QNEBlock* dest = this->m_Graph->GetVertex( cIt->first );
\r
119 auto eIt = cIt->second.begin( );
\r
120 for( ; eIt != cIt->second.end( ); ++eIt )
\r
122 QNEOutputPort* op = orig->outputPort( eIt->first.c_str( ) );
\r
123 QNEInputPort* ip = dest->inputPort( eIt->second.c_str( ) );
\r
124 if( op == NULL || ip == NULL )
\r
127 QNEConnection* c = new QNEConnection( 0, this->m_Scene );
\r
130 c->updatePosFromPorts( );
\r
132 this->m_Graph->AddConnection( rIt->first, cIt->first, c );
\r
141 // -------------------------------------------------------------------------
\r
142 std::string PipelineEditor::QNodesEditor::
\r
143 createFilter( const std::string& filter, const QPointF& pnt )
\r
145 std::string name = filter;
\r
146 while( this->m_Workspace->HasFilter( name ) )
\r
147 name += std::string( "_" );
\r
148 if( this->m_Workspace->CreateFilter( filter, name ) )
\r
150 this->_CreateBlock( this->m_Workspace->GetFilter( name ), pnt );
\r
157 // -------------------------------------------------------------------------
\r
158 void PipelineEditor::QNodesEditor::
\r
159 install( QGraphicsScene* s )
\r
161 s->installEventFilter( this );
\r
165 // -------------------------------------------------------------------------
\r
166 QGraphicsItem* PipelineEditor::QNodesEditor::
\r
167 itemAt( const QPointF& pos )
\r
169 QList< QGraphicsItem* > items =
\r
170 this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );
\r
172 foreach( QGraphicsItem* item, items )
\r
173 if( item->type( ) > QGraphicsItem::UserType )
\r
178 // -------------------------------------------------------------------------
\r
179 void PipelineEditor::QNodesEditor::
\r
180 _CreateBlock( TFilter* f, const QPointF& pnt )
\r
186 QNEBlock* b = new QNEBlock( f, 0, this->m_Scene );
\r
189 // Keep a trace of this visual graph
\r
190 this->m_Graph->SetVertex( f->GetName( ), b );
\r
193 // -------------------------------------------------------------------------
\r
195 void PipelineEditor::QNodesEditor::
\r
196 _DoubleClick( QGraphicsSceneMouseEvent* evt, QGraphicsItem* item )
\r
198 switch( evt->button( ) )
\r
200 case Qt::LeftButton:
\r
202 QNEBlock* block = dynamic_cast< QNEBlock* >( item );
\r
203 QNEPort* port = dynamic_cast< QNEPort* >( item );
\r
204 QNEConnection* conn = dynamic_cast< QNEConnection* >( item );
\r
206 if( block != NULL )
\r
208 QString old_name = block->namePort( );
\r
211 QInputDialog::getText(
\r
212 dynamic_cast< QWidget* >( this->parent( ) ),
\r
213 "Change filter name",
\r
219 if( ok && !new_name.isEmpty( ) && old_name != new_name )
\r
221 ok = this->m_Graph->RenameVertex(
\r
222 old_name.toStdString( ),
\r
223 new_name.toStdString( )
\r
227 block->setNamePort( new_name );
\r
228 this->m_Workspace->GetGraph( )->RenameVertex(
\r
229 old_name.toStdString( ),
\r
230 new_name.toStdString( )
\r
237 else if( port != NULL )
\r
240 else if( conn != NULL )
\r
245 case Qt::RightButton:
\r
249 case Qt::MiddleButton:
\r
259 // -------------------------------------------------------------------------
\r
260 bool PipelineEditor::QNodesEditor::
\r
261 eventFilter( QObject* o, QEvent* e )
\r
264 switch( int( e->type( ) ) )
\r
266 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneContextMenu, e );
\r
267 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneDragEnter, e );
\r
268 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneDragLeave, e );
\r
269 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneDragMove, e );
\r
270 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneDrop, e );
\r
271 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneHelp, e );
\r
272 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneHoverEnter, e );
\r
273 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneHoverLeave, e );
\r
274 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneHoverMove, e );
\r
275 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneMouseDoubleClick, e );
\r
276 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneMouseMove, e );
\r
277 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneMousePress, e );
\r
278 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneMouseRelease, e );
\r
279 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneMove, e );
\r
280 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneResize, e );
\r
281 PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneWheel, e );
\r
286 return( this->Superclass::eventFilter( o, e ) );
\r
289 // -------------------------------------------------------------------------
\r
290 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneContextMenu )
\r
294 // -------------------------------------------------------------------------
\r
295 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneDragEnter )
\r
299 // -------------------------------------------------------------------------
\r
300 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneDragLeave )
\r
304 // -------------------------------------------------------------------------
\r
305 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneDragMove )
\r
309 // -------------------------------------------------------------------------
\r
310 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneDrop )
\r
314 // -------------------------------------------------------------------------
\r
315 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneHelp )
\r
319 // -------------------------------------------------------------------------
\r
320 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneHoverEnter )
\r
324 // -------------------------------------------------------------------------
\r
325 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneHoverLeave )
\r
329 // -------------------------------------------------------------------------
\r
330 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneHoverMove )
\r
334 // -------------------------------------------------------------------------
\r
335 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneMouseDoubleClick )
\r
337 QGraphicsItem* item = this->itemAt( evt->scenePos( ) );
\r
341 switch( evt->button( ) )
\r
343 case Qt::LeftButton:
\r
345 QNEBlock* block = dynamic_cast< QNEBlock* >( item );
\r
346 QNEPort* port = dynamic_cast< QNEPort* >( item );
\r
347 QNEConnection* conn = dynamic_cast< QNEConnection* >( item );
\r
349 if( block != NULL )
\r
351 QString old_name = block->namePort( );
\r
354 QInputDialog::getText(
\r
355 dynamic_cast< QWidget* >( this->parent( ) ),
\r
356 "Change filter name",
\r
362 if( ok && !new_name.isEmpty( ) && old_name != new_name )
\r
364 ok = this->m_Graph->RenameVertex(
\r
365 old_name.toStdString( ),
\r
366 new_name.toStdString( )
\r
370 block->setNamePort( new_name );
\r
371 this->m_Workspace->GetGraph( )->RenameVertex(
\r
372 old_name.toStdString( ),
\r
373 new_name.toStdString( )
\r
380 else if( port != NULL )
\r
382 if( evt->modifiers( ) == Qt::ControlModifier )
\r
384 port->setExtend( !( port->isExtended( ) ) );
\r
385 QNEInputPort* in_port = dynamic_cast< QNEInputPort* >( port );
\r
386 QNEOutputPort* out_port = dynamic_cast< QNEOutputPort* >( port );
\r
387 if( port->isExtended( ) )
\r
389 if( in_port != NULL )
\r
391 this->m_Workspace->AddInputPort(
\r
392 in_port->extendedName( ).toStdString( ),
\r
393 in_port->block( )->namePort( ).toStdString( ),
\r
394 in_port->name( ).toStdString( )
\r
397 else if( out_port != NULL )
\r
403 if( in_port != NULL )
\r
406 else if( out_port != NULL )
\r
411 this->m_Scene->update( );
\r
413 else if( evt->modifiers( ) == Qt::NoModifier )
\r
415 if( port->isExtended( ) )
\r
417 QString old_name = port->extendedName( );
\r
420 QInputDialog::getText(
\r
421 dynamic_cast< QWidget* >( this->parent( ) ),
\r
422 "Change filter name",
\r
428 if( ok && !new_name.isEmpty( ) && old_name != new_name )
\r
430 // TODO: port->setExtendedName( new_name );
\r
432 ok = this->m_Graph->RenameVertex(
\r
433 old_name.toStdString( ),
\r
434 new_name.toStdString( )
\r
438 block->setNamePort( new_name );
\r
439 this->m_Workspace->GetGraph( )->RenameVertex(
\r
440 old_name.toStdString( ),
\r
441 new_name.toStdString( )
\r
452 else if( conn != NULL )
\r
458 case Qt::RightButton:
\r
462 case Qt::MiddleButton:
\r
472 // -------------------------------------------------------------------------
\r
473 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneMouseMove )
\r
475 if( this->m_Conn != NULL )
\r
477 if( this->m_Conn->port1( ) == NULL )
\r
478 this->m_Conn->setPos1( evt->scenePos( ) );
\r
479 else if( this->m_Conn->port2( ) == NULL )
\r
480 this->m_Conn->setPos2( evt->scenePos( ) );
\r
481 this->m_Conn->updatePath( );
\r
486 // -------------------------------------------------------------------------
\r
487 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneMousePress )
\r
489 QNEInputPort* in_port =
\r
490 dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
491 QNEOutputPort* out_port =
\r
492 dynamic_cast< QNEOutputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
493 if( in_port == NULL && out_port == NULL )
\r
496 switch( evt->button( ) )
\r
498 case Qt::LeftButton:
\r
500 if( out_port != NULL )
\r
502 if( out_port->block( ) != NULL )
\r
504 // Start new connection
\r
505 this->m_Conn = new QNEConnection( 0, this->m_Scene );
\r
506 this->m_Conn->setPort1( out_port );
\r
507 this->m_Conn->setPos1( out_port->scenePos( ) );
\r
508 this->m_Conn->setPos2( evt->scenePos( ) );
\r
509 this->m_Conn->updatePosFromPorts( );
\r
510 this->m_Conn->updatePath( );
\r
523 // -------------------------------------------------------------------------
\r
524 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneMouseRelease )
\r
526 if( this->m_Conn == NULL )
\r
529 switch( evt->button( ) )
\r
531 case Qt::LeftButton:
\r
533 QNEInputPort* port2 =
\r
534 dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );
\r
535 if( port2 != NULL )
\r
537 QNEOutputPort* port1 =
\r
538 dynamic_cast< QNEOutputPort* >( this->m_Conn->port1( ) );
\r
539 if( port1 != NULL )
\r
542 port1->block( ) != port2->block( ) &&
\r
543 !port2->hasConnection( ) &&
\r
544 !port1->isConnected( port2 ) &&
\r
545 !port2->isExtended( )
\r
548 this->m_Conn->setPos2( port2->scenePos( ) );
\r
549 this->m_Conn->setPort2( port2 );
\r
550 this->m_Conn->updatePosFromPorts( );
\r
551 this->m_Conn->updatePath( );
\r
553 this->m_Workspace->Connect(
\r
554 port1->block( )->namePort( ).toStdString( ),
\r
555 port2->block( )->namePort( ).toStdString( ),
\r
556 port1->name( ).toStdString( ),
\r
557 port2->name( ).toStdString( )
\r
559 this->m_Graph->AddConnection(
\r
560 port1->block( )->namePort( ).toStdString( ),
\r
561 port2->block( )->namePort( ).toStdString( ),
\r
566 delete this->m_Conn;
\r
569 delete this->m_Conn;
\r
572 delete this->m_Conn;
\r
573 this->m_Conn = NULL;
\r
581 // -------------------------------------------------------------------------
\r
582 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneMove )
\r
586 // -------------------------------------------------------------------------
\r
587 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneResize )
\r
591 // -------------------------------------------------------------------------
\r
592 PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneWheel )
\r