]> Creatis software - cpPlugins.git/blob - lib/cpPipelineEditor/Editor.cxx
289ee46431d2e8e51dc0e5f51eb64a658396cd67
[cpPlugins.git] / lib / cpPipelineEditor / Editor.cxx
1 #include "Editor.h"\r
2 \r
3 #include <QGraphicsScene>\r
4 #include <QEvent>\r
5 #include <QGraphicsSceneContextMenuEvent>\r
6 #include <QGraphicsSceneDragDropEvent>\r
7 #include <QGraphicsSceneHelpEvent>\r
8 #include <QGraphicsSceneHoverEvent>\r
9 #include <QGraphicsSceneMouseEvent>\r
10 #include <QGraphicsSceneMoveEvent>\r
11 #include <QGraphicsSceneResizeEvent>\r
12 #include <QGraphicsSceneWheelEvent>\r
13 #include <QInputDialog>\r
14 #include <QMessageBox>\r
15 \r
16 #include "Port.h"\r
17 #include "Connection.h"\r
18 #include "Block.h"\r
19 \r
20 // -------------------------------------------------------------------------\r
21 #define cpPipelineEditor_Editor_Callback_SWITCH( E, e )                 \\r
22   case QEvent::GraphicsScene##E:                                        \\r
23   {                                                                     \\r
24     QGraphicsScene##E##Event* evt =                                     \\r
25       dynamic_cast< QGraphicsScene##E##Event* >( e );                   \\r
26     if( evt != NULL )                                                   \\r
27       this->_##E##_cbk( evt );                                          \\r
28   }                                                                     \\r
29   break;\r
30 \r
31 // -------------------------------------------------------------------------\r
32 #define cpPipelineEditor_Editor_Callback_CODE( E )                      \\r
33   void cpPipelineEditor::Editor::_##E##_cbk( QGraphicsScene##E##Event* evt )\r
34 \r
35 // -------------------------------------------------------------------------\r
36 cpPipelineEditor::Editor::\r
37 Editor( QObject* parent )\r
38   : Superclass( parent ),\r
39     m_ActualConnection( NULL ),\r
40     m_Workspace( NULL )\r
41 {\r
42 }\r
43 \r
44 // -------------------------------------------------------------------------\r
45 cpPipelineEditor::Editor::\r
46 ~Editor( )\r
47 {\r
48 }\r
49 \r
50 // -------------------------------------------------------------------------\r
51 cpPipelineEditor::Editor::\r
52 TWorkspace* cpPipelineEditor::Editor::\r
53 workspace( )\r
54 {\r
55   return( this->m_Workspace );\r
56 }\r
57 \r
58 // -------------------------------------------------------------------------\r
59 const cpPipelineEditor::Editor::\r
60 TWorkspace* cpPipelineEditor::Editor::\r
61 workspace( ) const\r
62 {\r
63   return( this->m_Workspace );\r
64 }\r
65 \r
66 // -------------------------------------------------------------------------\r
67 void cpPipelineEditor::Editor::\r
68 setWorkspace( TWorkspace* ws )\r
69 {\r
70   this->m_Workspace = ws;\r
71   this->m_Graph = TGraph::New( );\r
72 \r
73   // Create blocks\r
74   auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( );\r
75   auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( );\r
76   for( ; vIt != vIt_end; ++vIt )\r
77   {\r
78     auto b = this->_createBlock(\r
79       dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ),\r
80       vIt->first.c_str( ),\r
81       QPointF( vIt->second->GetViewX( ), vIt->second->GetViewY( ) )\r
82       );\r
83     if( b != NULL )\r
84       this->m_Graph->SetVertex( vIt->first, b );\r
85 \r
86   } // rof\r
87 \r
88   // Add edges\r
89   auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( );\r
90   auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( );\r
91   for( ; rIt != rIt_end; ++rIt )\r
92   {\r
93     Block* orig = this->m_Graph->GetVertex( rIt->first );\r
94     auto cIt = rIt->second.begin( );\r
95     for( ; cIt != rIt->second.end( ); ++cIt )\r
96     {\r
97       Block* dest = this->m_Graph->GetVertex( cIt->first );\r
98       auto eIt = cIt->second.begin( );\r
99       for( ; eIt != cIt->second.end( ); ++eIt )\r
100       {\r
101         OutputPort* op = orig->outputPort( eIt->first.c_str( ) );\r
102         InputPort* ip = dest->inputPort( eIt->second.c_str( ) );\r
103         if( op == NULL || ip == NULL )\r
104           continue;\r
105 \r
106         Connection* c = new Connection( 0, this->m_Scene );\r
107         c->setPort1( op );\r
108         c->setPort2( ip );\r
109         c->updatePosFromPorts( );\r
110         c->updatePath( );\r
111         this->m_Graph->AddEdge( rIt->first, cIt->first, c );\r
112 \r
113       } // rof\r
114 \r
115     } // rof\r
116 \r
117   } // rof\r
118 }\r
119 \r
120 // -------------------------------------------------------------------------\r
121 std::string cpPipelineEditor::Editor::\r
122 createFilter(\r
123   const std::string& category,\r
124   const std::string& filter,\r
125   const QPointF& pnt\r
126   )\r
127 {\r
128   std::string name = filter;\r
129   while( this->m_Workspace->HasFilter( name ) )\r
130     name += std::string( "_" );\r
131   if( this->m_Workspace->CreateFilter( category, filter, name ) )\r
132   {\r
133     auto b = this->_createBlock(\r
134       this->m_Workspace->GetFilter( name ),\r
135       name.c_str( ),\r
136       pnt\r
137       );\r
138     return( name );\r
139   }\r
140   else\r
141     return( "" );\r
142 }\r
143 \r
144 // -------------------------------------------------------------------------\r
145 bool cpPipelineEditor::Editor::\r
146 deleteFilter( const std::string& name )\r
147 {\r
148   std::cout << name << std::endl;\r
149   return( false );\r
150 }\r
151 \r
152 // -------------------------------------------------------------------------\r
153 bool cpPipelineEditor::Editor::\r
154 deleteConnection(\r
155   const std::string& src, const std::string& des,\r
156   const std::string& in, const std::string& out\r
157   )\r
158 {\r
159   std::cout\r
160     << src << " "\r
161     << des << " "\r
162     << in << " "\r
163     << out << std::endl;\r
164   return( false );\r
165 }\r
166 \r
167 // -------------------------------------------------------------------------\r
168 void cpPipelineEditor::Editor::\r
169 install( QGraphicsScene* s )\r
170 {\r
171   s->installEventFilter( this );\r
172   this->m_Scene = s;\r
173 }\r
174 \r
175 // -------------------------------------------------------------------------\r
176 QGraphicsItem* cpPipelineEditor::Editor::\r
177 itemAt( const QPointF& pos )\r
178 {\r
179   QList< QGraphicsItem* > items =\r
180     this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );\r
181 \r
182   foreach( QGraphicsItem* item, items )\r
183     if( item->type( ) > QGraphicsItem::UserType )\r
184       return( item );\r
185   return( NULL );\r
186 }\r
187 \r
188 // -------------------------------------------------------------------------\r
189 cpPipelineEditor::Block* cpPipelineEditor::Editor::\r
190 _createBlock( TFilter* f, const QString& name, const QPointF& pnt )\r
191 {\r
192   if( f == NULL )\r
193     return( NULL );\r
194 \r
195   // Add block\r
196   Block* b = new Block( f, name, 0, this->m_Scene );\r
197   b->setEditor( this );\r
198   b->setPos( pnt );\r
199 \r
200   // Mark exposed inputs\r
201   auto& e_in = this->m_Workspace->GetExposedInputPorts( );\r
202   auto f_in = f->GetInputsNames( );\r
203   for( auto iIt = f_in.begin( ); iIt != f_in.end( ); ++iIt )\r
204   {\r
205     auto eIt = e_in.begin( );\r
206     auto fIt = e_in.end( );\r
207     for( ; eIt != e_in.end( ) && fIt == e_in.end( ); ++eIt )\r
208       if( eIt->second.second == *iIt )\r
209         fIt = eIt;\r
210     if( fIt == e_in.end( ) )\r
211       continue;\r
212     \r
213     auto port = b->inputPort( iIt->c_str( ) );\r
214     port->setExtendedName( fIt->first.c_str( ) );\r
215     port->setExtend( true );\r
216 \r
217   } // rof\r
218 \r
219   // Mark exposed outputs\r
220   auto& e_out = this->m_Workspace->GetExposedOutputPorts( );\r
221   auto f_out = f->GetOutputsNames( );\r
222   for( auto iIt = f_out.begin( ); iIt != f_out.end( ); ++iIt )\r
223   {\r
224     auto eIt = e_out.begin( );\r
225     auto fIt = e_out.end( );\r
226     for( ; eIt != e_out.end( ) && fIt == e_out.end( ); ++eIt )\r
227       if( eIt->second.second == *iIt )\r
228         fIt = eIt;\r
229     if( fIt == e_out.end( ) )\r
230       continue;\r
231     \r
232     auto port = b->outputPort( iIt->c_str( ) );\r
233     port->setExtendedName( fIt->first.c_str( ) );\r
234     port->setExtend( true );\r
235 \r
236   } // rof\r
237 \r
238   return( b );\r
239 }\r
240 \r
241 // -------------------------------------------------------------------------\r
242 bool cpPipelineEditor::Editor::\r
243 eventFilter( QObject* o, QEvent* e )\r
244 {\r
245   // Event type\r
246   switch( int( e->type( ) ) )\r
247   {\r
248     cpPipelineEditor_Editor_Callback_SWITCH( ContextMenu, e );\r
249     cpPipelineEditor_Editor_Callback_SWITCH( DragEnter, e );\r
250     cpPipelineEditor_Editor_Callback_SWITCH( DragLeave, e );\r
251     cpPipelineEditor_Editor_Callback_SWITCH( DragMove, e );\r
252     cpPipelineEditor_Editor_Callback_SWITCH( Drop, e );\r
253     cpPipelineEditor_Editor_Callback_SWITCH( Help, e );\r
254     cpPipelineEditor_Editor_Callback_SWITCH( HoverEnter, e );\r
255     cpPipelineEditor_Editor_Callback_SWITCH( HoverLeave, e );\r
256     cpPipelineEditor_Editor_Callback_SWITCH( HoverMove, e );\r
257     cpPipelineEditor_Editor_Callback_SWITCH( MouseDoubleClick, e );\r
258     cpPipelineEditor_Editor_Callback_SWITCH( MouseMove, e );\r
259     cpPipelineEditor_Editor_Callback_SWITCH( MousePress, e );\r
260     cpPipelineEditor_Editor_Callback_SWITCH( MouseRelease, e );\r
261     cpPipelineEditor_Editor_Callback_SWITCH( Move, e );\r
262     cpPipelineEditor_Editor_Callback_SWITCH( Resize, e );\r
263     cpPipelineEditor_Editor_Callback_SWITCH( Wheel, e );\r
264   default:\r
265     break;\r
266   } // hctiws\r
267   return( this->Superclass::eventFilter( o, e ) );\r
268 }\r
269 \r
270 // -------------------------------------------------------------------------\r
271 void cpPipelineEditor::Editor::\r
272 updateFilter( const std::string& filter_name )\r
273 {\r
274   emit execFilter( filter_name );\r
275 }\r
276 \r
277 // -------------------------------------------------------------------------\r
278 void cpPipelineEditor::Editor::\r
279 showOutputData(\r
280   const std::string& filter_name, const std::string& output_name\r
281   )\r
282 {\r
283   emit showFilterOutput( filter_name, output_name );\r
284 }\r
285 \r
286 // -------------------------------------------------------------------------\r
287 void cpPipelineEditor::Editor::\r
288 hideOutputData(\r
289   const std::string& filter_name, const std::string& output_name\r
290   )\r
291 {\r
292   emit hideFilterOutput( filter_name, output_name );\r
293 }\r
294 \r
295 // -------------------------------------------------------------------------\r
296 void cpPipelineEditor::Editor::\r
297 visualPropertiesOutputData(\r
298   const std::string& filter_name, const std::string& output_name\r
299   )\r
300 {\r
301   emit visualPropertiesFilterOutput( filter_name, output_name );\r
302 }\r
303 \r
304 // -------------------------------------------------------------------------\r
305 cpPipelineEditor_Editor_Callback_CODE( ContextMenu )\r
306 {\r
307 }\r
308 \r
309 // -------------------------------------------------------------------------\r
310 cpPipelineEditor_Editor_Callback_CODE( DragEnter )\r
311 {\r
312 }\r
313 \r
314 // -------------------------------------------------------------------------\r
315 cpPipelineEditor_Editor_Callback_CODE( DragLeave )\r
316 {\r
317 }\r
318 \r
319 // -------------------------------------------------------------------------\r
320 cpPipelineEditor_Editor_Callback_CODE( DragMove )\r
321 {\r
322 }\r
323 \r
324 // -------------------------------------------------------------------------\r
325 cpPipelineEditor_Editor_Callback_CODE( Drop )\r
326 {\r
327 }\r
328 \r
329 // -------------------------------------------------------------------------\r
330 cpPipelineEditor_Editor_Callback_CODE( Help )\r
331 {\r
332 }\r
333 \r
334 // -------------------------------------------------------------------------\r
335 cpPipelineEditor_Editor_Callback_CODE( HoverEnter )\r
336 {\r
337 }\r
338 \r
339 // -------------------------------------------------------------------------\r
340 cpPipelineEditor_Editor_Callback_CODE( HoverLeave )\r
341 {\r
342 }\r
343 \r
344 // -------------------------------------------------------------------------\r
345 cpPipelineEditor_Editor_Callback_CODE( HoverMove )\r
346 {\r
347 }\r
348 \r
349 // -------------------------------------------------------------------------\r
350 cpPipelineEditor_Editor_Callback_CODE( MouseDoubleClick )\r
351 {\r
352   QGraphicsItem* item = this->itemAt( evt->scenePos( ) );\r
353   if( item == NULL )\r
354     return;\r
355 \r
356   switch( evt->button( ) )\r
357   {\r
358   case Qt::LeftButton:\r
359   {\r
360     Block* block = dynamic_cast< Block* >( item );\r
361     Port* port = dynamic_cast< Port* >( item );\r
362     Connection* conn = dynamic_cast< Connection* >( item );\r
363 \r
364     if( block != NULL )\r
365     {\r
366       QString old_name = block->namePort( );\r
367       bool ok;\r
368       QString new_name =\r
369         QInputDialog::getText(\r
370           dynamic_cast< QWidget* >( this->parent( ) ),\r
371           "Change filter name",\r
372           "Filter name:",\r
373           QLineEdit::Normal,\r
374           old_name,\r
375           &ok\r
376           );\r
377       if( ok && !new_name.isEmpty( ) && old_name != new_name )\r
378       {\r
379         ok = this->m_Graph->RenameVertex(\r
380           old_name.toStdString( ),\r
381           new_name.toStdString( )\r
382           );\r
383         block->setNamePort( new_name );\r
384         this->m_Workspace->RenameFilter(\r
385           old_name.toStdString( ),\r
386           new_name.toStdString( )\r
387           );\r
388 \r
389       } // fi\r
390     }\r
391     else if( port != NULL )\r
392     {\r
393       if( evt->modifiers( ) == Qt::ControlModifier )\r
394       {\r
395         port->setExtend( !( port->isExtended( ) ) );\r
396         InputPort* in_port = dynamic_cast< InputPort* >( port );\r
397         OutputPort* out_port = dynamic_cast< OutputPort* >( port );\r
398         if( port->isExtended( ) )\r
399         {\r
400           if( in_port != NULL )\r
401           {\r
402             this->m_Workspace->ExposeInputPort(\r
403               in_port->extendedName( ).toStdString( ),\r
404               in_port->block( )->namePort( ).toStdString( ),\r
405               in_port->name( ).toStdString( )\r
406               );\r
407           }\r
408           else if( out_port != NULL )\r
409           {\r
410             this->m_Workspace->ExposeOutputPort(\r
411               out_port->extendedName( ).toStdString( ),\r
412               out_port->block( )->namePort( ).toStdString( ),\r
413               out_port->name( ).toStdString( )\r
414               );\r
415 \r
416           } // fi\r
417         }\r
418         else\r
419         {\r
420           if( in_port != NULL )\r
421             this->m_Workspace->HideInputPort(\r
422               in_port->extendedName( ).toStdString( )\r
423               );\r
424           else if( out_port != NULL )\r
425             this->m_Workspace->HideOutputPort(\r
426               out_port->extendedName( ).toStdString( )\r
427               );\r
428 \r
429         } // fi\r
430         this->m_Scene->update( );\r
431       }\r
432       else if( evt->modifiers( ) == Qt::NoModifier )\r
433       {\r
434         if( port->isExtended( ) )\r
435         {\r
436           QString old_name = port->extendedName( );\r
437           bool ok;\r
438           QString new_name =\r
439             QInputDialog::getText(\r
440               dynamic_cast< QWidget* >( this->parent( ) ),\r
441               "Change filter name",\r
442               "Filter name:",\r
443               QLineEdit::Normal,\r
444               old_name,\r
445               &ok\r
446               );\r
447           if( ok && !new_name.isEmpty( ) && old_name != new_name )\r
448           {\r
449             port->setExtendedName( new_name );\r
450             InputPort* in_port = dynamic_cast< InputPort* >( port );\r
451             OutputPort* out_port = dynamic_cast< OutputPort* >( port );\r
452             if( in_port != NULL )\r
453               this->m_Workspace->\r
454                 RenameExposedInputPort(\r
455                   old_name.toStdString( ),\r
456                   new_name.toStdString( )\r
457                   );\r
458             else if( out_port != NULL )\r
459               this->m_Workspace->\r
460                 RenameExposedOutputPort(\r
461                   old_name.toStdString( ),\r
462                   new_name.toStdString( )\r
463                   );\r
464             this->m_Scene->update( );\r
465 \r
466           } // fi\r
467 \r
468         } // fi\r
469 \r
470       } // fi\r
471     }\r
472     else if( conn != NULL )\r
473     {\r
474     } // fi\r
475   }\r
476   break;\r
477   /* TODO:\r
478      case Qt::RightButton:\r
479      {\r
480      }\r
481      break;\r
482      case Qt::MiddleButton:\r
483      {\r
484      }\r
485      break;\r
486   */\r
487   default:\r
488     break;\r
489   } // hctiws\r
490 }\r
491 \r
492 // -------------------------------------------------------------------------\r
493 cpPipelineEditor_Editor_Callback_CODE( MouseMove )\r
494 {\r
495   if( this->m_ActualConnection != NULL )\r
496   {\r
497     if( this->m_ActualConnection->port1( ) == NULL )\r
498       this->m_ActualConnection->setPos1( evt->scenePos( ) );\r
499     else if( this->m_ActualConnection->port2( ) == NULL )\r
500       this->m_ActualConnection->setPos2( evt->scenePos( ) );\r
501     this->m_ActualConnection->updatePath( );\r
502 \r
503   } // fi\r
504 }\r
505 \r
506 // -------------------------------------------------------------------------\r
507 cpPipelineEditor_Editor_Callback_CODE( MousePress )\r
508 {\r
509   InputPort* in_port =\r
510     dynamic_cast< InputPort* >( this->itemAt( evt->scenePos( ) ) );\r
511   OutputPort* out_port =\r
512     dynamic_cast< OutputPort* >( this->itemAt( evt->scenePos( ) ) );\r
513   if( in_port == NULL && out_port == NULL )\r
514     return;\r
515 \r
516   switch( evt->button( ) )\r
517   {\r
518   case Qt::LeftButton:\r
519   {\r
520     if( out_port != NULL )\r
521     {\r
522       if( out_port->block( ) != NULL )\r
523       {\r
524         // Start new connection\r
525         this->m_ActualConnection = new Connection( 0, this->m_Scene );\r
526         this->m_ActualConnection->setPort1( out_port );\r
527         this->m_ActualConnection->setPos1( out_port->scenePos( ) );\r
528         this->m_ActualConnection->setPos2( evt->scenePos( ) );\r
529         this->m_ActualConnection->updatePosFromPorts( );\r
530         this->m_ActualConnection->updatePath( );\r
531 \r
532       } // fi\r
533 \r
534     } // fi\r
535   }\r
536   break;\r
537   default:\r
538     break;\r
539 \r
540   } // hctiws\r
541 }\r
542 \r
543 // -------------------------------------------------------------------------\r
544 cpPipelineEditor_Editor_Callback_CODE( MouseRelease )\r
545 {\r
546   if( this->m_ActualConnection == NULL )\r
547     return;\r
548 \r
549   switch( evt->button( ) )\r
550   {\r
551   case Qt::LeftButton:\r
552   {\r
553     InputPort* port2 =\r
554       dynamic_cast< InputPort* >( this->itemAt( evt->scenePos( ) ) );\r
555     if( port2 != NULL )\r
556     {\r
557       OutputPort* port1 =\r
558         dynamic_cast< OutputPort* >( this->m_ActualConnection->port1( ) );\r
559       if( port1 != NULL )\r
560       {\r
561         if(\r
562           port1->block( ) != port2->block( ) &&\r
563           !port2->hasConnection( ) &&\r
564           !port1->isConnected( port2 ) &&\r
565           !port2->isExtended( )\r
566           )\r
567         {\r
568           this->m_ActualConnection->setPos2( port2->scenePos( ) );\r
569           this->m_ActualConnection->setPort2( port2 );\r
570           this->m_ActualConnection->updatePosFromPorts( );\r
571           this->m_ActualConnection->updatePath( );\r
572 \r
573           this->m_Workspace->Connect(\r
574             port1->block( )->namePort( ).toStdString( ),\r
575             port2->block( )->namePort( ).toStdString( ),\r
576             port1->name( ).toStdString( ),\r
577             port2->name( ).toStdString( )\r
578             );\r
579           this->m_Graph->AddEdge(\r
580             port1->block( )->namePort( ).toStdString( ),\r
581             port2->block( )->namePort( ).toStdString( ),\r
582             this->m_ActualConnection\r
583             );\r
584         }\r
585         else\r
586           delete this->m_ActualConnection;\r
587       }\r
588       else\r
589         delete this->m_ActualConnection;\r
590     }\r
591     else\r
592       delete this->m_ActualConnection;\r
593     this->m_ActualConnection = NULL;\r
594   }\r
595   break;\r
596   default:\r
597     break;\r
598   } // hctisw\r
599 }\r
600 \r
601 // -------------------------------------------------------------------------\r
602 cpPipelineEditor_Editor_Callback_CODE( Move )\r
603 {\r
604 }\r
605 \r
606 // -------------------------------------------------------------------------\r
607 cpPipelineEditor_Editor_Callback_CODE( Resize )\r
608 {\r
609 }\r
610 \r
611 // -------------------------------------------------------------------------\r
612 cpPipelineEditor_Editor_Callback_CODE( Wheel )\r
613 {\r
614 }\r
615 \r
616 // eof - $RCSfile$\r