]> Creatis software - cpPlugins.git/blob - appli/ImageMPR/ImageMPR.cxx
Interactive filters synchronization debugged
[cpPlugins.git] / appli / ImageMPR / ImageMPR.cxx
1 #include "ImageMPR.h"
2 #include "ui_ImageMPR.h"
3
4 #include <QFileInfo>
5 #include <QMessageBox>
6
7 // -------------------------------------------------------------------------
8 #define ImageMPR_ConnectAction( ACTION )                \
9   QObject::connect(                                     \
10     this->m_UI->a##ACTION, SIGNAL( triggered( ) ),      \
11     this, SLOT( _a##ACTION( ) )                         \
12     )
13
14 // -------------------------------------------------------------------------
15 ImageMPR::
16 ImageMPR( QWidget* parent )
17   : QMainWindow( parent ),
18     m_UI( new Ui::ImageMPR )
19 {
20   this->m_UI->setupUi( this );
21   this->m_Plugins.SetWidget( this );
22   this->m_Plugins.SetApplication( this );
23
24   // Connect actions
25   ImageMPR_ConnectAction( OpenImage );
26   ImageMPR_ConnectAction( OpenDICOMSeries );
27   ImageMPR_ConnectAction( OpenSegmentation );
28   ImageMPR_ConnectAction( OpenPolyData );
29   ImageMPR_ConnectAction( SaveImage );
30   ImageMPR_ConnectAction( SaveSegmentation );
31   ImageMPR_ConnectAction( SavePolyData );
32   ImageMPR_ConnectAction( Undo );
33   ImageMPR_ConnectAction( Redo );
34   ImageMPR_ConnectAction( LoadPlugins );
35   ImageMPR_ConnectAction( ShowPlugins );
36
37   // Associate model with view
38   for( unsigned int i = 0; i < 4; ++i )
39     this->m_Plugins.AddInteractor( this->m_UI->MPR->GetInteractor( i ) );
40
41   // Try to load default plugins
42   QStringList args = QApplication::arguments( );
43   QFileInfo info( args.at( 0 ) );
44   this->m_Plugins.LoadPluginsPath(
45     info.absolutePath( ).toStdString( ), true
46     );
47
48   // Put loaded plugins into menu
49   this->_AssociatePluginsToMenu( );
50 }
51
52 // -------------------------------------------------------------------------
53 ImageMPR::
54 ~ImageMPR( )
55 {
56   delete this->m_UI;
57 }
58
59 // -------------------------------------------------------------------------
60 void ImageMPR::
61 UpdateActualFilter( )
62 {
63   if( !( this->m_Plugins.HasActiveFilter( ) ) )
64     return;
65
66   // Update filter
67   TPlugins::TStringContainer outputs;
68   if(
69     !(
70       this->m_Plugins.UpdateActiveFilter(
71         outputs, this->m_ActiveFilterMainInput
72         )
73       )
74     )
75     return;
76
77   // Show outputs
78   for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt )
79   {
80     std::string parent = this->m_Plugins.GetParent( *oIt );
81     TDataObject* dobj = this->m_Plugins.GetData< TDataObject >( *oIt );
82     if( this->m_UI->MPR->AddData( dobj, *oIt, parent ) )
83       this->m_UI->MPR->ShowData( *oIt );
84
85   } // rof
86 }
87
88 // -------------------------------------------------------------------------
89 void ImageMPR::
90 _AssociatePluginsToMenu( )
91 {
92   this->m_UI->MenuFilters->clear( );
93
94   TPlugins::TStringContainer categories;
95   this->m_Plugins.GetLoadedCategories( categories );
96   for( auto cIt = categories.begin( ); cIt != categories.end( ); ++cIt )
97   {
98     QMenu* category = this->m_UI->MenuFilters->addMenu( cIt->c_str( ) );
99     const TPlugins::TStringContainer& filters =
100       this->m_Plugins.GetLoadedFilters( *cIt );
101     for( auto fIt = filters.begin( ); fIt != filters.end( ); ++fIt )
102     {
103       QAction* filter = category->addAction( fIt->c_str( ) );
104       this->connect(
105         filter, SIGNAL( triggered( ) ),
106         this, SLOT( _execPlugin( ) )
107         );
108
109     } // rof
110
111   } // rof
112 }
113
114 // -------------------------------------------------------------------------
115 #define ImageMPR_ReadImage( F )                                         \
116   this->m_UI->MPR->DeleteAllData( );                                    \
117   this->m_Plugins.ClearDataObjects( );                                  \
118   try                                                                   \
119   {                                                                     \
120     std::string name = this->m_Plugins.Read##F( "" );                   \
121     if( name == "" )                                                    \
122       return;                                                           \
123     TImage* image = this->m_Plugins.GetData< TImage >( name );          \
124     this->m_UI->MPR->AddData( image, name, "" );                        \
125     this->m_UI->MPR->SetMainImage( name );                              \
126     this->m_UI->MPR->ShowData( name );                                  \
127   }                                                                     \
128   catch( std::exception& err )                                          \
129   {                                                                     \
130     QMessageBox::critical(                                              \
131       this,                                                             \
132       QMessageBox::tr( "Error reading image." ),                        \
133       QMessageBox::tr( err.what( ) )                                    \
134       );                                                                \
135   }
136
137 void ImageMPR::_aOpenImage( )       { ImageMPR_ReadImage( Image ) }
138 void ImageMPR::_aOpenDICOMSeries( ) { ImageMPR_ReadImage( DicomSeries ) }
139
140 // -------------------------------------------------------------------------
141 void ImageMPR::
142 _aOpenSegmentation( )
143 {
144   /*
145     if( this->m_ImageLoaded != "" )
146     this->m_ImageLoaded = this->m_UI->MPR->LoadImage( );
147   */
148 }
149
150 // -------------------------------------------------------------------------
151 void ImageMPR::
152 _aOpenPolyData( )
153 {
154 }
155
156 // -------------------------------------------------------------------------
157 void ImageMPR::
158 _aSaveImage( )
159 {
160   /*
161     std::string data_name = this->m_UI->MPR->GetSelectedData( );
162     this->m_Plugins->WriteImage( data_name );
163   */
164 }
165
166 // -------------------------------------------------------------------------
167 void ImageMPR::
168 _aSaveSegmentation( )
169 {
170 }
171
172 // -------------------------------------------------------------------------
173 void ImageMPR::
174 _aSavePolyData( )
175 {
176 }
177
178 // -------------------------------------------------------------------------
179 void ImageMPR::
180 _aUndo( )
181 {
182 }
183
184 // -------------------------------------------------------------------------
185 void ImageMPR::
186 _aRedo( )
187 {
188 }
189
190 // -------------------------------------------------------------------------
191 void ImageMPR::
192 _aLoadPlugins( )
193 {
194   this->m_Plugins.DialogLoadPlugins( );
195   this->_AssociatePluginsToMenu( );
196 }
197
198 // -------------------------------------------------------------------------
199 void ImageMPR::
200 _aShowPlugins( )
201 {
202 }
203
204 // -------------------------------------------------------------------------
205 void ImageMPR::
206 _execPlugin( )
207 {
208   // Get filter's name
209   QAction* action = dynamic_cast< QAction* >( this->sender( ) );
210   if( action == NULL )
211     return;
212   std::string filter_name = action->text( ).toStdString( );
213
214   // Activate filter
215   if( !( this->m_Plugins.ActivateFilter( filter_name ) ) )
216     return;
217
218   // Get IO names
219   TPlugins::TStringContainer inputs;
220   this->m_Plugins.GetActiveFilterInputsNames( inputs );
221
222   // Configure inputs
223   if( inputs.size( ) > 1 )
224   {
225     // TODO
226   }
227   else if( inputs.size( ) == 1 )
228   {
229     this->m_ActiveFilterMainInput = this->m_UI->MPR->GetSelectedData( );
230     this->m_Plugins.ConnectInputInActiveFilter(
231       this->m_ActiveFilterMainInput, *( inputs.begin( ) )
232       );
233
234   } // fi
235
236   // Configure paramereters
237   auto dlg_res = this->m_Plugins.ConfigureActiveFilter( );
238   if( dlg_res == TPlugins::TProcessObject::DialogResult_Cancel )
239   {
240     // Just deactivate filter, since it was canceled
241     this->m_Plugins.DeactivateFilter( );
242     return;
243   }
244   else if( dlg_res == TPlugins::TProcessObject::DialogResult_NoModal )
245   {
246     // Execute automatic filter and associate outputs
247     this->UpdateActualFilter( );
248     this->m_Plugins.DeactivateFilter( );
249
250   } // fi
251 }
252
253 // -------------------------------------------------------------------------
254 /* TODO
255    void ImageMPR::
256    _CursorCommand( double* pos, int axis, void* data )
257    {
258    Self* app = reinterpret_cast< Self* >( data );
259    if( app == NULL )
260    return;
261    if( !( app->m_Flooding ) )
262    return;
263
264    cpPlugins::Interface::ProcessObject::Pointer filter =
265    app->m_UI->MPR->CreateFilter(
266    "cpPlugins::BasicFilters::FloodFillImageFilter"
267    );
268    if( filter.IsNull( ) )
269    return;
270
271    cpPlugins::Interface::Parameters* params = filter->GetParameters( );
272    params->SetPoint( "Seed", 3, pos );
273    params->SetReal( "Window", app->m_UI->MPR->GetWindow( ) );
274    params->SetReal( "Level", app->m_UI->MPR->GetLevel( ) );
275    params->SetUint( "InsideValue", 1 );
276    params->SetUint( "OutsideValue", 0 );
277    filter->SetInput( "Input", app->m_UI->MPR->GetImage( app->m_ImageLoaded ) );
278    app->m_UI->MPR->Block( );
279    std::string err = filter->Update( );
280    cpPlugins::Interface::BaseMPRWindow::TImage::Pointer image = filter->GetOutput< cpPlugins::Interface::BaseMPRWindow::TImage >( "Output" );
281    filter->DisconnectOutputs( );
282    app->m_UI->MPR->AddImage( "Segmentation", image );
283    app->m_UI->MPR->Unblock( );
284
285    std::cout
286    << "CursorCommand ==> "
287    << pos[ 0 ] << " "
288    << pos[ 1 ] << " "
289    << pos[ 2 ] << " : "
290    << axis << " "
291    << data << std::endl;
292    }
293 */
294
295 /*
296 #include "MementoState.h"
297
298 #include <vtkProperty.h>
299 #include <vtkRenderWindow.h>
300 #include <vtkMetaImageReader.h>
301
302 #include <QFileDialog>
303 #include <QMessageBox>
304
305 #ifdef _WIN32
306 #  define PLUGIN_PREFIX ""
307 #  define PLUGIN_EXT "dll"
308 #  define PLUGIN_REGEX "Plugins file (*.dll);;All files (*)"
309 #else
310 #  define PLUGIN_PREFIX "lib"
311 #  define PLUGIN_EXT "so"
312 #  define PLUGIN_REGEX "Plugins file (*.so);;All files (*)"
313 #endif // _WIN32
314
315 // -------------------------------------------------------------------------
316 ImageMPR::ImageMPR( QWidget* parent )
317   : QMainWindow( parent ),
318     m_UI( new Ui::ImageMPR ),
319     m_ImageReaderClass( "" ),
320     m_ImageWriterClass( "" ),
321     m_MeshReaderClass( "" ),
322     m_MeshWriterClass( "" ),
323     m_MeshCutterClass( "" ),
324     m_Image( NULL ),
325         m_state(0),
326         m_max_state(0)
327 {
328   this->m_UI->setupUi( this );
329
330   // Create and associate renderers
331   this->m_MPRObjects = vtkSmartPointer< TMPRObjects >::New( );
332   this->m_MPRObjects->SetRenderWindows(
333     this->m_UI->m_XPlaneVTK->GetRenderWindow( ),
334     this->m_UI->m_YPlaneVTK->GetRenderWindow( ),
335     this->m_UI->m_ZPlaneVTK->GetRenderWindow( ),
336     this->m_UI->m_3DVTK->GetRenderWindow( )
337     );
338
339   // signals <-> slots
340   QObject::connect(
341     this->m_UI->actionOpenPlugins, SIGNAL( triggered( ) ),
342     this, SLOT( _triggered_actionOpenPlugins( ) )
343     );
344   QObject::connect(
345     this->m_UI->actionOpenInputImage, SIGNAL( triggered( ) ),
346     this, SLOT( _triggered_actionOpenInputImage( ) )
347     );
348   QObject::connect(
349     this->m_UI->actionOpenSegmentation, SIGNAL( triggered( ) ),
350     this, SLOT( _triggered_actionOpenSegmentation( ) )
351     );
352   QObject::connect(
353     this->m_UI->actionOpenInputPolyData, SIGNAL( triggered( ) ),
354     this, SLOT( _triggered_actionOpenInputPolyData( ) )
355     );
356   QObject::connect(
357         this->m_UI->actionUndo, SIGNAL(triggered()),
358         this, SLOT(_triggered_actionUndo())
359         );
360   QObject::connect(
361         this->m_UI->actionRedo, SIGNAL(triggered()),
362         this, SLOT(_triggered_actionRedo())
363         );
364
365   // Start: load all disponible plugins
366   this->_LoadPlugins(
367     std::string( PLUGIN_PREFIX ) +
368     std::string( "cpPluginsIO." ) +
369     std::string( PLUGIN_EXT )
370     );
371   this->_LoadPlugins(
372     std::string( PLUGIN_PREFIX ) +
373     std::string( "cpPluginsBasicFilters." ) +
374     std::string( PLUGIN_EXT )
375     );
376 }
377
378 // -------------------------------------------------------------------------
379 ImageMPR::
380 ~ImageMPR( )
381 {
382   // Close all connections
383   this->m_Plugins.UnloadAll( );
384
385   // Delete objects
386   delete this->m_UI;
387 }
388
389 // -------------------------------------------------------------------------
390 bool ImageMPR::
391 _LoadPlugins( const std::string& filename )
392 {
393   QApplication::setOverrideCursor( Qt::WaitCursor );
394   this->setEnabled( false );
395
396   this->m_ImageReaderClass = "";
397   this->m_ImageWriterClass = "";
398   this->m_MeshReaderClass = "";
399   this->m_MeshWriterClass = "";
400   this->m_MeshCutterClass = "";
401   this->m_UI->MenuImageToImage->clear( );
402   this->m_UI->MenuImageToMesh->clear( );
403
404   if( !( this->m_Plugins.Load( filename ) ) )
405     return( false );
406
407   typedef TPluginsInterface::TClasses _TClasses;
408   _TClasses::const_iterator cIt = this->m_Plugins.GetClasses( ).begin( );
409   for( ; cIt != this->m_Plugins.GetClasses( ).end( ); ++cIt )
410   {
411     TPluginFilter::Pointer o =
412       this->m_Plugins.CreateProcessObject( cIt->first );
413     std::string name = o->GetClassName( );
414     std::string category = o->GetClassCategory( );
415     if( category == "ImageReader" )
416       this->m_ImageReaderClass = name;
417     else if( category == "ImageWriter" )
418       this->m_ImageWriterClass = name;
419     else if( category == "MeshReader" )
420       this->m_MeshReaderClass = name;
421     else if( category == "MeshWriter" )
422       this->m_MeshWriterClass = name;
423     else if( category == "MeshToMeshFilter" )
424     {
425       if( name.find_last_of( "Cutter" ) != std::string::npos )
426         this->m_MeshCutterClass = name;
427     }
428     else if( category == "ImageToImageFilter" )
429     {
430       QAction* action =
431         this->m_UI->MenuImageToImage->addAction( QString( name.c_str( ) ) );
432       QObject::connect(
433         action, SIGNAL( triggered( ) ),
434         this, SLOT( _triggered_actionImageToImage( ) )
435         );
436     }
437     else if( category == "ImageToMeshFilter" )
438     {
439       QAction* action =
440         this->m_UI->MenuImageToMesh->addAction( QString( name.c_str( ) ) );
441       QObject::connect(
442         action, SIGNAL( triggered( ) ),
443         this, SLOT( _triggered_actionImageToMesh( ) )
444         );
445
446     } // fi
447
448   } // rof
449   QApplication::restoreOverrideCursor( );
450   this->setEnabled( true );
451
452   return( true );
453 }
454
455 // -------------------------------------------------------------------------
456 std::string ImageMPR::
457 _LoadImage( TPluginImage::Pointer& image )
458 {
459   std::string ret = "";
460   image = NULL;
461
462   // Get a reader from loaded plugins
463   TPluginFilter::Pointer reader =
464     this->m_Plugins.CreateProcessObject( this->m_ImageReaderClass );
465   if( reader.IsNotNull( ) )
466   {
467     if( reader->ExecConfigurationDialog( this ) )
468     {
469       // Block application
470       QApplication::setOverrideCursor( Qt::WaitCursor );
471       this->setEnabled( false );
472
473       // Execute and get error message, if any
474       ret = reader->Update( );
475
476       // Assign fresh image, if any
477       if( ret == "" )
478       {
479         image = reader->GetOutput< TPluginImage >( 0 );
480         reader->DisconnectOutputs( );
481
482       } // fi
483
484       // Unblock application
485       QApplication::restoreOverrideCursor( );
486       this->setEnabled( true );
487
488     } // fi
489   }
490   else
491     ret = "No suitable reader object found in loaded plugins.";
492   
493   return( ret );
494 }
495
496 // -------------------------------------------------------------------------
497 std::string ImageMPR::
498 _ConfigureMeshActors( )
499 {
500   if( this->m_Mesh.IsNull( ) )
501     return( "Valid mesh not found." );
502
503   this->m_Mesh->CreateVTKActor( );
504   vtkActor* vtk_actor = this->m_Mesh->GetVTKActor( );
505   if( vtk_actor != NULL )
506   {
507     this->m_MPRObjects->Get3DRenderer( )->AddActor( vtk_actor );
508     this->m_MPRObjects->Render( 4 );
509
510   } // fi
511
512   TMPRObjects::TMPRActors* mprActors = this->m_MPRObjects->GetMPRActors( );
513
514   std::string err = "";
515   for( unsigned int i = 0; i < 3; ++i )
516   {
517     this->m_Cutters[ i ] = this->m_Plugins.CreateProcessObject( this->m_MeshCutterClass );
518     this->m_Planes[ i ] = TPluginImplicitFunction::New( );
519     this->m_Planes[ i ]->SetFunction( mprActors->GetSliceActors( i )->GetPlaneFunction( ) );
520     this->m_Cutters[ i ]->SetInput( 0, this->m_Mesh );
521     this->m_Cutters[ i ]->SetInput( 1, this->m_Planes[ i ] );
522     std::string lerr = this->m_Cutters[ i ]->Update( );
523     if( lerr == "" )
524     {
525       this->m_Cutters[ i ]->GetOutput< TPluginMesh >( 0 )->CreateVTKActor( );
526       vtkActor* actor = this->m_Cutters[ i ]->GetOutput< TPluginMesh >( 0 )->GetVTKActor( );
527       mprActors->GetSliceActors( i )->AddActor( this->m_Cutters[ i ]->GetVTK< vtkAlgorithm >( ), actor );
528       if( i == 0 )
529         this->m_MPRObjects->GetXRenderer( )->AddActor( actor );
530       else if( i == 1 )
531         this->m_MPRObjects->GetYRenderer( )->AddActor( actor );
532       else if( i == 2 )
533         this->m_MPRObjects->GetZRenderer( )->AddActor( actor );
534
535     } // fi
536     err += lerr;
537
538   } // rof
539   this->m_MPRObjects->RenderAll( );
540   return( err );
541 }
542
543 // -------------------------------------------------------------------------
544 void ImageMPR::
545 _triggered_actionOpenPlugins( )
546 {
547   // Show dialog and check if it was accepted
548   QFileDialog dialog( this );
549   dialog.setFileMode( QFileDialog::ExistingFile );
550   dialog.setDirectory( "." );
551   dialog.setNameFilter( tr( PLUGIN_REGEX ) );
552   dialog.setDefaultSuffix( tr( PLUGIN_EXT ) );
553   if( !( dialog.exec( ) ) )
554     return;
555   
556   std::string fname = dialog.selectedFiles( ).at( 0 ).toStdString( );
557   if( !( _LoadPlugins( fname ) ) )
558     QMessageBox::critical(
559       this,
560       tr( "Ignoring plugin" ),
561       tr( fname.c_str( ) )
562       );
563 }
564
565 // -------------------------------------------------------------------------
566 void ImageMPR::
567 _triggered_actionOpenInputImage( )
568 {
569   // Read image
570   std::string err = this->_LoadImage( this->m_Image );
571   if( err == "" )
572   {
573     vtkImageData* vtk_id = this->m_Image->GetVTK< vtkImageData >( );
574     if( vtk_id != NULL )
575     {
576       this->m_MPRObjects->SetImage( vtk_id );
577       this->m_MPRObjects->ActivateInteractors( );
578       this->m_MPRObjects->ResetCameras( );
579       this->m_MPRObjects->RenderAll( );
580
581           MementoState(m_state, this->m_Image);  
582           this->m_state++;
583     }
584     else
585       QMessageBox::critical(
586         this,
587         tr( "Error message" ),
588         tr( "Read image does not have a valid VTK converter." )
589         );
590   }
591   else
592     QMessageBox::critical(
593       this,
594       tr( "Error reading single image" ),
595       tr( err.c_str( ) )
596       );
597 }
598
599 // -------------------------------------------------------------------------
600 void ImageMPR::
601 _triggered_actionOpenSegmentation( )
602 {
603   if( this->m_Image.IsNull( ) )
604   {
605     QMessageBox::critical(
606       this,
607       tr( "Error message" ),
608       tr( "Before reading a segmentation, first load a raw image." )
609       );
610     return;
611
612   } // fi
613
614   // Read image
615   std::string err = this->_LoadImage( this->m_Segmentation );
616   if( err == "" )
617   {
618     vtkImageData* vtk_id = this->m_Segmentation->GetVTK< vtkImageData >( );
619     if( vtk_id != NULL )
620     {
621       this->m_MPRObjects->AddAuxiliaryImage( vtk_id );
622       this->m_MPRObjects->RenderAll( );
623     }
624     else
625       QMessageBox::critical(
626         this,
627         tr( "Error message" ),
628         tr( "Read image does not have a valid VTK converter." )
629         );
630   }
631   else
632     QMessageBox::critical(
633       this,
634       tr( "Error reading single image" ),
635       tr( err.c_str( ) )
636       );
637 }
638
639 // -------------------------------------------------------------------------
640 void ImageMPR::
641 _triggered_actionOpenInputPolyData( )
642 {
643   this->m_Mesh = NULL;
644
645   // Get a reader from plugins
646   TPluginFilter::Pointer reader =
647     this->m_Plugins.CreateProcessObject( this->m_MeshReaderClass );
648
649   if( reader.IsNotNull( ) )
650   {
651     // Configure reader
652     if( reader->ExecConfigurationDialog( this ) )
653     {
654       // Execute and get error message, if any
655       QApplication::setOverrideCursor( Qt::WaitCursor );
656       this->setEnabled( false );
657       std::string err = reader->Update( );
658       QApplication::restoreOverrideCursor( );
659       this->setEnabled( true );
660
661       // Assign fresh mesh, if any
662       if( err == "" )
663       {
664         this->m_Mesh = reader->GetOutput< TPluginMesh >( 0 );
665         reader->DisconnectOutputs( );
666         err = this->_ConfigureMeshActors( );
667         if( err != "" )
668           QMessageBox::critical(
669             this,
670             tr( "Error message" ),
671             tr( err.c_str( ) )
672             );
673       }
674       else
675         QMessageBox::critical(
676           this,
677           tr( "Error reading mesh" ),
678           tr( err.c_str( ) )
679           );
680
681     } // fi
682   }
683   else
684     QMessageBox::critical(
685       this,
686       tr( "Error reading single mesh" ),
687       tr( "No suitable mesh reader found in loaded plugins." )
688       );
689 }
690
691 // -------------------------------------------------------------------------
692 void ImageMPR::
693 _triggered_actionImageToImage( )
694 {
695   if( this->m_Image.IsNull( ) )
696     return;
697
698   // Get filter name
699   QAction* action = dynamic_cast< QAction* >( this->sender( ) );
700   if( action == NULL )
701     return;
702   std::string name = action->text( ).toStdString( );
703
704   // Configure filter
705   TPluginFilter::Pointer filter =
706     this->m_Plugins.CreateProcessObject( name );
707   bool dlg_ok = filter->ExecConfigurationDialog( NULL );
708   if( !dlg_ok )
709     return;
710
711   // Execute filter
712   QApplication::setOverrideCursor( Qt::WaitCursor );
713   this->setEnabled( false );
714   filter->SetInput( 0, this->m_Image );
715   std::string err = filter->Update( );
716   QApplication::restoreOverrideCursor( );
717   this->setEnabled( true );
718
719   // Update image
720   if( err == "" )
721   {
722     TPluginImage* result = filter->GetOutput< TPluginImage >( 0 );
723     result->DisconnectPipeline( );
724     this->m_Image = result;
725     if( this->m_Image.IsNotNull( ) )
726       this->m_MPRObjects->SetImage(
727         this->m_Image->GetVTK< vtkImageData >( )
728
729                 );
730         
731         
732         MementoState(this->m_state, this->m_Image);
733         this->m_state++;
734         if (this->m_state > this->m_max_state)
735         {
736                 this->m_max_state = this->m_state;
737         }
738   }
739   else
740     QMessageBox::critical(
741       this,
742       tr( "Error executing filter" ),
743       tr( err.c_str( ) )
744       );
745 }
746
747 // -------------------------------------------------------------------------
748 void ImageMPR::
749 _triggered_actionImageToMesh( )
750 {
751   if( this->m_Image.IsNull( ) )
752     return;
753
754   // Get filter name
755   QAction* action = dynamic_cast< QAction* >( this->sender( ) );
756   if( action == NULL )
757     return;
758   std::string name = action->text( ).toStdString( );
759
760   // Configure filter
761   TPluginFilter::Pointer filter =
762     this->m_Plugins.CreateProcessObject( name );
763   bool dlg_ok = filter->ExecConfigurationDialog( NULL );
764   if( !dlg_ok )
765     return;
766
767   // Execute filter
768   QApplication::setOverrideCursor( Qt::WaitCursor );
769   this->setEnabled( false );
770   filter->SetInput( 0, this->m_Image );
771   std::string err = filter->Update( );
772   QApplication::restoreOverrideCursor( );
773   this->setEnabled( true );
774
775   // Update image
776   if( err == "" )
777   {
778     TPluginMesh* result = filter->GetOutput< TPluginMesh >( 0 );
779     result->DisconnectPipeline( );
780     this->m_Mesh = result;
781     err = this->_ConfigureMeshActors( );
782     if( err != "" )
783       QMessageBox::critical(
784         this,
785         tr( "Error message" ),
786         tr( err.c_str( ) )
787         );
788   }
789   else
790     QMessageBox::critical(
791       this,
792       tr( "Error executing filter" ),
793       tr( err.c_str( ) )
794       );
795 }
796
797 // -------------------------------------------------------------------------
798 void ImageMPR::
799 _triggered_actionUndo()
800 {
801         MementoState memento = MementoState();
802     
803         if (this->m_state>1)
804         {
805                 this->m_state--;
806                 this->m_MPRObjects->SetImage(
807                         memento.getMemento(this->m_state)->GetOutput()
808                         );
809         } else
810         {
811                 QMessageBox::warning(
812                         this,
813                         tr("message"),
814                         tr("No history to undo")
815                         );
816         }
817
818 }
819
820 // -------------------------------------------------------------------------
821 void ImageMPR::
822 _triggered_actionRedo()
823 {
824         MementoState memento = MementoState();
825                 if (this->m_state + 1 <= m_max_state)
826                 {
827                         this->m_state++;
828                         this->m_MPRObjects->SetImage(
829                                 memento.getMemento(this->m_state)->GetOutput()
830                                 );
831                 } else
832                 {
833                         QMessageBox::warning(
834                                 this,
835                                 tr("message"),
836                                 tr("No history to redo")
837                                 );
838                 }
839         
840 }
841         
842 */
843
844 // eof - $RCSfile$