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