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