]> Creatis software - cpPlugins.git/blob - appli/cpPipelineEditor/QNodesEditor.cxx
...
[cpPlugins.git] / appli / cpPipelineEditor / QNodesEditor.cxx
1 /* Copyright (c) 2012, STANISLAW ADASZEWSKI\r
2    All rights reserved.\r
3 \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
14 \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
25 */\r
26 \r
27 #include "QNodesEditor.h"\r
28 \r
29 #include <QGraphicsScene>\r
30 #include <QEvent>\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
40 \r
41 #include "QNEPort.h"\r
42 #include "QNEConnection.h"\r
43 #include "QNEBlock.h"\r
44 \r
45 // -------------------------------------------------------------------------\r
46 PipelineEditor::QNodesEditor::\r
47 QNodesEditor( QObject* parent )\r
48  : Superclass( parent ),\r
49    m_Conn( NULL ),\r
50    m_Workspace( NULL )\r
51 {\r
52 }\r
53 \r
54 // -------------------------------------------------------------------------\r
55 PipelineEditor::QNodesEditor::\r
56 ~QNodesEditor( )\r
57 {\r
58 }\r
59 \r
60 // -------------------------------------------------------------------------\r
61 PipelineEditor::QNodesEditor::\r
62 TWorkspace* PipelineEditor::QNodesEditor::\r
63 workspace( )\r
64 {\r
65   return( this->m_Workspace );\r
66 }\r
67 \r
68 // -------------------------------------------------------------------------\r
69 const PipelineEditor::QNodesEditor::\r
70 TWorkspace* PipelineEditor::QNodesEditor::\r
71 workspace( ) const\r
72 {\r
73   return( this->m_Workspace );\r
74 }\r
75 \r
76 // -------------------------------------------------------------------------\r
77 void PipelineEditor::QNodesEditor::\r
78 setWorkspace( TWorkspace* ws )\r
79 {\r
80   this->m_Workspace = ws;\r
81   this->m_Graph = TGraph::New( );\r
82 \r
83   // Create blocks\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
87   {\r
88     this->_CreateBlock(\r
89       dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ),\r
90       QPointF( vIt->second->GetViewX( ), vIt->second->GetViewY( ) )\r
91       );\r
92 \r
93   } // rof\r
94 \r
95   // Add edges\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
99   {\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
103     {\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
107       {\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
111           continue;\r
112 \r
113         QNEConnection* c = new QNEConnection( 0, this->m_Scene );\r
114         c->setPort1( op );\r
115         c->setPort2( ip );\r
116         c->updatePosFromPorts( );\r
117         c->updatePath( );\r
118         this->m_Graph->AddConnection( rIt->first, cIt->first, c );\r
119 \r
120       } // rof\r
121 \r
122     } // rof\r
123 \r
124   } // rof\r
125 }\r
126 \r
127 // -------------------------------------------------------------------------\r
128 std::string PipelineEditor::QNodesEditor::\r
129 createFilter( const std::string& filter, const QPointF& pnt )\r
130 {\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
135   {\r
136     this->_CreateBlock( this->m_Workspace->GetFilter( name ), pnt );\r
137     return( name );\r
138   }\r
139   else\r
140     return( "" );\r
141 }\r
142 \r
143 // -------------------------------------------------------------------------\r
144 void PipelineEditor::QNodesEditor::\r
145 install( QGraphicsScene* s )\r
146 {\r
147   s->installEventFilter( this );\r
148   this->m_Scene = s;\r
149 }\r
150 \r
151 // -------------------------------------------------------------------------\r
152 QGraphicsItem* PipelineEditor::QNodesEditor::\r
153 itemAt( const QPointF& pos )\r
154 {\r
155   QList< QGraphicsItem* > items =\r
156     this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );\r
157 \r
158   foreach( QGraphicsItem* item, items )\r
159     if( item->type( ) > QGraphicsItem::UserType )\r
160       return( item );\r
161   return( NULL );\r
162 }\r
163 \r
164 // -------------------------------------------------------------------------\r
165 void PipelineEditor::QNodesEditor::\r
166 _CreateBlock( TFilter* f, const QPointF& pnt )\r
167 {\r
168   if( f == NULL )\r
169     return;\r
170 \r
171   // Add block\r
172   QNEBlock* b = new QNEBlock( f, 0, this->m_Scene );\r
173   b->setPos( pnt );\r
174 \r
175   // Keep a trace of this visual graph\r
176   this->m_Graph->SetVertex( f->GetName( ), b );\r
177 }\r
178 \r
179 // -------------------------------------------------------------------------\r
180 void PipelineEditor::QNodesEditor::\r
181 _DoubleClick( QGraphicsSceneMouseEvent* evt, QGraphicsItem* item )\r
182 {\r
183   switch( evt->button( ) )\r
184   {\r
185   case Qt::LeftButton:\r
186   {\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
190 \r
191     if( block != NULL )\r
192     {\r
193       QString old_name = block->namePort( );\r
194       bool ok;\r
195       QString new_name =\r
196         QInputDialog::getText(\r
197           dynamic_cast< QWidget* >( this->parent( ) ),\r
198           "Change filter name",\r
199           "Filter name:",\r
200           QLineEdit::Normal,\r
201           old_name,\r
202           &ok\r
203           );\r
204       if( ok && !new_name.isEmpty( ) && old_name != new_name )\r
205       {\r
206         ok = this->m_Graph->RenameVertex(\r
207           old_name.toStdString( ),\r
208           new_name.toStdString( )\r
209           );\r
210         if( ok )\r
211         {\r
212           block->setNamePort( new_name );\r
213           this->m_Workspace->GetGraph( )->RenameVertex(\r
214             old_name.toStdString( ),\r
215             new_name.toStdString( )\r
216             );\r
217 \r
218         } // fi\r
219 \r
220       } // fi\r
221     }\r
222     else if( port != NULL )\r
223     {\r
224     }\r
225     else if( conn != NULL )\r
226     {\r
227     } // fi\r
228   }\r
229   break;\r
230   /* TODO:\r
231      case Qt::RightButton:\r
232      {\r
233      }\r
234      break;\r
235      case Qt::MiddleButton:\r
236      {\r
237      }\r
238      break;\r
239   */\r
240   default:\r
241     break;\r
242   } // hctiws\r
243 }\r
244 \r
245 // -------------------------------------------------------------------------\r
246 bool PipelineEditor::QNodesEditor::\r
247 eventFilter( QObject* o, QEvent* e )\r
248 {\r
249   // Event type\r
250   switch( int( e->type( ) ) )\r
251   {\r
252   case QEvent::GraphicsSceneContextMenu:\r
253   {\r
254     QGraphicsSceneContextMenuEvent* evt =\r
255       dynamic_cast< QGraphicsSceneContextMenuEvent* >( e );\r
256     if( evt != NULL )\r
257     {\r
258     } // fi\r
259   }\r
260   break;\r
261   case QEvent::GraphicsSceneDragEnter:\r
262   {\r
263     QGraphicsSceneDragDropEvent* evt =\r
264       dynamic_cast< QGraphicsSceneDragDropEvent* >( e );\r
265     if( evt != NULL )\r
266     {\r
267     } // fi\r
268   }\r
269   break;\r
270   case QEvent::GraphicsSceneDragLeave:\r
271   {\r
272     QGraphicsSceneDragDropEvent* evt =\r
273       dynamic_cast< QGraphicsSceneDragDropEvent* >( e );\r
274     if( evt != NULL )\r
275     {\r
276     } // fi\r
277   }\r
278   break;\r
279   case QEvent::GraphicsSceneDragMove:\r
280   {\r
281     QGraphicsSceneDragDropEvent* evt =\r
282       dynamic_cast< QGraphicsSceneDragDropEvent* >( e );\r
283     if( evt != NULL )\r
284     {\r
285     } // fi\r
286   }\r
287   break;\r
288   case QEvent::GraphicsSceneDrop:\r
289   {\r
290     QGraphicsSceneDragDropEvent* evt =\r
291       dynamic_cast< QGraphicsSceneDragDropEvent* >( e );\r
292     if( evt != NULL )\r
293     {\r
294     } // fi\r
295   }\r
296   break;\r
297   case QEvent::GraphicsSceneHelp:\r
298   {\r
299     QGraphicsSceneHelpEvent* evt =\r
300       dynamic_cast< QGraphicsSceneHelpEvent* >( e );\r
301     if( evt != NULL )\r
302     {\r
303     } // fi\r
304   }\r
305   break;\r
306   case QEvent::GraphicsSceneHoverEnter:\r
307   {\r
308     QGraphicsSceneHoverEvent* evt =\r
309       dynamic_cast< QGraphicsSceneHoverEvent* >( e );\r
310     if( evt != NULL )\r
311     {\r
312     } // fi\r
313   }\r
314   break;\r
315   case QEvent::GraphicsSceneHoverLeave:\r
316   {\r
317     QGraphicsSceneHoverEvent* evt =\r
318       dynamic_cast< QGraphicsSceneHoverEvent* >( e );\r
319     if( evt != NULL )\r
320     {\r
321     } // fi\r
322   }\r
323   break;\r
324   case QEvent::GraphicsSceneHoverMove:\r
325   {\r
326     QGraphicsSceneHoverEvent* evt =\r
327       dynamic_cast< QGraphicsSceneHoverEvent* >( e );\r
328     if( evt != NULL )\r
329     {\r
330     } // fi\r
331   }\r
332   break;\r
333   case QEvent::GraphicsSceneMouseDoubleClick:\r
334   {\r
335     QGraphicsSceneMouseEvent* evt =\r
336       dynamic_cast< QGraphicsSceneMouseEvent* >( e );\r
337     if( evt != NULL )\r
338     {\r
339       QGraphicsItem* item = this->itemAt( evt->scenePos( ) );\r
340       if( item != NULL )\r
341       {\r
342         this->_DoubleClick( evt, item );\r
343         return( true );\r
344 \r
345       } // fi\r
346 \r
347     } // fi\r
348   }\r
349   break;\r
350   case QEvent::GraphicsSceneMouseMove:\r
351   {\r
352     QGraphicsSceneMouseEvent* evt =\r
353       dynamic_cast< QGraphicsSceneMouseEvent* >( e );\r
354     if( evt != NULL )\r
355     {\r
356       if( this->m_Conn )\r
357       {\r
358         this->m_Conn->setPos2( evt->scenePos( ) );\r
359         this->m_Conn->updatePath( );\r
360         return( true );\r
361 \r
362       } // fi\r
363 \r
364     } // fi\r
365   }\r
366   break;\r
367   case QEvent::GraphicsSceneMousePress:\r
368   {\r
369     QGraphicsSceneMouseEvent* evt =\r
370       dynamic_cast< QGraphicsSceneMouseEvent* >( e );\r
371     if( evt != NULL )\r
372     {\r
373       switch( evt->button( ) )\r
374       {\r
375       case Qt::LeftButton:\r
376       {\r
377         QNEOutputPort* port =\r
378           dynamic_cast< QNEOutputPort* >( this->itemAt( evt->scenePos( ) ) );\r
379         if( port != NULL )\r
380         {\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
386           return( true );\r
387 \r
388         } // fi\r
389       }\r
390       break;\r
391       case Qt::RightButton:\r
392       {\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
398         {\r
399           if( in_port->connection( ) == NULL )\r
400           {\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
406             return( true );\r
407 \r
408           } // fi\r
409         }\r
410         else if( out_port != NULL )\r
411         {\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
417           return( true );\r
418 \r
419         } // fi\r
420       }\r
421       break;\r
422       default:\r
423         break;\r
424 \r
425       } // hctiws\r
426 \r
427     } // fi\r
428   }\r
429   break;\r
430   case QEvent::GraphicsSceneMouseRelease:\r
431   {\r
432     QGraphicsSceneMouseEvent* evt =\r
433       dynamic_cast< QGraphicsSceneMouseEvent* >( e );\r
434     if( evt != NULL )\r
435     {\r
436       if( this->m_Conn != NULL && evt->button( ) == Qt::LeftButton )\r
437       {\r
438         QNEInputPort* port2 =\r
439           dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );\r
440         if( port2 != NULL )\r
441         {\r
442           QNEOutputPort* port1 =\r
443             dynamic_cast< QNEOutputPort* >( this->m_Conn->port1( ) );\r
444           if( port1 != NULL )\r
445           {\r
446             if(\r
447               port1->block( ) != port2->block( ) &&\r
448               !port2->hasConnection( ) &&\r
449               !port1->isConnected( port2 )\r
450               )\r
451             {\r
452               this->m_Conn->setPos2( port2->scenePos( ) );\r
453               this->m_Conn->setPort2( port2 );\r
454               this->m_Conn->updatePath( );\r
455 \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
461                 );\r
462               this->m_Graph->AddConnection(\r
463                 port1->block( )->namePort( ).toStdString( ),\r
464                 port2->block( )->namePort( ).toStdString( ),\r
465                 this->m_Conn\r
466                 );\r
467 \r
468               this->m_Conn = NULL;\r
469               return( true );\r
470 \r
471             } // fi\r
472 \r
473           } // fi\r
474 \r
475         } // fi\r
476         delete this->m_Conn;\r
477         this->m_Conn = NULL;\r
478         return( true );\r
479       }\r
480       else if( this->m_Conn != NULL && evt->button( ) == Qt::RightButton )\r
481       {\r
482         QNEOutputPort* port1 = this->m_Conn->port1( );\r
483         QNEInputPort* port2 = this->m_Conn->port2( );\r
484 \r
485         if( port1 != NULL && port2 == NULL )\r
486         {\r
487           if(\r
488             dynamic_cast< QNEInputPort* >(\r
489               this->itemAt( evt->scenePos( ) )\r
490               ) == NULL\r
491             )\r
492           {\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
499           }\r
500           else\r
501             delete this->m_Conn;\r
502           this->m_Conn = NULL;\r
503           return( true );\r
504         }\r
505         else if( port1 == NULL && port2 != NULL )\r
506         {\r
507           if(\r
508             dynamic_cast< QNEOutputPort* >(\r
509               this->itemAt( evt->scenePos( ) )\r
510               ) == NULL\r
511             /*&&\r
512             port2->connection( ) == NULL*/\r
513             )\r
514           {\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
521           }\r
522           else\r
523             delete this->m_Conn;\r
524           this->m_Conn = NULL;\r
525           return( true );\r
526 \r
527         } // fi\r
528 \r
529       } // fi\r
530 \r
531     } // fi\r
532   }\r
533   break;\r
534   case QEvent::GraphicsSceneMove:\r
535   {\r
536     QGraphicsSceneMoveEvent* evt =\r
537       dynamic_cast< QGraphicsSceneMoveEvent* >( e );\r
538     if( evt != NULL )\r
539     {\r
540     } // fi\r
541   }\r
542   break;\r
543   case QEvent::GraphicsSceneResize:\r
544   {\r
545     QGraphicsSceneResizeEvent* evt =\r
546       dynamic_cast< QGraphicsSceneResizeEvent* >( e );\r
547     if( evt != NULL )\r
548     {\r
549     } // fi\r
550   }\r
551   break;\r
552   case QEvent::GraphicsSceneWheel:\r
553   {\r
554     QGraphicsSceneWheelEvent* evt =\r
555       dynamic_cast< QGraphicsSceneWheelEvent* >( e );\r
556     if( evt != NULL )\r
557     {\r
558     } // fi\r
559   }\r
560   break;\r
561   default:\r
562     break;\r
563   } // hctiws\r
564 \r
565   // Mouse event\r
566   /*\r
567     QGraphicsSceneMouseEvent* me =\r
568     dynamic_cast< QGraphicsSceneMouseEvent* >( e );\r
569     if( me != NULL )\r
570     {\r
571     } // fi\r
572   */\r
573 \r
574   /* TODO\r
575      switch( ( int ) e->type( ) )\r
576      {\r
577      case QEvent::GraphicsSceneMouseMove:\r
578      {\r
579      if( this->m_Conn )\r
580      {\r
581      this->m_Conn->setPos2( me->scenePos( ) );\r
582      this->m_Conn->updatePath( );\r
583      return( true );\r
584      }\r
585      break;\r
586      }\r
587      case QEvent::GraphicsSceneMouseRelease:\r
588      {\r
589      if( this->m_Conn && me->button( ) == Qt::LeftButton )\r
590      {\r
591      QGraphicsItem* item = itemAt( me->scenePos( ) );\r
592      if( item && item->type( ) == QNEPort::Type )\r
593      {\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
597      {\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
602      return( true );\r
603      }\r
604      }\r
605 \r
606      delete this->m_Conn;\r
607      this->m_Conn = NULL;\r
608      return( true );\r
609      }\r
610      break;\r
611      }\r
612      } // hctiws\r
613   */\r
614 \r
615   return( this->Superclass::eventFilter( o, e ) );\r
616 }\r
617 \r
618 // eof - $RCSfile$\r