Salome HOME
Conversion between STL and C-string to avoid compilation errors.
[modules/gui.git] / src / SalomeApp / SalomeApp_Study.cxx
1 #include "SalomeApp_Study.h"
2
3 #include "SalomeApp_Module.h"
4 #include "SalomeApp_DataModel.h"
5 #include "SalomeApp_DataObject.h"
6 #include "SalomeApp_Application.h"
7 #include "SalomeApp_Engine_i.hxx"
8
9 #include "LightApp_RootObject.h"
10
11 #include <OB_Browser.h>
12
13 #include <SUIT_ResourceMgr.h>
14
15 #include <qptrlist.h>
16
17 #include "utilities.h"
18 #include "string.h"
19 #include "vector.h"
20
21 #include "SALOMEDS_Tool.hxx"
22
23 #include <SALOMEconfig.h>
24 #include CORBA_SERVER_HEADER(SALOME_Exception)
25
26 /*!
27   Constructor.
28 */
29 SalomeApp_Study::SalomeApp_Study( SUIT_Application* app )
30 : LightApp_Study( app )
31 {
32 }  
33
34 /*!
35   Destructor.
36 */
37 SalomeApp_Study::~SalomeApp_Study()
38 {
39 }
40
41 /*!
42   Gets study id.
43 */
44 int SalomeApp_Study::id() const
45 {
46   int id = -1;
47   if ( myStudyDS )
48     id = studyDS()->StudyId();
49   return id;
50 }
51
52 /*!
53   Gets studyDS pointer.
54 */
55 _PTR(Study) SalomeApp_Study::studyDS() const
56 {
57   return myStudyDS;
58 }
59
60 /*!
61   Create document.
62 */
63 void SalomeApp_Study::createDocument()
64 {
65   MESSAGE( "openDocument" );
66
67   // initialize myStudyDS, read HDF file
68   QString aName = newStudyName();
69   _PTR(Study) study ( SalomeApp_Application::studyMgr()->NewStudy( aName.latin1() ) );
70   if ( !study )
71     return;
72
73   setStudyDS( study );
74   setStudyName( aName );
75
76   // create myRoot
77   setRoot( new LightApp_RootObject( this ) );
78
79   CAM_Study::createDocument();
80   emit created( this );
81 }
82
83 //=======================================================================
84 // name    : openDocument
85 /*! Purpose : Open document*/
86 //=======================================================================
87 bool SalomeApp_Study::openDocument( const QString& theFileName )
88 {
89   MESSAGE( "openDocument" );
90
91   // initialize myStudyDS, read HDF file
92   _PTR(Study) study ( SalomeApp_Application::studyMgr()->Open( (char*) theFileName.latin1() ) );
93   if ( !study )
94     return false;
95
96   setStudyDS( study );
97
98   setRoot( new LightApp_RootObject( this ) ); // create myRoot
99
100   // update loaded data models: call open() and update() on them.
101   ModelList dm_s;
102   dataModels( dm_s );
103   for ( ModelListIterator it( dm_s ); it.current(); ++it )
104     openDataModel( studyName(), it.current() );
105
106   // this will build a SUIT_DataObject-s tree under myRoot member field
107   // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
108   // but tree that corresponds to not-loaded data models will be updated any way. 
109   ((SalomeApp_Application*)application())->updateObjectBrowser( false ); 
110
111   bool res = CAM_Study::openDocument( theFileName );
112   
113   emit opened( this );
114   study->IsSaved(true);
115   return res;
116 }
117
118 //=======================================================================
119 // name    : loadDocument
120 /*! Purpose : Connects GUI study to SALOMEDS one already loaded into StudyManager*/
121 //=======================================================================
122 bool SalomeApp_Study::loadDocument( const QString& theStudyName )
123 {
124   MESSAGE( "loadDocument" );
125
126   // obtain myStudyDS from StudyManager
127   _PTR(Study) study ( SalomeApp_Application::studyMgr()->GetStudyByName( (char*) theStudyName.latin1() ) );
128   if ( !study )
129     return false;
130
131   setStudyDS( study );
132
133   setRoot( new LightApp_RootObject( this ) ); // create myRoot
134
135   //SRN: BugID IPAL9021, put there the same code as in a method openDocument
136
137   // update loaded data models: call open() and update() on them.
138   ModelList dm_s;
139   dataModels( dm_s );
140
141   for ( ModelListIterator it( dm_s ); it.current(); ++it )
142     openDataModel( studyName(), it.current() );
143
144   // this will build a SUIT_DataObject-s tree under myRoot member field
145   // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
146   // but tree that corresponds to not-loaded data models will be updated any way. 
147   ((SalomeApp_Application*)application())->updateObjectBrowser( false ); 
148
149   bool res = CAM_Study::openDocument( theStudyName );
150   emit opened( this );
151
152   //SRN: BugID IPAL9021: End
153
154   return res;
155 }
156
157 //=======================================================================
158 // name    : saveDocumentAs
159 /*! Purpose : Save document*/
160 //=======================================================================
161 bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
162 {
163   ModelList list; dataModels( list );
164
165   SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
166   QStringList listOfFiles;
167   for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
168     listOfFiles.clear();
169     aModel->saveAs( theFileName, this, listOfFiles );
170     if ( !listOfFiles.isEmpty() )
171       saveModuleData(aModel->module()->name(), listOfFiles);
172   }
173
174   // save SALOMEDS document
175   SUIT_ResourceMgr* resMgr = application()->resourceMgr();
176   if( !resMgr )
177     return false;
178
179   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ),
180        isAscii = resMgr->booleanValue( "Study", "ascii_file", true );
181   isAscii ? SalomeApp_Application::studyMgr()->SaveAsASCII( theFileName.latin1(), studyDS(), isMultiFile ) :
182             SalomeApp_Application::studyMgr()->SaveAs     ( theFileName.latin1(), studyDS(), isMultiFile );
183
184   bool res = CAM_Study::saveDocumentAs( theFileName );  //SRN: BugID IPAL9377, removed usage of uninitialized variable <res>
185   res = res && saveStudyData(theFileName);
186   if ( res )
187     emit saved( this );
188
189   return res;
190 }
191
192 //=======================================================================
193 // name    : saveDocument
194 /*! Purpose : Save document*/
195 //=======================================================================
196 bool SalomeApp_Study::saveDocument()
197 {
198   ModelList list; dataModels( list );
199
200   SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
201   QStringList listOfFiles;
202   for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
203     listOfFiles.clear();
204     aModel->save(listOfFiles);
205     if ( !listOfFiles.isEmpty() )
206       saveModuleData(aModel->module()->name(), listOfFiles);
207   }
208
209   // save SALOMEDS document
210   SUIT_ResourceMgr* resMgr = application()->resourceMgr();
211   if( !resMgr )
212     return false;
213
214   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ),
215        isAscii = resMgr->booleanValue( "Study", "ascii_file", true );
216   isAscii ? SalomeApp_Application::studyMgr()->SaveASCII( studyDS(), isMultiFile ) :
217             SalomeApp_Application::studyMgr()->Save     ( studyDS(), isMultiFile );
218
219   bool res = CAM_Study::saveDocument();
220
221   res = res && saveStudyData(studyName());
222   if ( res )
223     emit saved( this );  
224
225   return res;
226 }
227
228 //================================================================
229 // Function : closeDocument
230 /*! Purpose  : Close document*/
231 //================================================================
232 void SalomeApp_Study::closeDocument(bool permanently)
233 {
234   LightApp_Study::closeDocument(permanently);
235
236   // close SALOMEDS document
237   _PTR(Study) studyPtr = studyDS();
238   if ( studyPtr )
239   {
240     if(permanently) SalomeApp_Application::studyMgr()->Close( studyPtr );
241     SALOMEDSClient_Study* aStudy = 0;
242     setStudyDS( _PTR(Study)(aStudy) );
243   }
244 }
245
246 //================================================================
247 // Function : isModified
248 // Purpose  : 
249 //================================================================
250 bool SalomeApp_Study::isModified() const
251 {
252   bool isAnyChanged = studyDS() && studyDS()->IsModified();
253   if (!isAnyChanged)
254     isAnyChanged = LightApp_Study::isModified();
255
256   return isAnyChanged; 
257 }
258
259 //================================================================
260 // Function : isSaved
261 /*! Purpose  : Check: data model is saved?*/
262 //================================================================
263 bool SalomeApp_Study::isSaved() const
264 {
265   bool isAllSaved = studyDS() && studyDS()->GetPersistentReference().size();
266   if (!isAllSaved)
267     isAllSaved = LightApp_Study::isModified();
268
269   return isAllSaved; 
270 }
271
272 //=======================================================================
273 // name    : saveModuleData
274 /*! Purpose : save list file for module 'theModuleName' */
275 //=======================================================================
276 void SalomeApp_Study::saveModuleData( QString theModuleName, QStringList theListOfFiles )
277 {
278   int aNb = theListOfFiles.count();
279   if ( aNb == 0 )
280     return;
281
282   std::vector<std::string> aListOfFiles ( aNb );
283   int anIndex = 0;
284   for ( QStringList::Iterator it = theListOfFiles.begin(); it != theListOfFiles.end(); ++it ) {
285     if ( (*it).isEmpty() )
286       continue;
287     aListOfFiles[anIndex] = (*it).latin1();
288     anIndex++;
289   }
290   SetListOfFiles(theModuleName, aListOfFiles);
291 }
292
293 //=======================================================================
294 // name    : openModuleData
295 /*! Purpose : gets list of file for module 'theModuleNam' */
296 //=======================================================================
297 void SalomeApp_Study::openModuleData( QString theModuleName, QStringList& theListOfFiles )
298 {
299   std::vector<std::string> aListOfFiles =  GetListOfFiles( theModuleName );
300
301   int i, aLength = aListOfFiles.size() - 1;
302   if ( aLength < 0 )
303     return;
304
305   //Get a temporary directory for saved a file
306   theListOfFiles.append(aListOfFiles[0].c_str());
307
308   for(i = 0; i < aLength; i++)
309     theListOfFiles.append(aListOfFiles[i+1].c_str());
310 }
311
312 //=======================================================================
313 // name    : saveStudyData
314 /*! Purpose : save data from study */
315 //=======================================================================
316 bool SalomeApp_Study::saveStudyData( const QString& theFileName )
317 {
318   ModelList list; dataModels( list );
319   SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
320   std::vector<std::string> listOfFiles(0);
321   for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() )
322     SetListOfFiles(aModel->module()->name(), listOfFiles);
323   return true;
324 }
325
326 //=======================================================================
327 // name    : openStudyData
328 /*! Purpose : open data for study */
329 //=======================================================================
330 bool SalomeApp_Study::openStudyData( const QString& theFileName )
331 {
332  return true;
333 }
334
335 /*!
336   Set studyDS.
337 */
338 void SalomeApp_Study::setStudyDS( const _PTR(Study)& s )
339 {
340   myStudyDS = s;
341 }
342
343 /*!
344   Insert data model.
345 */
346 void SalomeApp_Study::dataModelInserted (const CAM_DataModel* dm)
347 {
348   MESSAGE("SalomeApp_Study::dataModelInserted() : module name() = " << dm->module()->name());
349
350   CAM_Study::dataModelInserted(dm);
351
352   //  addComponent(dm);
353 }
354
355 /*!
356  Create SComponent for module, using default engine (CORBAless)
357 */
358 void SalomeApp_Study::addComponent(const CAM_DataModel* dm)
359 {
360   SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
361   // 1. aModule == 0 means that this is a light module (no CORBA enigine)
362   if (!aModule) {
363     // Check SComponent existance
364     _PTR(Study) aStudy = studyDS();
365     if (!aStudy) 
366       return;
367     _PTR(SComponent) aComp = aStudy->FindComponent(dm->module()->name());
368     if (!aComp) {
369       // Create SComponent
370       _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
371       aComp = aBuilder->NewComponent(dm->module()->name());
372       aBuilder->SetName(aComp, dm->module()->moduleName().latin1());
373       QString anIconName = dm->module()->iconName();
374       if (!anIconName.isEmpty()) {
375         _PTR(AttributePixMap) anAttr = aBuilder->FindOrCreateAttribute(aComp, "AttributePixMap");
376         if (anAttr)
377           anAttr->SetPixMap(anIconName.latin1());
378       }
379       // Set default engine IOR
380       aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().latin1());
381       SalomeApp_DataModel::BuildTree( aComp, root(), this, /*skipExisitng=*/true );
382     }
383   }
384 }
385
386 /*!
387   Open data model
388 */
389 bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm )
390 {
391   if (!dm)
392     return false;
393
394   //  SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm);
395   SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
396   _PTR(Study)       aStudy = studyDS(); // shared_ptr cannot be used here
397   _PTR(SComponent)  aSComp;
398   QString anEngine;
399   // 1. aModule == 0 means that this is a light module (no CORBA enigine)
400   if (!aModule) {
401     anEngine = SalomeApp_Application::defaultEngineIOR();
402     aSComp = aStudy->FindComponent(dm->module()->name());
403   }
404   else {
405     SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
406     if ( aDM ) {
407       QString anId = aDM->getRootEntry( this );
408       if ( anId.isEmpty() )
409         return true; // Probably nothing to load
410       anEngine = aDM->getModule()->engineIOR();
411       if ( anEngine.isEmpty() )
412         return false;
413       aSComp = aStudy->FindComponentID( std::string( anId.latin1() ) );
414     }
415   }
416   if ( aSComp ) {
417     _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() );
418     if ( aBuilder ) {
419       try {
420         aBuilder->LoadWith( aSComp, std::string( anEngine.latin1() ) );
421       }
422       catch( const SALOME::SALOME_Exception& ) {
423         // Oops, something went wrong while loading -> return an error
424         return false;
425       }
426       // Something has been read -> create data model tree
427       //SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
428       // aDM->buildTree( aSComp, 0, this );
429     }
430   } else {
431     // Don't return false here, for there might be no data
432     // for a given component in the study yet
433   }
434   QStringList listOfFiles;
435   openModuleData(dm->module()->name(), listOfFiles);
436   if (dm && dm->open(studyName, this, listOfFiles)) {
437     // Remove the files and temporary directory, created
438     // for this module by LightApp_Engine_i::Load()
439     bool isMultiFile = false; // TODO: decide, how to access this parameter
440     RemoveTemporaryFiles( dm->module()->name(), isMultiFile );
441
442     // Something has been read -> create data model tree
443     LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>( dm );
444     if ( aDM )
445       aDM->update(NULL, this);
446     return true;
447   }
448   return false;
449 }
450
451 /*!
452   Create new study name.
453 */
454 QString SalomeApp_Study::newStudyName() const
455 {
456   std::vector<std::string> studies = SalomeApp_Application::studyMgr()->GetOpenStudies();
457   QString prefix( "Study%1" ), newName, curName;
458   int i = 1, j, n = studies.size();
459   while ( newName.isEmpty() ){
460     curName = prefix.arg( i );
461     for ( j = 0 ; j < n; j++ ){
462       if ( !strcmp( studies[j].c_str(), curName.latin1() ) )
463         break;
464     }
465     if ( j == n )
466       newName = curName;
467     else
468       i++;
469   }
470   return newName;
471 }
472
473 //================================================================
474 // Function : GetListOfFiles
475 /*! Purpose  : to be used by CORBAless modules*/
476 //================================================================
477 std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleName  ) const
478 {
479   SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
480   if (aDefaultEngine)
481     return aDefaultEngine->GetListOfFiles(id(), theModuleName);
482
483   std::vector<std::string> aListOfFiles;
484   return aListOfFiles;
485 }
486
487 //================================================================
488 // Function : SetListOfFiles
489 /*! Purpose  : to be used by CORBAless modules*/
490 //================================================================
491 void SalomeApp_Study::SetListOfFiles ( const char* theModuleName,
492                                        const std::vector<std::string> theListOfFiles )
493 {
494   SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
495   if (aDefaultEngine)
496     aDefaultEngine->SetListOfFiles(theListOfFiles, id(), theModuleName);
497 }
498
499 //================================================================
500 // Function : GetTmpDir
501 /*! Purpose  : to be used by CORBAless modules*/
502 //================================================================
503 std::string SalomeApp_Study::GetTmpDir ( const char* theURL, const bool  isMultiFile )
504 {
505   std::string anURLDir = SALOMEDS_Tool::GetDirFromPath(theURL);
506   std::string aTmpDir = isMultiFile ? anURLDir : SALOMEDS_Tool::GetTmpDir();
507   return aTmpDir;
508 }
509
510 //================================================================
511 // Function : RemoveTemporaryFiles
512 /*! Purpose  : to be used by CORBAless modules*/
513 //================================================================
514 void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bool isMultiFile ) const
515 {
516   if (isMultiFile)
517     return;
518
519   std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName );
520   if (aListOfFiles.size() > 0) {
521     std::string aTmpDir = aListOfFiles[0];
522
523     const int n = aListOfFiles.size() - 1;
524     SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
525     aSeq->length(n);
526     for (int i = 0; i < n; i++)
527       aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str());
528
529     SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
530   }
531 }
532
533 // END: methods to be used by CORBAless modules
534
535 void SalomeApp_Study::deleteReferencesTo( _PTR( SObject ) obj )
536 {
537   _PTR(StudyBuilder) sb = studyDS()->NewBuilder();
538   std::vector<_PTR(SObject)> aRefs = studyDS()->FindDependances( obj );
539   for( int i=0, n=aRefs.size(); i<n; i++ )
540   {
541     _PTR( SObject ) o = aRefs[i];
542     if( o->GetFatherComponent()->ComponentDataType()==obj->GetFatherComponent()->ComponentDataType() )
543     {
544       sb->RemoveReference( o );
545       sb->RemoveObjectWithChildren( o );
546     }
547   }
548 }
549
550 //================================================================
551 // Function : referencedToEntry
552 /*! Purpose  : Return referenced entry from entry*/
553 //================================================================
554 QString SalomeApp_Study::referencedToEntry( const QString& entry )
555 {
556   _PTR(SObject) obj = studyDS()->FindObjectID( entry.latin1() );
557   _PTR(SObject) refobj;
558
559   if( obj && obj->ReferencedObject( refobj ) )
560     return refobj->GetID().c_str();
561   return LightApp_Study::referencedToEntry( entry );
562 }
563
564 //================================================================
565 // Function : componentDataType
566 /*! Purpose  : Return component data type from entry*/
567 //================================================================
568 QString SalomeApp_Study::componentDataType( const QString& entry )
569 {
570   _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) );
571   if ( !obj )
572     return LightApp_Study::componentDataType( entry );
573   return obj->GetFatherComponent()->ComponentDataType().c_str();
574 }