Salome HOME
Join modifications from branch OCC_debug_for_3_2_0b1
[modules/gui.git] / src / SalomeApp / SalomeApp_Study.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
2 // 
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either 
6 // version 2.1 of the License.
7 // 
8 // This library is distributed in the hope that it will be useful 
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public  
14 // License along with this library; if not, write to the Free Software 
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/
18 //
19 #include "SalomeApp_Study.h"
20
21 #include "SalomeApp_Module.h"
22 #include "SalomeApp_DataModel.h"
23 #include "SalomeApp_DataObject.h"
24 #include "SalomeApp_Application.h"
25 #include "SalomeApp_Engine_i.hxx"
26 #include "SalomeApp_VisualState.h"
27
28 #include "LightApp_RootObject.h"
29
30 #include <OB_Browser.h>
31
32 #include <SUIT_ResourceMgr.h>
33
34 #include <qptrlist.h>
35 #include <qapplication.h>
36 #include <qdict.h>
37
38 #include "utilities.h"
39 #include <iostream.h>
40 #include <string>
41 #include <vector>
42
43 #include <SUIT_Session.h>
44
45 #include "SALOMEDS_Tool.hxx"
46
47 #include "SALOMEDSClient_ClientFactory.hxx"
48 #include "SALOMEDSClient_IParameters.hxx"
49
50 #include <SALOMEconfig.h>
51 #include CORBA_SERVER_HEADER(SALOME_Exception)
52
53 using namespace std;
54
55 /*!
56   Constructor.
57 */
58 SalomeApp_Study::SalomeApp_Study( SUIT_Application* app )
59 : LightApp_Study( app )
60 {
61 }  
62
63 /*!
64   Destructor.
65 */
66 SalomeApp_Study::~SalomeApp_Study()
67 {
68 }
69
70 /*!
71   Gets study id.
72 */
73 int SalomeApp_Study::id() const
74 {
75   int id = -1;
76   if ( myStudyDS )
77     id = studyDS()->StudyId();
78   return id;
79 }
80
81 /*!
82   Gets studyDS pointer.
83 */
84 _PTR(Study) SalomeApp_Study::studyDS() const
85 {
86   return myStudyDS;
87 }
88
89 /*!
90   Create document.
91 */
92 void SalomeApp_Study::createDocument()
93 {
94   MESSAGE( "openDocument" );
95
96   // initialize myStudyDS, read HDF file
97   QString aName = newStudyName();
98   _PTR(Study) study ( SalomeApp_Application::studyMgr()->NewStudy( aName.latin1() ) );
99   if ( !study )
100     return;
101
102   setStudyDS( study );
103   setStudyName( aName );
104
105   // create myRoot
106   setRoot( new LightApp_RootObject( this ) );
107
108   CAM_Study::createDocument();
109   emit created( this );
110 }
111
112 /*!
113   Opens document
114   \param theFileName - name of file
115 */
116 bool SalomeApp_Study::openDocument( const QString& theFileName )
117 {
118   MESSAGE( "openDocument" );
119
120   // initialize myStudyDS, read HDF file
121   _PTR(Study) study ( SalomeApp_Application::studyMgr()->Open( (char*) theFileName.latin1() ) );
122   if ( !study )
123     return false;
124
125   setStudyDS( study );
126
127   setRoot( new LightApp_RootObject( this ) ); // create myRoot
128
129   // update loaded data models: call open() and update() on them.
130   ModelList dm_s;
131   dataModels( dm_s );
132   for ( ModelListIterator it( dm_s ); it.current(); ++it )
133     openDataModel( studyName(), it.current() );
134
135   // this will build a SUIT_DataObject-s tree under myRoot member field
136   // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
137   // but tree that corresponds to not-loaded data models will be updated any way. 
138   ((SalomeApp_Application*)application())->updateObjectBrowser( false ); 
139
140   bool res = CAM_Study::openDocument( theFileName );
141   
142   emit opened( this );
143   study->IsSaved(true);
144
145   bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
146   if ( restore ) {
147     std::vector<int> savePoints = getSavePoints();
148     if ( savePoints.size() > 0 )
149       SalomeApp_VisualState( (SalomeApp_Application*)application() ).restoreState( savePoints[savePoints.size()-1] );
150   }
151
152   return res;
153 }
154
155 /*!
156   Connects GUI study to SALOMEDS one already loaded into StudyManager
157   \param theStudyName - name of study
158 */
159 bool SalomeApp_Study::loadDocument( const QString& theStudyName )
160 {
161   MESSAGE( "loadDocument" );
162
163   // obtain myStudyDS from StudyManager
164   _PTR(Study) study ( SalomeApp_Application::studyMgr()->GetStudyByName( (char*) theStudyName.latin1() ) );
165   if ( !study )
166     return false;
167
168   setStudyDS( study );
169
170   setRoot( new LightApp_RootObject( this ) ); // create myRoot
171
172   //SRN: BugID IPAL9021, put there the same code as in a method openDocument
173
174   // update loaded data models: call open() and update() on them.
175   ModelList dm_s;
176   dataModels( dm_s );
177
178   for ( ModelListIterator it( dm_s ); it.current(); ++it )
179     openDataModel( studyName(), it.current() );
180
181   // this will build a SUIT_DataObject-s tree under myRoot member field
182   // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
183   // but tree that corresponds to not-loaded data models will be updated any way. 
184   ((SalomeApp_Application*)application())->updateObjectBrowser( false ); 
185
186   bool res = CAM_Study::openDocument( theStudyName );
187   emit opened( this );
188
189   bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
190   if ( restore ) {
191     std::vector<int> savePoints = getSavePoints();
192     if ( savePoints.size() > 0 )
193       SalomeApp_VisualState( (SalomeApp_Application*)application() ).restoreState( savePoints[savePoints.size()-1] );
194   }
195
196   //SRN: BugID IPAL9021: End
197
198   return res;
199 }
200
201 /*!
202   Saves document
203   \param theFileName - name of file
204 */
205 bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
206 {
207   bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
208   if ( store )
209     SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
210   
211   ModelList list; dataModels( list );
212
213   SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
214   QStringList listOfFiles;
215   for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
216     listOfFiles.clear();
217     aModel->saveAs( theFileName, this, listOfFiles );
218     if ( !listOfFiles.isEmpty() )
219       saveModuleData(aModel->module()->name(), listOfFiles);
220   }
221
222   // save SALOMEDS document
223   SUIT_ResourceMgr* resMgr = application()->resourceMgr();
224   if( !resMgr )
225     return false;
226
227   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false );
228   bool isAscii = resMgr->booleanValue( "Study", "ascii_file", false );
229   bool res = (isAscii ? 
230     SalomeApp_Application::studyMgr()->SaveAsASCII( theFileName.latin1(), studyDS(), isMultiFile ) :
231     SalomeApp_Application::studyMgr()->SaveAs     ( theFileName.latin1(), studyDS(), isMultiFile ))
232     && CAM_Study::saveDocumentAs( theFileName );
233   
234   res = res && saveStudyData(theFileName);
235
236   if ( res )
237     emit saved( this );
238
239   return res;
240 }
241
242 /*!
243   Saves previously opened document
244 */
245 bool SalomeApp_Study::saveDocument()
246 {
247   bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
248   if ( store )
249     SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
250
251   ModelList list; dataModels( list );
252
253   SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
254   QStringList listOfFiles;
255   for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
256     listOfFiles.clear();
257     aModel->save(listOfFiles);
258     if ( !listOfFiles.isEmpty() ) 
259       saveModuleData(aModel->module()->name(), listOfFiles);
260   }
261
262   // save SALOMEDS document
263   SUIT_ResourceMgr* resMgr = application()->resourceMgr();
264   if( !resMgr )
265     return false;
266
267   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false );
268   bool isAscii = resMgr->booleanValue( "Study", "ascii_file", false );
269   bool res = (isAscii ? 
270     SalomeApp_Application::studyMgr()->SaveASCII( studyDS(), isMultiFile ) :
271     SalomeApp_Application::studyMgr()->Save     ( studyDS(), isMultiFile )) && CAM_Study::saveDocument();
272
273   res = res && saveStudyData(studyName());
274   if ( res )
275     emit saved( this );  
276
277   return res;
278 }
279
280 /*!
281   Closes document
282 */
283 void SalomeApp_Study::closeDocument(bool permanently)
284 {
285   LightApp_Study::closeDocument(permanently);
286
287   // close SALOMEDS document
288   _PTR(Study) studyPtr = studyDS();
289   if ( studyPtr )
290   {
291     if(permanently) SalomeApp_Application::studyMgr()->Close( studyPtr );
292     SALOMEDSClient_Study* aStudy = 0;
293     setStudyDS( _PTR(Study)(aStudy) );
294   }
295 }
296
297 /*!
298   \return true, if study is modified in comparison with last open/save
299 */
300 bool SalomeApp_Study::isModified() const
301 {
302   bool isAnyChanged = studyDS() && studyDS()->IsModified();
303   if (!isAnyChanged)
304     isAnyChanged = LightApp_Study::isModified();
305
306   return isAnyChanged; 
307 }
308
309 /*!
310   \return if data model is saved
311 */
312 bool SalomeApp_Study::isSaved() const
313 {
314   bool isAllSaved = studyDS() && studyDS()->GetPersistentReference().size();
315   if (!isAllSaved)
316     isAllSaved = LightApp_Study::isSaved();
317
318   return isAllSaved; 
319 }
320
321 /*!
322   Saves data of module
323   \param theModuleName - name of module
324   \param theListOfFiles - list of files to be saved
325 */
326 void SalomeApp_Study::saveModuleData( QString theModuleName, QStringList theListOfFiles )
327 {
328   int aNb = theListOfFiles.count();
329   if ( aNb == 0 )
330     return;
331
332   std::vector<std::string> aListOfFiles ( aNb );
333   int anIndex = 0;
334   for ( QStringList::Iterator it = theListOfFiles.begin(); it != theListOfFiles.end(); ++it ) {
335     if ( (*it).isEmpty() )
336       continue;
337     aListOfFiles[anIndex] = (*it).latin1();
338     anIndex++;
339   }
340   SetListOfFiles(theModuleName, aListOfFiles);
341 }
342
343 /*!
344   Loads data of module
345   \param theModuleName - name of module
346   \param theListOfFiles - list of files to be loaded
347 */
348 void SalomeApp_Study::openModuleData( QString theModuleName, QStringList& theListOfFiles )
349 {
350   std::vector<std::string> aListOfFiles =  GetListOfFiles( theModuleName );
351
352   int i, aLength = aListOfFiles.size() - 1;
353   if ( aLength < 0 )
354     return;
355
356   //Get a temporary directory for saved a file
357   theListOfFiles.append(aListOfFiles[0].c_str());
358
359   for(i = 0; i < aLength; i++)
360     theListOfFiles.append(aListOfFiles[i+1].c_str());
361 }
362
363 /*!
364   Saves data from study
365 */
366 bool SalomeApp_Study::saveStudyData( const QString& theFileName )
367 {
368   ModelList list; dataModels( list );
369   SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
370   std::vector<std::string> listOfFiles(0);
371   for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() )
372     SetListOfFiles(aModel->module()->name(), listOfFiles);
373   return true;
374 }
375
376 /*!
377   Loads data for study
378 */
379 bool SalomeApp_Study::openStudyData( const QString& theFileName )
380 {
381  return true;
382 }
383
384 /*!
385   Set studyDS.
386 */
387 void SalomeApp_Study::setStudyDS( const _PTR(Study)& s )
388 {
389   myStudyDS = s;
390 }
391
392 /*!
393   Insert data model.
394 */
395 void SalomeApp_Study::dataModelInserted (const CAM_DataModel* dm)
396 {
397   MESSAGE("SalomeApp_Study::dataModelInserted() : module name() = " << dm->module()->name());
398
399   CAM_Study::dataModelInserted(dm);
400
401   //  addComponent(dm);
402 }
403
404 /*!
405   Create SComponent for module, using default engine (CORBAless)
406 */
407 void SalomeApp_Study::addComponent(const CAM_DataModel* dm)
408 {
409   SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
410   // 1. aModule == 0 means that this is a light module (no CORBA enigine)
411   if (!aModule) {
412     // Check SComponent existance
413     _PTR(Study) aStudy = studyDS();
414     if (!aStudy) 
415       return;
416     _PTR(SComponent) aComp = aStudy->FindComponent(dm->module()->name());
417     if (!aComp) {
418       // Create SComponent
419       _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
420       aComp = aBuilder->NewComponent(dm->module()->name());
421       aBuilder->SetName(aComp, dm->module()->moduleName().latin1());
422       QString anIconName = dm->module()->iconName();
423       if (!anIconName.isEmpty()) {
424         _PTR(AttributePixMap) anAttr = aBuilder->FindOrCreateAttribute(aComp, "AttributePixMap");
425         if (anAttr)
426           anAttr->SetPixMap(anIconName.latin1());
427       }
428       // Set default engine IOR
429       aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().latin1());
430       //SalomeApp_DataModel::BuildTree( aComp, root(), this, /*skipExisitng=*/true );
431       SalomeApp_DataModel::synchronize( aComp, this );
432     }
433   }
434 }
435
436 /*!
437   Open data model
438 */
439 bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm )
440 {
441   if (!dm)
442     return false;
443
444   //  SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm);
445   SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
446   _PTR(Study)       aStudy = studyDS(); // shared_ptr cannot be used here
447   _PTR(SComponent)  aSComp;
448   QString anEngine;
449   // 1. aModule == 0 means that this is a light module (no CORBA enigine)
450   if (!aModule) {
451     anEngine = SalomeApp_Application::defaultEngineIOR();
452     aSComp = aStudy->FindComponent(dm->module()->name());
453   }
454   else {
455     SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
456     if ( aDM ) {
457       QString anId = aDM->getRootEntry( this );
458       if ( anId.isEmpty() )
459         return true; // Probably nothing to load
460       anEngine = aDM->getModule()->engineIOR();
461       if ( anEngine.isEmpty() )
462         return false;
463       aSComp = aStudy->FindComponentID( std::string( anId.latin1() ) );
464     }
465   }
466   if ( aSComp ) {
467     _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() );
468     if ( aBuilder ) {
469       try {
470         aBuilder->LoadWith( aSComp, std::string( anEngine.latin1() ) );
471       }
472       catch( const SALOME::SALOME_Exception& ) {
473         // Oops, something went wrong while loading -> return an error
474         return false;
475       }
476       // Something has been read -> create data model tree
477       //SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
478       // aDM->buildTree( aSComp, 0, this );
479     }
480   } else {
481     // Don't return false here, for there might be no data
482     // for a given component in the study yet
483   }
484   QStringList listOfFiles;
485   openModuleData(dm->module()->name(), listOfFiles);
486   if (dm && dm->open(studyName, this, listOfFiles)) {
487     // Remove the files and temporary directory, created
488     // for this module by LightApp_Engine_i::Load()
489     bool isMultiFile = false; // TODO: decide, how to access this parameter
490     RemoveTemporaryFiles( dm->module()->name(), isMultiFile );
491
492     // Something has been read -> create data model tree
493     LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>( dm );
494     if ( aDM )
495       aDM->update(NULL, this);
496     return true;
497   }
498   return false;
499 }
500
501 /*!
502   Create new study name.
503 */
504 QString SalomeApp_Study::newStudyName() const
505 {
506   std::vector<std::string> studies = SalomeApp_Application::studyMgr()->GetOpenStudies();
507   QString prefix( "Study%1" ), newName, curName;
508   int i = 1, j, n = studies.size();
509   while ( newName.isEmpty() ){
510     curName = prefix.arg( i );
511     for ( j = 0 ; j < n; j++ ){
512       if ( !strcmp( studies[j].c_str(), curName.latin1() ) )
513         break;
514     }
515     if ( j == n )
516       newName = curName;
517     else
518       i++;
519   }
520   return newName;
521 }
522
523 /*!
524   \return list of files used by module: to be used by CORBAless modules
525   \param theModuleName - name of module
526 */
527 std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleName  ) const
528 {
529   SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
530   if (aDefaultEngine)
531     return aDefaultEngine->GetListOfFiles(id(), theModuleName);
532
533   std::vector<std::string> aListOfFiles;
534   return aListOfFiles;
535 }
536
537 /*!
538   Sets list of files used by module: to be used by CORBAless modules
539   \param theModuleName - name of module
540   \param theListOfFiles - list of files
541 */
542 void SalomeApp_Study::SetListOfFiles ( const char* theModuleName,
543                                        const std::vector<std::string> theListOfFiles )
544 {
545   SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
546   if (aDefaultEngine)
547     aDefaultEngine->SetListOfFiles(theListOfFiles, id(), theModuleName);
548 }
549
550 /*!
551   \return temporary directory for saving files of modules
552 */
553 std::string SalomeApp_Study::GetTmpDir ( const char* theURL, const bool  isMultiFile )
554 {
555   std::string anURLDir = SALOMEDS_Tool::GetDirFromPath(theURL);
556   std::string aTmpDir = isMultiFile ? anURLDir : SALOMEDS_Tool::GetTmpDir();
557   return aTmpDir;
558 }
559
560 /*!
561   Removes temporary files
562 */
563 void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bool isMultiFile ) const
564 {
565   if (isMultiFile)
566     return;
567
568   std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName );
569   if (aListOfFiles.size() > 0) {
570     std::string aTmpDir = aListOfFiles[0];
571
572     const int n = aListOfFiles.size() - 1;
573     SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
574     aSeq->length(n);
575     for (int i = 0; i < n; i++)
576       aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str());
577
578     SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
579   }
580 }
581
582 /*!
583   Deletes all references to object
584   \param obj - object
585 */
586 void SalomeApp_Study::deleteReferencesTo( _PTR( SObject ) obj )
587 {
588   _PTR(StudyBuilder) sb = studyDS()->NewBuilder();
589   std::vector<_PTR(SObject)> aRefs = studyDS()->FindDependances( obj );
590   for( int i=0, n=aRefs.size(); i<n; i++ )
591   {
592     _PTR( SObject ) o = aRefs[i];
593     if( o->GetFatherComponent()->ComponentDataType()==obj->GetFatherComponent()->ComponentDataType() )
594     {
595       sb->RemoveReference( o );
596       sb->RemoveObjectWithChildren( o );
597     }
598   }
599 }
600
601 /*!
602   \return real entry by entry of reference
603   \param entry - entry of reference object
604 */
605 QString SalomeApp_Study::referencedToEntry( const QString& entry ) const
606 {
607   _PTR(SObject) obj = studyDS()->FindObjectID( entry.latin1() );
608   _PTR(SObject) refobj;
609
610   if( obj && obj->ReferencedObject( refobj ) )
611     return refobj->GetID().c_str();
612   return LightApp_Study::referencedToEntry( entry );
613 }
614
615 /*!
616   \return component data type for entry
617 */
618 QString SalomeApp_Study::componentDataType( const QString& entry ) const
619 {
620   _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) );
621   if ( !obj )
622     return LightApp_Study::componentDataType( entry );
623   return obj->GetFatherComponent()->ComponentDataType().c_str();
624 }
625
626 /*!
627   \return true if entry corresponds to component
628 */
629 bool SalomeApp_Study::isComponent( const QString& entry ) const
630 {
631   _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) );
632   return obj && QString( obj->GetID().c_str() ) == obj->GetFatherComponent()->GetID().c_str();
633 }
634
635 /*!
636   \return entries of object children
637 */
638 void SalomeApp_Study::children( const QString& entry, QStringList& child_entries ) const
639 {
640   _PTR(SObject) SO = studyDS()->FindObjectID( entry.latin1() );
641   _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( SO ) );
642   anIter->InitEx( true );
643   while( anIter->More() )
644   {
645     _PTR(SObject) val( anIter->Value() );
646     child_entries.append( val->GetID().c_str() );
647     anIter->Next();
648   }
649 }
650
651 /*!
652   Fills list with components names
653   \param comp - list to be filled
654 */
655 void SalomeApp_Study::components( QStringList& comps ) const
656 {
657   for( _PTR(SComponentIterator) it ( studyDS()->NewComponentIterator() ); it->More(); it->Next() ) 
658   {
659     _PTR(SComponent) aComponent ( it->Value() );
660     if( aComponent && aComponent->ComponentDataType() == "Interface Applicative" )
661       continue; // skip the magic "Interface Applicative" component
662     comps.append( aComponent->ComponentDataType().c_str() );
663   }
664 }
665
666 /*!
667   \return a list of saved points' IDs
668 */
669 std::vector<int> SalomeApp_Study::getSavePoints()
670 {
671   std::vector<int> v;
672
673   _PTR(SObject) so = studyDS()->FindComponent("Interface Applicative");
674   if(!so) return v;
675
676   _PTR(StudyBuilder) builder = studyDS()->NewBuilder();
677   _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( so ) );
678   for(; anIter->More(); anIter->Next())
679   {
680     _PTR(SObject) val( anIter->Value() );
681     _PTR(GenericAttribute) genAttr;
682     if(builder->FindAttribute(val, genAttr, "AttributeParameter")) v.push_back(val->Tag());
683   }
684
685   return v;
686 }
687
688 /*!
689   Removes a given save point
690 */
691 void SalomeApp_Study::removeSavePoint(int savePoint)
692 {
693   if(savePoint <= 0) return;
694  _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
695   _PTR(SObject) so = AP->GetSObject();
696   _PTR(StudyBuilder) builder = studyDS()->NewBuilder();
697   builder->RemoveObjectWithChildren(so);
698 }
699
700 /*!
701   \return a name of save point
702 */
703 QString SalomeApp_Study::getNameOfSavePoint(int savePoint)
704 {
705   _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
706   _PTR(IParameters) ip = ClientFactory::getIParameters(AP);
707   return ip->getProperty("AP_SAVEPOINT_NAME");
708 }
709
710 /*!
711   Sets a name of save point
712 */
713 void SalomeApp_Study::setNameOfSavePoint(int savePoint, const QString& nameOfSavePoint)
714 {
715   _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
716   _PTR(IParameters) ip = ClientFactory::getIParameters(AP);
717   ip->setProperty("AP_SAVEPOINT_NAME", nameOfSavePoint.latin1());
718 }
719
720 /*!
721   \return a name of the component where visual parameters are stored
722 */
723 std::string SalomeApp_Study::getVisualComponentName()
724 {
725   return "Interface Applicative";
726 }
727
728 /*!
729   Slot: called on change of a root of a data model. Redefined from CAM_Study
730 */
731 void SalomeApp_Study::updateModelRoot( const CAM_DataModel* dm )
732 {
733   LightApp_Study::updateModelRoot( dm );
734
735   // calling updateSavePointDataObjects in order to set correct order of "Gui states" object
736   // it must always be the last one.
737   ((SalomeApp_Application*)application())->updateSavePointDataObjects( this );
738 }