]> Creatis software - cpPlugins.git/blob - lib/cpBaseQtApplication/Editor.cxx
35b8a61ceb7f52dac45909f0d22d0c26057a51c7
[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->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 cpBaseQtApplication::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 cpBaseQtApplication::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 cpBaseQtApplication::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 cpBaseQtApplication::Editor::\r
169 clear( )\r
170 {\r
171   std::cout << "Editor::clear" << std::endl;\r
172 }\r
173 \r
174 // -------------------------------------------------------------------------\r
175 void cpBaseQtApplication::Editor::\r
176 install( QGraphicsScene* s )\r
177 {\r
178   s->installEventFilter( this );\r
179   this->m_Scene = s;\r
180 }\r
181 \r
182 // -------------------------------------------------------------------------\r
183 QGraphicsItem* cpBaseQtApplication::Editor::\r
184 itemAt( const QPointF& pos )\r
185 {\r
186   QList< QGraphicsItem* > items =\r
187     this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );\r
188 \r
189   foreach( QGraphicsItem* item, items )\r
190     if( item->type( ) > QGraphicsItem::UserType )\r
191       return( item );\r
192   return( NULL );\r
193 }\r
194 \r
195 // -------------------------------------------------------------------------\r
196 cpBaseQtApplication::Block* cpBaseQtApplication::Editor::\r
197 _createBlock( TFilter* f, const QString& name, const QPointF& pnt )\r
198 {\r
199   if( f == NULL )\r
200     return( NULL );\r
201 \r
202   // Add block\r
203   Block* b = new Block( f, name, 0, this->m_Scene );\r
204   b->setEditor( this );\r
205   b->setPos( pnt );\r
206 \r
207   // Mark exposed inputs\r
208   auto& e_in = this->m_Workspace->GetExposedInputPorts( );\r
209   auto f_in = f->GetInputsNames( );\r
210   for( auto iIt = f_in.begin( ); iIt != f_in.end( ); ++iIt )\r
211   {\r
212     auto eIt = e_in.begin( );\r
213     auto fIt = e_in.end( );\r
214     for( ; eIt != e_in.end( ) && fIt == e_in.end( ); ++eIt )\r
215       if( eIt->second.second == *iIt )\r
216         fIt = eIt;\r
217     if( fIt == e_in.end( ) )\r
218       continue;\r
219 \r
220     auto port = b->inputPort( iIt->c_str( ) );\r
221     port->setExtendedName( fIt->first.c_str( ) );\r
222     port->setExtend( true );\r
223 \r
224   } // rof\r
225 \r
226   // Mark exposed outputs\r
227   auto& e_out = this->m_Workspace->GetExposedOutputPorts( );\r
228   auto f_out = f->GetOutputsNames( );\r
229   for( auto iIt = f_out.begin( ); iIt != f_out.end( ); ++iIt )\r
230   {\r
231     auto eIt = e_out.begin( );\r
232     auto fIt = e_out.end( );\r
233     for( ; eIt != e_out.end( ) && fIt == e_out.end( ); ++eIt )\r
234       if( eIt->second.second == *iIt )\r
235         fIt = eIt;\r
236     if( fIt == e_out.end( ) )\r
237       continue;\r
238 \r
239     auto port = b->outputPort( iIt->c_str( ) );\r
240     port->setExtendedName( fIt->first.c_str( ) );\r
241     port->setExtend( true );\r
242 \r
243   } // rof\r
244 \r
245   return( b );\r
246 }\r
247 \r
248 // -------------------------------------------------------------------------\r
249 bool cpBaseQtApplication::Editor::\r
250 eventFilter( QObject* o, QEvent* e )\r
251 {\r
252   // Event type\r
253   switch( int( e->type( ) ) )\r
254   {\r
255     cpBaseQtApplication_Editor_Callback_SWITCH( ContextMenu, e );\r
256     cpBaseQtApplication_Editor_Callback_SWITCH( DragEnter, e );\r
257     cpBaseQtApplication_Editor_Callback_SWITCH( DragLeave, e );\r
258     cpBaseQtApplication_Editor_Callback_SWITCH( DragMove, e );\r
259     cpBaseQtApplication_Editor_Callback_SWITCH( Drop, e );\r
260     cpBaseQtApplication_Editor_Callback_SWITCH( Help, e );\r
261     cpBaseQtApplication_Editor_Callback_SWITCH( HoverEnter, e );\r
262     cpBaseQtApplication_Editor_Callback_SWITCH( HoverLeave, e );\r
263     cpBaseQtApplication_Editor_Callback_SWITCH( HoverMove, e );\r
264     cpBaseQtApplication_Editor_Callback_SWITCH( MouseDoubleClick, e );\r
265     cpBaseQtApplication_Editor_Callback_SWITCH( MouseMove, e );\r
266     cpBaseQtApplication_Editor_Callback_SWITCH( MousePress, e );\r
267     cpBaseQtApplication_Editor_Callback_SWITCH( MouseRelease, e );\r
268     cpBaseQtApplication_Editor_Callback_SWITCH( Move, e );\r
269     cpBaseQtApplication_Editor_Callback_SWITCH( Resize, e );\r
270     cpBaseQtApplication_Editor_Callback_SWITCH( Wheel, e );\r
271   default:\r
272     break;\r
273   } // hctiws\r
274   return( this->Superclass::eventFilter( o, e ) );\r
275 }\r
276 \r
277 // -------------------------------------------------------------------------\r
278 void cpBaseQtApplication::Editor::\r
279 updateFilter( const std::string& filter_name )\r
280 {\r
281   emit execFilter( filter_name );\r
282 }\r
283 \r
284 // -------------------------------------------------------------------------\r
285 void cpBaseQtApplication::Editor::\r
286 showOutputData(\r
287   const std::string& filter_name, const std::string& output_name\r
288   )\r
289 {\r
290   emit showFilterOutput( filter_name, output_name );\r
291 }\r
292 \r
293 // -------------------------------------------------------------------------\r
294 void cpBaseQtApplication::Editor::\r
295 hideOutputData(\r
296   const std::string& filter_name, const std::string& output_name\r
297   )\r
298 {\r
299   emit hideFilterOutput( filter_name, output_name );\r
300 }\r
301 \r
302 // -------------------------------------------------------------------------\r
303 void cpBaseQtApplication::Editor::\r
304 visualPropertiesOutputData(\r
305   const std::string& filter_name, const std::string& output_name\r
306   )\r
307 {\r
308   emit visualPropertiesFilterOutput( filter_name, output_name );\r
309 }\r
310 \r
311 // -------------------------------------------------------------------------\r
312 cpBaseQtApplication_Editor_Callback_CODE( ContextMenu )\r
313 {\r
314 }\r
315 \r
316 // -------------------------------------------------------------------------\r
317 cpBaseQtApplication_Editor_Callback_CODE( DragEnter )\r
318 {\r
319 }\r
320 \r
321 // -------------------------------------------------------------------------\r
322 cpBaseQtApplication_Editor_Callback_CODE( DragLeave )\r
323 {\r
324 }\r
325 \r
326 // -------------------------------------------------------------------------\r
327 cpBaseQtApplication_Editor_Callback_CODE( DragMove )\r
328 {\r
329 }\r
330 \r
331 // -------------------------------------------------------------------------\r
332 cpBaseQtApplication_Editor_Callback_CODE( Drop )\r
333 {\r
334 }\r
335 \r
336 // -------------------------------------------------------------------------\r
337 cpBaseQtApplication_Editor_Callback_CODE( Help )\r
338 {\r
339 }\r
340 \r
341 // -------------------------------------------------------------------------\r
342 cpBaseQtApplication_Editor_Callback_CODE( HoverEnter )\r
343 {\r
344 }\r
345 \r
346 // -------------------------------------------------------------------------\r
347 cpBaseQtApplication_Editor_Callback_CODE( HoverLeave )\r
348 {\r
349 }\r
350 \r
351 // -------------------------------------------------------------------------\r
352 cpBaseQtApplication_Editor_Callback_CODE( HoverMove )\r
353 {\r
354 }\r
355 \r
356 // -------------------------------------------------------------------------\r
357 cpBaseQtApplication_Editor_Callback_CODE( MouseDoubleClick )\r
358 {\r
359   QGraphicsItem* item = this->itemAt( evt->scenePos( ) );\r
360   if( item == NULL )\r
361     return;\r
362 \r
363   switch( evt->button( ) )\r
364   {\r
365   case Qt::LeftButton:\r
366   {\r
367     Block* block = dynamic_cast< Block* >( item );\r
368     Port* port = dynamic_cast< Port* >( item );\r
369     Connection* conn = dynamic_cast< Connection* >( item );\r
370 \r
371     if( block != NULL )\r
372     {\r
373       QString old_name = block->namePort( );\r
374       bool ok;\r
375       QString new_name =\r
376         QInputDialog::getText(\r
377           dynamic_cast< QWidget* >( this->parent( ) ),\r
378           "Change filter name",\r
379           "Filter name:",\r
380           QLineEdit::Normal,\r
381           old_name,\r
382           &ok\r
383           );\r
384       if( ok && !new_name.isEmpty( ) && old_name != new_name )\r
385       {\r
386         ok = this->m_Graph->RenameVertex(\r
387           old_name.toStdString( ),\r
388           new_name.toStdString( )\r
389           );\r
390         block->setNamePort( new_name );\r
391         this->m_Workspace->RenameFilter(\r
392           old_name.toStdString( ),\r
393           new_name.toStdString( )\r
394           );\r
395 \r
396       } // fi\r
397     }\r
398     else if( port != NULL )\r
399     {\r
400       if( evt->modifiers( ) == Qt::ControlModifier )\r
401       {\r
402         port->setExtend( !( port->isExtended( ) ) );\r
403         InputPort* in_port = dynamic_cast< InputPort* >( port );\r
404         OutputPort* out_port = dynamic_cast< OutputPort* >( port );\r
405         if( port->isExtended( ) )\r
406         {\r
407           if( in_port != NULL )\r
408           {\r
409             this->m_Workspace->ExposeInputPort(\r
410               in_port->extendedName( ).toStdString( ),\r
411               in_port->block( )->namePort( ).toStdString( ),\r
412               in_port->name( ).toStdString( )\r
413               );\r
414           }\r
415           else if( out_port != NULL )\r
416           {\r
417             this->m_Workspace->ExposeOutputPort(\r
418               out_port->extendedName( ).toStdString( ),\r
419               out_port->block( )->namePort( ).toStdString( ),\r
420               out_port->name( ).toStdString( )\r
421               );\r
422 \r
423           } // fi\r
424         }\r
425         else\r
426         {\r
427           if( in_port != NULL )\r
428             this->m_Workspace->HideInputPort(\r
429               in_port->extendedName( ).toStdString( )\r
430               );\r
431           else if( out_port != NULL )\r
432             this->m_Workspace->HideOutputPort(\r
433               out_port->extendedName( ).toStdString( )\r
434               );\r
435 \r
436         } // fi\r
437         this->m_Scene->update( );\r
438       }\r
439       else if( evt->modifiers( ) == Qt::NoModifier )\r
440       {\r
441         if( port->isExtended( ) )\r
442         {\r
443           QString old_name = port->extendedName( );\r
444           bool ok;\r
445           QString new_name =\r
446             QInputDialog::getText(\r
447               dynamic_cast< QWidget* >( this->parent( ) ),\r
448               "Change filter name",\r
449               "Filter name:",\r
450               QLineEdit::Normal,\r
451               old_name,\r
452               &ok\r
453               );\r
454           if( ok && !new_name.isEmpty( ) && old_name != new_name )\r
455           {\r
456             port->setExtendedName( new_name );\r
457             InputPort* in_port = dynamic_cast< InputPort* >( port );\r
458             OutputPort* out_port = dynamic_cast< OutputPort* >( port );\r
459             if( in_port != NULL )\r
460               this->m_Workspace->\r
461                 RenameExposedInputPort(\r
462                   old_name.toStdString( ),\r
463                   new_name.toStdString( )\r
464                   );\r
465             else if( out_port != NULL )\r
466               this->m_Workspace->\r
467                 RenameExposedOutputPort(\r
468                   old_name.toStdString( ),\r
469                   new_name.toStdString( )\r
470                   );\r
471             this->m_Scene->update( );\r
472 \r
473           } // fi\r
474 \r
475         } // fi\r
476 \r
477       } // fi\r
478     }\r
479     else if( conn != NULL )\r
480     {\r
481     } // fi\r
482   }\r
483   break;\r
484   /* TODO:\r
485      case Qt::RightButton:\r
486      {\r
487      }\r
488      break;\r
489      case Qt::MiddleButton:\r
490      {\r
491      }\r
492      break;\r
493   */\r
494   default:\r
495     break;\r
496   } // hctiws\r
497 }\r
498 \r
499 // -------------------------------------------------------------------------\r
500 cpBaseQtApplication_Editor_Callback_CODE( MouseMove )\r
501 {\r
502   if( this->m_ActualConnection != NULL )\r
503   {\r
504     if( this->m_ActualConnection->port1( ) == NULL )\r
505       this->m_ActualConnection->setPos1( evt->scenePos( ) );\r
506     else if( this->m_ActualConnection->port2( ) == NULL )\r
507       this->m_ActualConnection->setPos2( evt->scenePos( ) );\r
508     this->m_ActualConnection->updatePath( );\r
509 \r
510   } // fi\r
511 }\r
512 \r
513 // -------------------------------------------------------------------------\r
514 cpBaseQtApplication_Editor_Callback_CODE( MousePress )\r
515 {\r
516   InputPort* in_port =\r
517     dynamic_cast< InputPort* >( this->itemAt( evt->scenePos( ) ) );\r
518   OutputPort* out_port =\r
519     dynamic_cast< OutputPort* >( this->itemAt( evt->scenePos( ) ) );\r
520   if( in_port == NULL && out_port == NULL )\r
521     return;\r
522 \r
523   switch( evt->button( ) )\r
524   {\r
525   case Qt::LeftButton:\r
526   {\r
527     if( out_port != NULL )\r
528     {\r
529       if( out_port->block( ) != NULL )\r
530       {\r
531         // Start new connection\r
532         this->m_ActualConnection = new Connection( 0, this->m_Scene );\r
533         this->m_ActualConnection->setPort1( out_port );\r
534         this->m_ActualConnection->setPos1( out_port->scenePos( ) );\r
535         this->m_ActualConnection->setPos2( evt->scenePos( ) );\r
536         this->m_ActualConnection->updatePosFromPorts( );\r
537         this->m_ActualConnection->updatePath( );\r
538 \r
539       } // fi\r
540 \r
541     } // fi\r
542   }\r
543   break;\r
544   default:\r
545     break;\r
546 \r
547   } // hctiws\r
548 }\r
549 \r
550 // -------------------------------------------------------------------------\r
551 cpBaseQtApplication_Editor_Callback_CODE( MouseRelease )\r
552 {\r
553   if( this->m_ActualConnection == NULL )\r
554     return;\r
555 \r
556   switch( evt->button( ) )\r
557   {\r
558   case Qt::LeftButton:\r
559   {\r
560     InputPort* port2 =\r
561       dynamic_cast< InputPort* >( this->itemAt( evt->scenePos( ) ) );\r
562     if( port2 != NULL )\r
563     {\r
564       OutputPort* port1 =\r
565         dynamic_cast< OutputPort* >( this->m_ActualConnection->port1( ) );\r
566       if( port1 != NULL )\r
567       {\r
568         if(\r
569           port1->block( ) != port2->block( ) &&\r
570           !port2->hasConnection( ) &&\r
571           !port1->isConnected( port2 ) &&\r
572           !port2->isExtended( )\r
573           )\r
574         {\r
575           this->m_ActualConnection->setPos2( port2->scenePos( ) );\r
576           this->m_ActualConnection->setPort2( port2 );\r
577           this->m_ActualConnection->updatePosFromPorts( );\r
578           this->m_ActualConnection->updatePath( );\r
579 \r
580           this->m_Workspace->Connect(\r
581             port1->block( )->namePort( ).toStdString( ),\r
582             port2->block( )->namePort( ).toStdString( ),\r
583             port1->name( ).toStdString( ),\r
584             port2->name( ).toStdString( )\r
585             );\r
586           this->m_Graph->AddEdge(\r
587             port1->block( )->namePort( ).toStdString( ),\r
588             port2->block( )->namePort( ).toStdString( ),\r
589             this->m_ActualConnection\r
590             );\r
591         }\r
592         else\r
593           delete this->m_ActualConnection;\r
594       }\r
595       else\r
596         delete this->m_ActualConnection;\r
597     }\r
598     else\r
599       delete this->m_ActualConnection;\r
600     this->m_ActualConnection = NULL;\r
601   }\r
602   break;\r
603   default:\r
604     break;\r
605   } // hctisw\r
606 }\r
607 \r
608 // -------------------------------------------------------------------------\r
609 cpBaseQtApplication_Editor_Callback_CODE( Move )\r
610 {\r
611 }\r
612 \r
613 // -------------------------------------------------------------------------\r
614 cpBaseQtApplication_Editor_Callback_CODE( Resize )\r
615 {\r
616 }\r
617 \r
618 // -------------------------------------------------------------------------\r
619 cpBaseQtApplication_Editor_Callback_CODE( Wheel )\r
620 {\r
621 }\r
622 \r
623 // eof - $RCSfile$\r