1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
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.
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.
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
17 // See http://www.salome-platform.org/
19 #include "SalomeApp_Study.h"
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"
27 #include "LightApp_RootObject.h"
29 #include <OB_Browser.h>
31 #include <SUIT_ResourceMgr.h>
35 #include "utilities.h"
39 #include "SALOMEDS_Tool.hxx"
41 #include <SALOMEconfig.h>
42 #include CORBA_SERVER_HEADER(SALOME_Exception)
47 SalomeApp_Study::SalomeApp_Study( SUIT_Application* app )
48 : LightApp_Study( app )
55 SalomeApp_Study::~SalomeApp_Study()
62 int SalomeApp_Study::id() const
66 id = studyDS()->StudyId();
73 _PTR(Study) SalomeApp_Study::studyDS() const
81 void SalomeApp_Study::createDocument()
83 MESSAGE( "openDocument" );
85 // initialize myStudyDS, read HDF file
86 QString aName = newStudyName();
87 _PTR(Study) study ( SalomeApp_Application::studyMgr()->NewStudy( aName.latin1() ) );
92 setStudyName( aName );
95 setRoot( new LightApp_RootObject( this ) );
97 CAM_Study::createDocument();
101 //=======================================================================
102 // name : openDocument
103 /*! Purpose : Open document*/
104 //=======================================================================
105 bool SalomeApp_Study::openDocument( const QString& theFileName )
107 MESSAGE( "openDocument" );
109 // initialize myStudyDS, read HDF file
110 _PTR(Study) study ( SalomeApp_Application::studyMgr()->Open( (char*) theFileName.latin1() ) );
116 setRoot( new LightApp_RootObject( this ) ); // create myRoot
118 // update loaded data models: call open() and update() on them.
121 for ( ModelListIterator it( dm_s ); it.current(); ++it )
122 openDataModel( studyName(), it.current() );
124 // this will build a SUIT_DataObject-s tree under myRoot member field
125 // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
126 // but tree that corresponds to not-loaded data models will be updated any way.
127 ((SalomeApp_Application*)application())->updateObjectBrowser( false );
129 bool res = CAM_Study::openDocument( theFileName );
132 study->IsSaved(true);
136 //=======================================================================
137 // name : loadDocument
138 /*! Purpose : Connects GUI study to SALOMEDS one already loaded into StudyManager*/
139 //=======================================================================
140 bool SalomeApp_Study::loadDocument( const QString& theStudyName )
142 MESSAGE( "loadDocument" );
144 // obtain myStudyDS from StudyManager
145 _PTR(Study) study ( SalomeApp_Application::studyMgr()->GetStudyByName( (char*) theStudyName.latin1() ) );
151 setRoot( new LightApp_RootObject( this ) ); // create myRoot
153 //SRN: BugID IPAL9021, put there the same code as in a method openDocument
155 // update loaded data models: call open() and update() on them.
159 for ( ModelListIterator it( dm_s ); it.current(); ++it )
160 openDataModel( studyName(), it.current() );
162 // this will build a SUIT_DataObject-s tree under myRoot member field
163 // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
164 // but tree that corresponds to not-loaded data models will be updated any way.
165 ((SalomeApp_Application*)application())->updateObjectBrowser( false );
167 bool res = CAM_Study::openDocument( theStudyName );
170 //SRN: BugID IPAL9021: End
175 //=======================================================================
176 // name : saveDocumentAs
177 /*! Purpose : Save document*/
178 //=======================================================================
179 bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
181 ModelList list; dataModels( list );
183 SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
184 QStringList listOfFiles;
185 for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
187 aModel->saveAs( theFileName, this, listOfFiles );
188 if ( !listOfFiles.isEmpty() )
189 saveModuleData(aModel->module()->name(), listOfFiles);
192 // save SALOMEDS document
193 SUIT_ResourceMgr* resMgr = application()->resourceMgr();
197 bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ),
198 isAscii = resMgr->booleanValue( "Study", "ascii_file", false );
199 isAscii ? SalomeApp_Application::studyMgr()->SaveAsASCII( theFileName.latin1(), studyDS(), isMultiFile ) :
200 SalomeApp_Application::studyMgr()->SaveAs ( theFileName.latin1(), studyDS(), isMultiFile );
202 bool res = CAM_Study::saveDocumentAs( theFileName ); //SRN: BugID IPAL9377, removed usage of uninitialized variable <res>
203 res = res && saveStudyData(theFileName);
210 //=======================================================================
211 // name : saveDocument
212 /*! Purpose : Save document*/
213 //=======================================================================
214 bool SalomeApp_Study::saveDocument()
216 ModelList list; dataModels( list );
218 SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
219 QStringList listOfFiles;
220 for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
222 aModel->save(listOfFiles);
223 if ( !listOfFiles.isEmpty() )
224 saveModuleData(aModel->module()->name(), listOfFiles);
227 // save SALOMEDS document
228 SUIT_ResourceMgr* resMgr = application()->resourceMgr();
232 bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ),
233 isAscii = resMgr->booleanValue( "Study", "ascii_file", false );
234 isAscii ? SalomeApp_Application::studyMgr()->SaveASCII( studyDS(), isMultiFile ) :
235 SalomeApp_Application::studyMgr()->Save ( studyDS(), isMultiFile );
237 bool res = CAM_Study::saveDocument();
239 res = res && saveStudyData(studyName());
246 //================================================================
247 // Function : closeDocument
248 /*! Purpose : Close document*/
249 //================================================================
250 void SalomeApp_Study::closeDocument(bool permanently)
252 LightApp_Study::closeDocument(permanently);
254 // close SALOMEDS document
255 _PTR(Study) studyPtr = studyDS();
258 if(permanently) SalomeApp_Application::studyMgr()->Close( studyPtr );
259 SALOMEDSClient_Study* aStudy = 0;
260 setStudyDS( _PTR(Study)(aStudy) );
264 //================================================================
265 // Function : isModified
267 //================================================================
268 bool SalomeApp_Study::isModified() const
270 bool isAnyChanged = studyDS() && studyDS()->IsModified();
272 isAnyChanged = LightApp_Study::isModified();
277 //================================================================
278 // Function : isSaved
279 /*! Purpose : Check: data model is saved?*/
280 //================================================================
281 bool SalomeApp_Study::isSaved() const
283 bool isAllSaved = studyDS() && studyDS()->GetPersistentReference().size();
285 isAllSaved = LightApp_Study::isModified();
290 //=======================================================================
291 // name : saveModuleData
292 /*! Purpose : save list file for module 'theModuleName' */
293 //=======================================================================
294 void SalomeApp_Study::saveModuleData( QString theModuleName, QStringList theListOfFiles )
296 int aNb = theListOfFiles.count();
300 std::vector<std::string> aListOfFiles ( aNb );
302 for ( QStringList::Iterator it = theListOfFiles.begin(); it != theListOfFiles.end(); ++it ) {
303 if ( (*it).isEmpty() )
305 aListOfFiles[anIndex] = (*it).latin1();
308 SetListOfFiles(theModuleName, aListOfFiles);
311 //=======================================================================
312 // name : openModuleData
313 /*! Purpose : gets list of file for module 'theModuleNam' */
314 //=======================================================================
315 void SalomeApp_Study::openModuleData( QString theModuleName, QStringList& theListOfFiles )
317 std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName );
319 int i, aLength = aListOfFiles.size() - 1;
323 //Get a temporary directory for saved a file
324 theListOfFiles.append(aListOfFiles[0].c_str());
326 for(i = 0; i < aLength; i++)
327 theListOfFiles.append(aListOfFiles[i+1].c_str());
330 //=======================================================================
331 // name : saveStudyData
332 /*! Purpose : save data from study */
333 //=======================================================================
334 bool SalomeApp_Study::saveStudyData( const QString& theFileName )
336 ModelList list; dataModels( list );
337 SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
338 std::vector<std::string> listOfFiles(0);
339 for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() )
340 SetListOfFiles(aModel->module()->name(), listOfFiles);
344 //=======================================================================
345 // name : openStudyData
346 /*! Purpose : open data for study */
347 //=======================================================================
348 bool SalomeApp_Study::openStudyData( const QString& theFileName )
356 void SalomeApp_Study::setStudyDS( const _PTR(Study)& s )
364 void SalomeApp_Study::dataModelInserted (const CAM_DataModel* dm)
366 MESSAGE("SalomeApp_Study::dataModelInserted() : module name() = " << dm->module()->name());
368 CAM_Study::dataModelInserted(dm);
374 Create SComponent for module, using default engine (CORBAless)
376 void SalomeApp_Study::addComponent(const CAM_DataModel* dm)
378 SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
379 // 1. aModule == 0 means that this is a light module (no CORBA enigine)
381 // Check SComponent existance
382 _PTR(Study) aStudy = studyDS();
385 _PTR(SComponent) aComp = aStudy->FindComponent(dm->module()->name());
388 _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
389 aComp = aBuilder->NewComponent(dm->module()->name());
390 aBuilder->SetName(aComp, dm->module()->moduleName().latin1());
391 QString anIconName = dm->module()->iconName();
392 if (!anIconName.isEmpty()) {
393 _PTR(AttributePixMap) anAttr = aBuilder->FindOrCreateAttribute(aComp, "AttributePixMap");
395 anAttr->SetPixMap(anIconName.latin1());
397 // Set default engine IOR
398 aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().latin1());
399 SalomeApp_DataModel::BuildTree( aComp, root(), this, /*skipExisitng=*/true );
407 bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm )
412 // SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm);
413 SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
414 _PTR(Study) aStudy = studyDS(); // shared_ptr cannot be used here
415 _PTR(SComponent) aSComp;
417 // 1. aModule == 0 means that this is a light module (no CORBA enigine)
419 anEngine = SalomeApp_Application::defaultEngineIOR();
420 aSComp = aStudy->FindComponent(dm->module()->name());
423 SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
425 QString anId = aDM->getRootEntry( this );
426 if ( anId.isEmpty() )
427 return true; // Probably nothing to load
428 anEngine = aDM->getModule()->engineIOR();
429 if ( anEngine.isEmpty() )
431 aSComp = aStudy->FindComponentID( std::string( anId.latin1() ) );
435 _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() );
438 aBuilder->LoadWith( aSComp, std::string( anEngine.latin1() ) );
440 catch( const SALOME::SALOME_Exception& ) {
441 // Oops, something went wrong while loading -> return an error
444 // Something has been read -> create data model tree
445 //SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
446 // aDM->buildTree( aSComp, 0, this );
449 // Don't return false here, for there might be no data
450 // for a given component in the study yet
452 QStringList listOfFiles;
453 openModuleData(dm->module()->name(), listOfFiles);
454 if (dm && dm->open(studyName, this, listOfFiles)) {
455 // Remove the files and temporary directory, created
456 // for this module by LightApp_Engine_i::Load()
457 bool isMultiFile = false; // TODO: decide, how to access this parameter
458 RemoveTemporaryFiles( dm->module()->name(), isMultiFile );
460 // Something has been read -> create data model tree
461 LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>( dm );
463 aDM->update(NULL, this);
470 Create new study name.
472 QString SalomeApp_Study::newStudyName() const
474 std::vector<std::string> studies = SalomeApp_Application::studyMgr()->GetOpenStudies();
475 QString prefix( "Study%1" ), newName, curName;
476 int i = 1, j, n = studies.size();
477 while ( newName.isEmpty() ){
478 curName = prefix.arg( i );
479 for ( j = 0 ; j < n; j++ ){
480 if ( !strcmp( studies[j].c_str(), curName.latin1() ) )
491 //================================================================
492 // Function : GetListOfFiles
493 /*! Purpose : to be used by CORBAless modules*/
494 //================================================================
495 std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleName ) const
497 SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
499 return aDefaultEngine->GetListOfFiles(id(), theModuleName);
501 std::vector<std::string> aListOfFiles;
505 //================================================================
506 // Function : SetListOfFiles
507 /*! Purpose : to be used by CORBAless modules*/
508 //================================================================
509 void SalomeApp_Study::SetListOfFiles ( const char* theModuleName,
510 const std::vector<std::string> theListOfFiles )
512 SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
514 aDefaultEngine->SetListOfFiles(theListOfFiles, id(), theModuleName);
517 //================================================================
518 // Function : GetTmpDir
519 /*! Purpose : to be used by CORBAless modules*/
520 //================================================================
521 std::string SalomeApp_Study::GetTmpDir ( const char* theURL, const bool isMultiFile )
523 std::string anURLDir = SALOMEDS_Tool::GetDirFromPath(theURL);
524 std::string aTmpDir = isMultiFile ? anURLDir : SALOMEDS_Tool::GetTmpDir();
528 //================================================================
529 // Function : RemoveTemporaryFiles
530 /*! Purpose : to be used by CORBAless modules*/
531 //================================================================
532 void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bool isMultiFile ) const
537 std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName );
538 if (aListOfFiles.size() > 0) {
539 std::string aTmpDir = aListOfFiles[0];
541 const int n = aListOfFiles.size() - 1;
542 SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
544 for (int i = 0; i < n; i++)
545 aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str());
547 SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
551 // END: methods to be used by CORBAless modules
553 void SalomeApp_Study::deleteReferencesTo( _PTR( SObject ) obj )
555 _PTR(StudyBuilder) sb = studyDS()->NewBuilder();
556 std::vector<_PTR(SObject)> aRefs = studyDS()->FindDependances( obj );
557 for( int i=0, n=aRefs.size(); i<n; i++ )
559 _PTR( SObject ) o = aRefs[i];
560 if( o->GetFatherComponent()->ComponentDataType()==obj->GetFatherComponent()->ComponentDataType() )
562 sb->RemoveReference( o );
563 sb->RemoveObjectWithChildren( o );
568 //================================================================
569 // Function : referencedToEntry
570 /*! Purpose : Return referenced entry from entry*/
571 //================================================================
572 QString SalomeApp_Study::referencedToEntry( const QString& entry ) const
574 _PTR(SObject) obj = studyDS()->FindObjectID( entry.latin1() );
575 _PTR(SObject) refobj;
577 if( obj && obj->ReferencedObject( refobj ) )
578 return refobj->GetID().c_str();
579 return LightApp_Study::referencedToEntry( entry );
582 //================================================================
583 // Function : componentDataType
584 /*! Purpose : Return component data type from entry*/
585 //================================================================
586 QString SalomeApp_Study::componentDataType( const QString& entry ) const
588 _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) );
590 return LightApp_Study::componentDataType( entry );
591 return obj->GetFatherComponent()->ComponentDataType().c_str();
594 //================================================================
595 // Function : componentDataType
596 /*! Purpose : Return component data type from entry*/
597 //================================================================
598 bool SalomeApp_Study::isComponent( const QString& entry ) const
600 _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) );
601 return obj && QString( obj->GetID().c_str() ) == obj->GetFatherComponent()->GetID().c_str();
604 //================================================================
605 // Function : children
606 /*! Purpose : Return entries of children of object*/
607 //================================================================
608 void SalomeApp_Study::children( const QString& entry, QStringList& child_entries ) const
610 _PTR(SObject) SO = studyDS()->FindObjectID( entry.latin1() );
611 _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( SO ) );
612 anIter->InitEx( true );
613 while( anIter->More() )
615 _PTR(SObject) val( anIter->Value() );
616 child_entries.append( val->GetID().c_str() );
621 void SalomeApp_Study::components( QStringList& comps ) const
623 for( _PTR(SComponentIterator) it ( studyDS()->NewComponentIterator() ); it->More(); it->Next() )
625 _PTR(SComponent) aComponent ( it->Value() );
626 if( aComponent && aComponent->ComponentDataType() == "Interface Applicative" )
627 continue; // skip the magic "Interface Applicative" component
628 comps.append( aComponent->ComponentDataType().c_str() );