]> Creatis software - cpPlugins.git/blob - appli/cpPipelineEditor/QNodesEditor.cxx
6417636e44ff256c6d30cbee0ce3786b5814e228
[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 \r
40 #include "QNEPort.h"\r
41 #include "QNEConnection.h"\r
42 #include "QNEBlock.h"\r
43 \r
44 // -------------------------------------------------------------------------\r
45 PipelineEditor::QNodesEditor::\r
46 QNodesEditor( QObject* parent )\r
47  : Superclass( parent ),\r
48    m_Conn( NULL ),\r
49    m_Workspace( NULL )\r
50 {\r
51 }\r
52 \r
53 // -------------------------------------------------------------------------\r
54 PipelineEditor::QNodesEditor::\r
55 ~QNodesEditor( )\r
56 {\r
57 }\r
58 \r
59 // -------------------------------------------------------------------------\r
60 PipelineEditor::QNodesEditor::\r
61 TWorkspace* PipelineEditor::QNodesEditor::\r
62 workspace( )\r
63 {\r
64   return( this->m_Workspace );\r
65 }\r
66 \r
67 // -------------------------------------------------------------------------\r
68 const PipelineEditor::QNodesEditor::\r
69 TWorkspace* PipelineEditor::QNodesEditor::\r
70 workspace( ) const\r
71 {\r
72   return( this->m_Workspace );\r
73 }\r
74 \r
75 // -------------------------------------------------------------------------\r
76 void PipelineEditor::QNodesEditor::\r
77 setWorkspace( TWorkspace* ws )\r
78 {\r
79   this->m_Workspace = ws;\r
80   this->m_Graph = TGraph::New( );\r
81 \r
82   // Create blocks\r
83   auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( );\r
84   auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( );\r
85   for( ; vIt != vIt_end; ++vIt )\r
86   {\r
87     this->_CreateBlock(\r
88       dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ),\r
89       QPointF( )\r
90       );\r
91 \r
92   } // rof\r
93 \r
94   // Add edges\r
95   auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( );\r
96   auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( );\r
97   for( ; rIt != rIt_end; ++rIt )\r
98   {\r
99     if( !this->m_Graph->HasVertexIndex( rIt->first ) )\r
100       continue;\r
101     QNEBlock* orig = this->m_Graph->GetVertex( rIt->first );\r
102     if( orig == NULL )\r
103       continue;\r
104     QVector< QNEOutputPort* >& oPorts = orig->outputPorts( );\r
105 \r
106     auto cIt = rIt->second.begin( );\r
107     for( ; cIt != rIt->second.end( ); ++cIt )\r
108     {\r
109       if( !this->m_Graph->HasVertexIndex( cIt->first ) )\r
110         continue;\r
111       QNEBlock* dest = this->m_Graph->GetVertex( cIt->first );\r
112       if( dest == NULL )\r
113         continue;\r
114       QVector< QNEInputPort* >& iPorts = dest->inputPorts( );\r
115 \r
116       auto eIt = cIt->second.begin( );\r
117       for( ; eIt != cIt->second.end( ); ++eIt )\r
118       {\r
119         QNEOutputPort* op = NULL;\r
120         auto opIt = oPorts.begin( );\r
121         for( ; opIt != oPorts.end( ) && op == NULL; ++opIt )\r
122           if( ( *opIt )->name( ).toStdString( ) == eIt->first )\r
123             op = *opIt;\r
124 \r
125         QNEInputPort* ip = NULL;\r
126         auto ipIt = iPorts.begin( );\r
127         for( ; ipIt != iPorts.end( ) && ip == NULL; ++ipIt )\r
128           if( ( *ipIt )->name( ).toStdString( ) == eIt->second )\r
129             ip = *ipIt;\r
130 \r
131         if( op == NULL || ip == NULL )\r
132           continue;\r
133 \r
134         QNEConnection* conn = new QNEConnection( 0, this->m_Scene );\r
135         conn->setPort1( op );\r
136         conn->setPort2( ip );\r
137         conn->updatePosFromPorts( );\r
138         conn->updatePath( );\r
139         this->m_Graph->AddConnection( rIt->first, cIt->first, conn );\r
140 \r
141       } // rof\r
142 \r
143     } // rof\r
144 \r
145   } // rof\r
146 }\r
147 \r
148 // -------------------------------------------------------------------------\r
149 std::string PipelineEditor::QNodesEditor::\r
150 createFilter( const std::string& filter, const QPointF& pnt )\r
151 {\r
152   std::string name = filter;\r
153   while( this->m_Workspace->HasFilter( name ) )\r
154     name += std::string( "_" );\r
155   if( this->m_Workspace->CreateFilter( filter, name ) )\r
156   {\r
157     this->_CreateBlock( this->m_Workspace->GetFilter( name ), pnt );\r
158     return( name );\r
159   }\r
160   else\r
161     return( "" );\r
162 }\r
163 \r
164 // -------------------------------------------------------------------------\r
165 void PipelineEditor::QNodesEditor::\r
166 install( QGraphicsScene* s )\r
167 {\r
168   s->installEventFilter( this );\r
169   this->m_Scene = s;\r
170 }\r
171 \r
172 // -------------------------------------------------------------------------\r
173 QGraphicsItem* PipelineEditor::QNodesEditor::\r
174 itemAt( const QPointF& pos )\r
175 {\r
176   QList< QGraphicsItem* > items =\r
177     this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );\r
178 \r
179   foreach( QGraphicsItem* item, items )\r
180     if( item->type( ) > QGraphicsItem::UserType )\r
181       return( item );\r
182   return( NULL );\r
183 }\r
184 \r
185 // -------------------------------------------------------------------------\r
186 void PipelineEditor::QNodesEditor::\r
187 _CreateBlock( TFilter* f, const QPointF& pnt )\r
188 {\r
189   if( f == NULL )\r
190     return;\r
191 \r
192   // Add block\r
193   QNEBlock* b = new QNEBlock( 0, this->m_Scene );\r
194   b->setNamePort( f->GetName( ) );\r
195   b->setTypePort( f->GetClassName( ) );\r
196   // TODO: b->setScenePos( pnt );\r
197 \r
198   // Add input ports\r
199   std::set< std::string > inputs;\r
200   f->GetInputsNames( inputs );\r
201   for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt )\r
202     b->addInputPort( iIt->c_str( ) );\r
203 \r
204   // Add output ports\r
205   std::set< std::string > outputs;\r
206   f->GetOutputsNames( outputs );\r
207   for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt )\r
208     b->addOutputPort( oIt->c_str( ) );\r
209 \r
210   // Keep a trace of this visual graph\r
211   this->m_Graph->SetVertex( f->GetName( ), b );\r
212 }\r
213 \r
214 // -------------------------------------------------------------------------\r
215 void PipelineEditor::QNodesEditor::\r
216 _DoubleClick( QGraphicsSceneMouseEvent* evt, QGraphicsItem* item )\r
217 {\r
218   switch( evt->button( ) )\r
219   {\r
220   case Qt::LeftButton:\r
221   {\r
222     QNEBlock* block = dynamic_cast< QNEBlock* >( item );\r
223     QNEPort* port = dynamic_cast< QNEPort* >( item );\r
224     QNEConnection* conn = dynamic_cast< QNEConnection* >( item );\r
225 \r
226     if( block != NULL )\r
227     {\r
228       /* TODO\r
229          auto ports = block->ports( );\r
230          std::string name = "";\r
231          for(\r
232          auto pIt = ports.begin( );\r
233          pIt != ports.end( ) && name == "";\r
234          ++pIt\r
235          )\r
236          if(\r
237          ( *pIt )->portFlags( ) && QNEPort::NamePort == QNEPort::NamePort\r
238          )\r
239          name = ( *pIt )->portName( ).toStdString( );\r
240          if( name == "" )\r
241          return;\r
242          TFilter* filter = this->m_Workspace->GetFilter( name );\r
243          if( filter != NULL )\r
244          {\r
245          } // fi\r
246       */\r
247     }\r
248     else if( port != NULL )\r
249     {\r
250     }\r
251     else if( conn != NULL )\r
252     {\r
253     } // fi\r
254   }\r
255   break;\r
256   /* TODO:\r
257      case Qt::RightButton:\r
258      {\r
259      }\r
260      break;\r
261      case Qt::MiddleButton:\r
262      {\r
263      }\r
264      break;\r
265   */\r
266   default:\r
267     break;\r
268   } // hctiws\r
269 }\r
270 \r
271 // -------------------------------------------------------------------------\r
272 bool PipelineEditor::QNodesEditor::\r
273 eventFilter( QObject* o, QEvent* e )\r
274 {\r
275   // Event type\r
276   switch( int( e->type( ) ) )\r
277   {\r
278   case QEvent::GraphicsSceneContextMenu:\r
279   {\r
280     QGraphicsSceneContextMenuEvent* evt =\r
281       dynamic_cast< QGraphicsSceneContextMenuEvent* >( e );\r
282     if( evt != NULL )\r
283     {\r
284     } // fi\r
285   }\r
286   break;\r
287   case QEvent::GraphicsSceneDragEnter:\r
288   {\r
289     QGraphicsSceneDragDropEvent* evt =\r
290       dynamic_cast< QGraphicsSceneDragDropEvent* >( e );\r
291     if( evt != NULL )\r
292     {\r
293     } // fi\r
294   }\r
295   break;\r
296   case QEvent::GraphicsSceneDragLeave:\r
297   {\r
298     QGraphicsSceneDragDropEvent* evt =\r
299       dynamic_cast< QGraphicsSceneDragDropEvent* >( e );\r
300     if( evt != NULL )\r
301     {\r
302     } // fi\r
303   }\r
304   break;\r
305   case QEvent::GraphicsSceneDragMove:\r
306   {\r
307     QGraphicsSceneDragDropEvent* evt =\r
308       dynamic_cast< QGraphicsSceneDragDropEvent* >( e );\r
309     if( evt != NULL )\r
310     {\r
311     } // fi\r
312   }\r
313   break;\r
314   case QEvent::GraphicsSceneDrop:\r
315   {\r
316     QGraphicsSceneDragDropEvent* evt =\r
317       dynamic_cast< QGraphicsSceneDragDropEvent* >( e );\r
318     if( evt != NULL )\r
319     {\r
320     } // fi\r
321   }\r
322   break;\r
323   case QEvent::GraphicsSceneHelp:\r
324   {\r
325     QGraphicsSceneHelpEvent* evt =\r
326       dynamic_cast< QGraphicsSceneHelpEvent* >( e );\r
327     if( evt != NULL )\r
328     {\r
329     } // fi\r
330   }\r
331   break;\r
332   case QEvent::GraphicsSceneHoverEnter:\r
333   {\r
334     QGraphicsSceneHoverEvent* evt =\r
335       dynamic_cast< QGraphicsSceneHoverEvent* >( e );\r
336     if( evt != NULL )\r
337     {\r
338     } // fi\r
339   }\r
340   break;\r
341   case QEvent::GraphicsSceneHoverLeave:\r
342   {\r
343     QGraphicsSceneHoverEvent* evt =\r
344       dynamic_cast< QGraphicsSceneHoverEvent* >( e );\r
345     if( evt != NULL )\r
346     {\r
347     } // fi\r
348   }\r
349   break;\r
350   case QEvent::GraphicsSceneHoverMove:\r
351   {\r
352     QGraphicsSceneHoverEvent* evt =\r
353       dynamic_cast< QGraphicsSceneHoverEvent* >( e );\r
354     if( evt != NULL )\r
355     {\r
356     } // fi\r
357   }\r
358   break;\r
359   case QEvent::GraphicsSceneMouseDoubleClick:\r
360   {\r
361     QGraphicsSceneMouseEvent* evt =\r
362       dynamic_cast< QGraphicsSceneMouseEvent* >( e );\r
363     if( evt != NULL )\r
364     {\r
365       QGraphicsItem* item = this->itemAt( evt->scenePos( ) );\r
366       if( item != NULL )\r
367       {\r
368         this->_DoubleClick( evt, item );\r
369         return( true );\r
370 \r
371       } // fi\r
372 \r
373     } // fi\r
374   }\r
375   break;\r
376   case QEvent::GraphicsSceneMouseMove:\r
377   {\r
378     QGraphicsSceneMouseEvent* evt =\r
379       dynamic_cast< QGraphicsSceneMouseEvent* >( e );\r
380     if( evt != NULL )\r
381     {\r
382       if( this->m_Conn )\r
383       {\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     } // fi\r
391   }\r
392   break;\r
393   case QEvent::GraphicsSceneMousePress:\r
394   {\r
395     QGraphicsSceneMouseEvent* evt =\r
396       dynamic_cast< QGraphicsSceneMouseEvent* >( e );\r
397     if( evt != NULL )\r
398     {\r
399       switch( evt->button( ) )\r
400       {\r
401       case Qt::LeftButton:\r
402       {\r
403         QNEOutputPort* port =\r
404           dynamic_cast< QNEOutputPort* >( this->itemAt( evt->scenePos( ) ) );\r
405         if( port != NULL )\r
406         {\r
407           this->m_Conn = new QNEConnection( 0, this->m_Scene );\r
408           this->m_Conn->setPort1( port );\r
409           this->m_Conn->setPos1( port->scenePos( ) );\r
410           this->m_Conn->setPos2( evt->scenePos( ) );\r
411           this->m_Conn->updatePath( );\r
412           return( true );\r
413 \r
414         } // fi\r
415       }\r
416       break;\r
417       default:\r
418         break;\r
419 \r
420       } // hctiws\r
421 \r
422     } // fi\r
423   }\r
424   break;\r
425   case QEvent::GraphicsSceneMouseRelease:\r
426   {\r
427     QGraphicsSceneMouseEvent* evt =\r
428       dynamic_cast< QGraphicsSceneMouseEvent* >( e );\r
429     if( evt != NULL )\r
430     {\r
431       if( this->m_Conn != NULL && evt->button( ) == Qt::LeftButton )\r
432       {\r
433         QNEInputPort* port2 =\r
434           dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );\r
435         if( port2 != NULL )\r
436         {\r
437           QNEOutputPort* port1 =\r
438             dynamic_cast< QNEOutputPort* >( this->m_Conn->port1( ) );\r
439           if( port1 != NULL )\r
440           {\r
441             if(\r
442               port1->block( ) != port2->block( ) &&\r
443               !port2->hasConnection( ) &&\r
444               !port1->isConnected( port2 )\r
445               )\r
446             {\r
447               this->m_Conn->setPos2( port2->scenePos( ) );\r
448               this->m_Conn->setPort2( port2 );\r
449               this->m_Conn->updatePath( );\r
450 \r
451               this->m_Workspace->Connect(\r
452                 port1->block( )->namePort( )->name( ).toStdString( ),\r
453                 port2->block( )->namePort( )->name( ).toStdString( ),\r
454                 port1->name( ).toStdString( ),\r
455                 port2->name( ).toStdString( )\r
456                 );\r
457               this->m_Graph->AddConnection(\r
458                 port1->block( )->namePort( )->name( ).toStdString( ),\r
459                 port2->block( )->namePort( )->name( ).toStdString( ),\r
460                 this->m_Conn\r
461                 );\r
462 \r
463               this->m_Conn = NULL;\r
464               return( true );\r
465 \r
466             } // fi\r
467 \r
468           } // fi\r
469 \r
470         } // fi\r
471         delete this->m_Conn;\r
472         this->m_Conn = NULL;\r
473         return( true );\r
474 \r
475       } // fi\r
476 \r
477     } // fi\r
478   }\r
479   break;\r
480   case QEvent::GraphicsSceneMove:\r
481   {\r
482     QGraphicsSceneMoveEvent* evt =\r
483       dynamic_cast< QGraphicsSceneMoveEvent* >( e );\r
484     if( evt != NULL )\r
485     {\r
486     } // fi\r
487   }\r
488   break;\r
489   case QEvent::GraphicsSceneResize:\r
490   {\r
491     QGraphicsSceneResizeEvent* evt =\r
492       dynamic_cast< QGraphicsSceneResizeEvent* >( e );\r
493     if( evt != NULL )\r
494     {\r
495     } // fi\r
496   }\r
497   break;\r
498   case QEvent::GraphicsSceneWheel:\r
499   {\r
500     QGraphicsSceneWheelEvent* evt =\r
501       dynamic_cast< QGraphicsSceneWheelEvent* >( e );\r
502     if( evt != NULL )\r
503     {\r
504     } // fi\r
505   }\r
506   break;\r
507   default:\r
508     break;\r
509   } // hctiws\r
510 \r
511   // Mouse event\r
512   /*\r
513     QGraphicsSceneMouseEvent* me =\r
514     dynamic_cast< QGraphicsSceneMouseEvent* >( e );\r
515     if( me != NULL )\r
516     {\r
517     } // fi\r
518   */\r
519 \r
520   /* TODO\r
521      switch( ( int ) e->type( ) )\r
522      {\r
523      case QEvent::GraphicsSceneMouseMove:\r
524      {\r
525      if( this->m_Conn )\r
526      {\r
527      this->m_Conn->setPos2( me->scenePos( ) );\r
528      this->m_Conn->updatePath( );\r
529      return( true );\r
530      }\r
531      break;\r
532      }\r
533      case QEvent::GraphicsSceneMouseRelease:\r
534      {\r
535      if( this->m_Conn && me->button( ) == Qt::LeftButton )\r
536      {\r
537      QGraphicsItem* item = itemAt( me->scenePos( ) );\r
538      if( item && item->type( ) == QNEPort::Type )\r
539      {\r
540      QNEPort* port1 = this->m_Conn->port1( );\r
541      QNEPort* port2 = ( QNEPort* ) item;\r
542      if( port1->block( ) != port2->block( ) && port1->isOutput( ) != port2->isOutput( ) && !port1->isConnected( port2 ) )\r
543      {\r
544      this->m_Conn->setPos2( port2->scenePos( ) );\r
545      this->m_Conn->setPort2( port2 );\r
546      this->m_Conn->updatePath( );\r
547      this->m_Conn = NULL;\r
548      return( true );\r
549      }\r
550      }\r
551 \r
552      delete this->m_Conn;\r
553      this->m_Conn = NULL;\r
554      return( true );\r
555      }\r
556      break;\r
557      }\r
558      } // hctiws\r
559   */\r
560 \r
561   return( this->Superclass::eventFilter( o, e ) );\r
562 }\r
563 \r
564 // eof - $RCSfile$\r