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