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