]> Creatis software - cpPlugins.git/blob - lib/cpBaseQtApplication/Editor.cxx
f379f6416d0672e10bce9a12e49fc5b51f69eeb1
[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   QGraphicsItem* item = this->itemAt( evt->scenePos( ) );\r
373   if( item == NULL )\r
374     return;\r
375 \r
376   switch( evt->button( ) )\r
377   {\r
378   case Qt::LeftButton:\r
379   {\r
380     Block* block = dynamic_cast< Block* >( item );\r
381     Port* port = dynamic_cast< Port* >( item );\r
382     Connection* conn = dynamic_cast< Connection* >( item );\r
383 \r
384     if( block != NULL )\r
385     {\r
386       QString old_name = block->namePort( );\r
387       bool ok;\r
388       QString new_name =\r
389         QInputDialog::getText(\r
390           dynamic_cast< QWidget* >( this->parent( ) ),\r
391           "Change filter name",\r
392           "Filter name:",\r
393           QLineEdit::Normal,\r
394           old_name,\r
395           &ok\r
396           );\r
397       if( ok && !new_name.isEmpty( ) && old_name != new_name )\r
398       {\r
399         block->setNamePort( new_name );\r
400         this->m_Workspace->RenameFilter(\r
401           old_name.toStdString( ),\r
402           new_name.toStdString( )\r
403           );\r
404 \r
405       } // fi\r
406     }\r
407     else if( port != NULL )\r
408     {\r
409       if( evt->modifiers( ) == Qt::ControlModifier )\r
410       {\r
411         port->setExtend( !( port->isExtended( ) ) );\r
412         InputPort* in_port = dynamic_cast< InputPort* >( port );\r
413         OutputPort* out_port = dynamic_cast< OutputPort* >( port );\r
414         if( port->isExtended( ) )\r
415         {\r
416           if( in_port != NULL )\r
417           {\r
418             this->m_Workspace->ExposeInputPort(\r
419               in_port->extendedName( ).toStdString( ),\r
420               in_port->block( )->namePort( ).toStdString( ),\r
421               in_port->name( ).toStdString( )\r
422               );\r
423           }\r
424           else if( out_port != NULL )\r
425           {\r
426             this->m_Workspace->ExposeOutputPort(\r
427               out_port->extendedName( ).toStdString( ),\r
428               out_port->block( )->namePort( ).toStdString( ),\r
429               out_port->name( ).toStdString( )\r
430               );\r
431 \r
432           } // fi\r
433         }\r
434         else\r
435         {\r
436           if( in_port != NULL )\r
437             this->m_Workspace->HideInputPort(\r
438               in_port->extendedName( ).toStdString( )\r
439               );\r
440           else if( out_port != NULL )\r
441             this->m_Workspace->HideOutputPort(\r
442               out_port->extendedName( ).toStdString( )\r
443               );\r
444 \r
445         } // fi\r
446         this->m_Scene->update( );\r
447       }\r
448       else if( evt->modifiers( ) == Qt::NoModifier )\r
449       {\r
450         if( port->isExtended( ) )\r
451         {\r
452           QString old_name = port->extendedName( );\r
453           bool ok;\r
454           QString new_name =\r
455             QInputDialog::getText(\r
456               dynamic_cast< QWidget* >( this->parent( ) ),\r
457               "Change filter name",\r
458               "Filter name:",\r
459               QLineEdit::Normal,\r
460               old_name,\r
461               &ok\r
462               );\r
463           if( ok && !new_name.isEmpty( ) && old_name != new_name )\r
464           {\r
465             port->setExtendedName( new_name );\r
466             InputPort* in_port = dynamic_cast< InputPort* >( port );\r
467             OutputPort* out_port = dynamic_cast< OutputPort* >( port );\r
468             if( in_port != NULL )\r
469               this->m_Workspace->\r
470                 RenameExposedInputPort(\r
471                   old_name.toStdString( ),\r
472                   new_name.toStdString( )\r
473                   );\r
474             else if( out_port != NULL )\r
475               this->m_Workspace->\r
476                 RenameExposedOutputPort(\r
477                   old_name.toStdString( ),\r
478                   new_name.toStdString( )\r
479                   );\r
480             this->m_Scene->update( );\r
481 \r
482           } // fi\r
483 \r
484         } // fi\r
485 \r
486       } // fi\r
487     }\r
488     else if( conn != NULL )\r
489     {\r
490     } // fi\r
491   }\r
492   break;\r
493   case Qt::RightButton:\r
494   {\r
495   }\r
496   break;\r
497   case Qt::MiddleButton:\r
498   {\r
499   }\r
500   break;\r
501   default:\r
502     break;\r
503   } // hctiws\r
504 }\r
505 \r
506 // -------------------------------------------------------------------------\r
507 cpBaseQtApplication_Editor_Callback_CODE( MouseMove )\r
508 {\r
509   if( this->m_ActualConnection != NULL )\r
510   {\r
511     if( this->m_ActualConnection->port1( ) == NULL )\r
512       this->m_ActualConnection->setPos1( evt->scenePos( ) );\r
513     else if( this->m_ActualConnection->port2( ) == NULL )\r
514       this->m_ActualConnection->setPos2( evt->scenePos( ) );\r
515     this->m_ActualConnection->updatePath( );\r
516 \r
517   } // fi\r
518 }\r
519 \r
520 // -------------------------------------------------------------------------\r
521 cpBaseQtApplication_Editor_Callback_CODE( MousePress )\r
522 {\r
523   InputPort* in_port =\r
524     dynamic_cast< InputPort* >( this->itemAt( evt->scenePos( ) ) );\r
525   OutputPort* out_port =\r
526     dynamic_cast< OutputPort* >( this->itemAt( evt->scenePos( ) ) );\r
527   if( in_port == NULL && out_port == NULL )\r
528     return;\r
529 \r
530   switch( evt->button( ) )\r
531   {\r
532   case Qt::LeftButton:\r
533   {\r
534     if( out_port != NULL )\r
535     {\r
536       if( out_port->block( ) != NULL )\r
537       {\r
538         // Start new connection\r
539         this->m_ActualConnection = new Connection( 0, this->m_Scene );\r
540         this->m_ActualConnection->setPort1( out_port );\r
541         this->m_ActualConnection->setPos1( out_port->scenePos( ) );\r
542         this->m_ActualConnection->setPos2( evt->scenePos( ) );\r
543         this->m_ActualConnection->updatePosFromPorts( );\r
544         this->m_ActualConnection->updatePath( );\r
545 \r
546       } // fi\r
547 \r
548     } // fi\r
549   }\r
550   break;\r
551   default:\r
552     break;\r
553 \r
554   } // hctiws\r
555 }\r
556 \r
557 // -------------------------------------------------------------------------\r
558 cpBaseQtApplication_Editor_Callback_CODE( MouseRelease )\r
559 {\r
560   if( this->m_ActualConnection == NULL )\r
561     return;\r
562 \r
563   switch( evt->button( ) )\r
564   {\r
565   case Qt::LeftButton:\r
566   {\r
567     InputPort* port2 =\r
568       dynamic_cast< InputPort* >( this->itemAt( evt->scenePos( ) ) );\r
569     if( port2 != NULL )\r
570     {\r
571       OutputPort* port1 =\r
572         dynamic_cast< OutputPort* >( this->m_ActualConnection->port1( ) );\r
573       if( port1 != NULL )\r
574       {\r
575         if(\r
576           port1->block( ) != port2->block( ) &&\r
577           !port2->hasConnection( ) &&\r
578           !port1->isConnected( port2 ) &&\r
579           !port2->isExtended( )\r
580           )\r
581         {\r
582           this->m_ActualConnection->setPos2( port2->scenePos( ) );\r
583           this->m_ActualConnection->setPort2( port2 );\r
584           this->m_ActualConnection->updatePosFromPorts( );\r
585           this->m_ActualConnection->updatePath( );\r
586 \r
587           this->m_Workspace->Connect(\r
588             port1->block( )->namePort( ).toStdString( ),\r
589             port2->block( )->namePort( ).toStdString( ),\r
590             port1->name( ).toStdString( ),\r
591             port2->name( ).toStdString( )\r
592             );\r
593         }\r
594         else\r
595           delete this->m_ActualConnection;\r
596       }\r
597       else\r
598         delete this->m_ActualConnection;\r
599     }\r
600     else\r
601       delete this->m_ActualConnection;\r
602     this->m_ActualConnection = NULL;\r
603   }\r
604   break;\r
605   default:\r
606     break;\r
607   } // hctisw\r
608 }\r
609 \r
610 // -------------------------------------------------------------------------\r
611 cpBaseQtApplication_Editor_Callback_CODE( Move )\r
612 {\r
613 }\r
614 \r
615 // -------------------------------------------------------------------------\r
616 cpBaseQtApplication_Editor_Callback_CODE( Resize )\r
617 {\r
618 }\r
619 \r
620 // -------------------------------------------------------------------------\r
621 cpBaseQtApplication_Editor_Callback_CODE( Wheel )\r
622 {\r
623 }\r
624 \r
625 // eof - $RCSfile$\r