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