1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include "SalomeApp_Study.h"
24 #include "SalomeApp_Module.h"
25 #include "SalomeApp_DataObject.h"
26 #include "SalomeApp_DataModel.h"
27 #include "SalomeApp_Application.h"
28 #include "SalomeApp_Engine_i.hxx"
29 #include "SalomeApp_VisualState.h"
31 // temporary commented
32 //#include <OB_Browser.h>
34 #include <SUIT_ResourceMgr.h>
36 #include "utilities.h"
38 #include "SALOMEDS_Tool.hxx"
40 #include "SALOMEDSClient_ClientFactory.hxx"
42 #include <SALOMEconfig.h>
43 #include CORBA_SERVER_HEADER(SALOME_Exception)
50 SalomeApp_Study::SalomeApp_Study( SUIT_Application* app )
51 : LightApp_Study( app )
58 SalomeApp_Study::~SalomeApp_Study()
65 int SalomeApp_Study::id() const
69 id = studyDS()->StudyId();
76 _PTR(Study) SalomeApp_Study::studyDS() const
84 bool SalomeApp_Study::createDocument( const QString& theStr )
86 MESSAGE( "openDocument" );
88 // initialize myStudyDS, read HDF file
89 QString aName = newStudyName();
90 _PTR(Study) study ( SalomeApp_Application::studyMgr()->NewStudy( aName.toStdString() ) );
95 setStudyName( aName );
98 setRoot( new SalomeApp_RootObject( this ) );
100 bool aRet = CAM_Study::createDocument( theStr );
101 emit created( this );
108 \param theFileName - name of file
110 bool SalomeApp_Study::openDocument( const QString& theFileName )
112 MESSAGE( "openDocument" );
114 // initialize myStudyDS, read HDF file
115 _PTR(Study) study ( SalomeApp_Application::studyMgr()->Open( (char*) theFileName.toStdString().c_str() ) );
121 setRoot( new SalomeApp_RootObject( this ) ); // create myRoot
123 // update loaded data models: call open() and update() on them.
126 QListIterator<CAM_DataModel*> it( dm_s );
127 while ( it.hasNext() )
128 openDataModel( studyName(), it.next() );
130 // this will build a SUIT_DataObject-s tree under myRoot member field
131 // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
132 // but tree that corresponds to not-loaded data models will be updated any way.
133 ((SalomeApp_Application*)application())->updateObjectBrowser( false );
135 bool res = CAM_Study::openDocument( theFileName );
138 study->IsSaved(true);
140 bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
142 std::vector<int> savePoints = getSavePoints();
143 if ( savePoints.size() > 0 )
144 SalomeApp_VisualState( (SalomeApp_Application*)application() ).restoreState( savePoints[savePoints.size()-1] );
147 ((SalomeApp_Application*)application())->updateObjectBrowser( true );
152 Connects GUI study to SALOMEDS one already loaded into StudyManager
153 \param theStudyName - name of study
155 bool SalomeApp_Study::loadDocument( const QString& theStudyName )
157 MESSAGE( "loadDocument" );
159 // obtain myStudyDS from StudyManager
160 _PTR(Study) study ( SalomeApp_Application::studyMgr()->GetStudyByName( (char*) theStudyName.toStdString().c_str() ) );
166 setRoot( new SalomeApp_RootObject( this ) ); // create myRoot
168 //SRN: BugID IPAL9021, put there the same code as in a method openDocument
170 // update loaded data models: call open() and update() on them.
174 QListIterator<CAM_DataModel*> it( dm_s );
175 while ( it.hasNext() )
176 openDataModel( studyName(), it.next() );
178 // this will build a SUIT_DataObject-s tree under myRoot member field
179 // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
180 // but tree that corresponds to not-loaded data models will be updated any way.
181 ((SalomeApp_Application*)application())->updateObjectBrowser( false );
183 bool res = CAM_Study::openDocument( theStudyName );
186 bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
188 std::vector<int> savePoints = getSavePoints();
189 if ( savePoints.size() > 0 )
190 SalomeApp_VisualState( (SalomeApp_Application*)application() ).restoreState( savePoints[savePoints.size()-1] );
193 //SRN: BugID IPAL9021: End
199 \param theFileName - name of file
201 bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
203 bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", false );
205 SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
207 ModelList list; dataModels( list );
209 QListIterator<CAM_DataModel*> it( list );
210 QStringList listOfFiles;
211 while ( it.hasNext() ) {
212 if ( SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)it.next() ) {
214 aModel->saveAs( theFileName, this, listOfFiles );
215 if ( !listOfFiles.isEmpty() )
216 saveModuleData(aModel->module()->name(), listOfFiles);
220 // save SALOMEDS document
221 SUIT_ResourceMgr* resMgr = application()->resourceMgr();
225 bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false );
226 bool isAscii = resMgr->booleanValue( "Study", "ascii_file", false );
227 bool res = (isAscii ?
228 SalomeApp_Application::studyMgr()->SaveAsASCII( theFileName.toStdString(), studyDS(), isMultiFile ) :
229 SalomeApp_Application::studyMgr()->SaveAs ( theFileName.toStdString(), studyDS(), isMultiFile ))
230 && CAM_Study::saveDocumentAs( theFileName );
232 res = res && saveStudyData(theFileName);
241 Saves previously opened document
243 bool SalomeApp_Study::saveDocument()
245 bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
247 SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
249 ModelList list; dataModels( list );
251 QListIterator<CAM_DataModel*> it( list );
252 QStringList listOfFiles;
253 while ( it.hasNext() ) {
254 if ( SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)it.next() ) {
256 aModel->save(listOfFiles);
257 if ( !listOfFiles.isEmpty() )
258 saveModuleData(aModel->module()->name(), listOfFiles);
262 // save SALOMEDS document
263 SUIT_ResourceMgr* resMgr = application()->resourceMgr();
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();
273 res = res && saveStudyData(studyName());
283 void SalomeApp_Study::closeDocument(bool permanently)
285 LightApp_Study::closeDocument(permanently);
287 // close SALOMEDS document
288 _PTR(Study) studyPtr = studyDS();
292 SalomeApp_Application::studyMgr()->Close( studyPtr );
294 SALOMEDSClient_Study* aStudy = 0;
295 setStudyDS( _PTR(Study)(aStudy) );
300 \return true, if study is modified in comparison with last open/save
302 bool SalomeApp_Study::isModified() const
304 bool isAnyChanged = studyDS() && studyDS()->IsModified();
306 isAnyChanged = LightApp_Study::isModified();
312 Set study modified to \a on.
314 void SalomeApp_Study::Modified()
316 if(_PTR(Study) aStudy = studyDS())
318 LightApp_Study::Modified();
322 \return if data model is saved
324 bool SalomeApp_Study::isSaved() const
326 bool isAllSaved = studyDS() && studyDS()->GetPersistentReference().size();
328 isAllSaved = LightApp_Study::isSaved();
335 \param theModuleName - name of module
336 \param theListOfFiles - list of files to be saved
338 void SalomeApp_Study::saveModuleData( QString theModuleName, QStringList theListOfFiles )
340 int aNb = theListOfFiles.count();
344 std::vector<std::string> aListOfFiles ( aNb );
346 for ( QStringList::Iterator it = theListOfFiles.begin(); it != theListOfFiles.end(); ++it ) {
347 if ( (*it).isEmpty() )
349 aListOfFiles[anIndex] = (*it).toStdString();
352 SetListOfFiles(theModuleName.toStdString().c_str(), aListOfFiles);
357 \param theModuleName - name of module
358 \param theListOfFiles - list of files to be loaded
360 void SalomeApp_Study::openModuleData( QString theModuleName, QStringList& theListOfFiles )
362 std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName.toStdString().c_str() );
364 int i, aLength = aListOfFiles.size() - 1;
368 //Get a temporary directory for saved a file
369 theListOfFiles.append(aListOfFiles[0].c_str());
371 for(i = 0; i < aLength; i++)
372 theListOfFiles.append(aListOfFiles[i+1].c_str());
376 Saves data from study
378 bool SalomeApp_Study::saveStudyData( const QString& theFileName )
380 ModelList list; dataModels( list );
381 QListIterator<CAM_DataModel*> it( list );
382 std::vector<std::string> listOfFiles(0);
383 while ( it.hasNext() )
384 if ( SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)it.next() )
385 SetListOfFiles(aModel->module()->name().toStdString().c_str(), listOfFiles);
392 bool SalomeApp_Study::openStudyData( const QString& theFileName )
400 void SalomeApp_Study::setStudyDS( const _PTR(Study)& s )
408 void SalomeApp_Study::dataModelInserted (const CAM_DataModel* dm)
410 MESSAGE("SalomeApp_Study::dataModelInserted() : module name() = " << dm->module()->name().toStdString());
412 CAM_Study::dataModelInserted(dm);
418 Create SComponent for module, using default engine (CORBAless)
420 void SalomeApp_Study::addComponent(const CAM_DataModel* dm)
422 SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
423 // 1. aModule == 0 means that this is a light module (no CORBA enigine)
425 // Check SComponent existance
426 _PTR(Study) aStudy = studyDS();
429 _PTR(SComponent) aComp = aStudy->FindComponent(dm->module()->name().toStdString());
432 _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
433 aComp = aBuilder->NewComponent(dm->module()->name().toStdString());
434 aBuilder->SetName(aComp, dm->module()->moduleName().toStdString());
435 QString anIconName = dm->module()->iconName();
436 if (!anIconName.isEmpty()) {
437 _PTR(AttributePixMap) anAttr = aBuilder->FindOrCreateAttribute(aComp, "AttributePixMap");
439 anAttr->SetPixMap(anIconName.toStdString());
441 // Set default engine IOR
442 aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().toStdString());
443 //SalomeApp_DataModel::BuildTree( aComp, root(), this, /*skipExisitng=*/true );
444 SalomeApp_DataModel::synchronize( aComp, this );
452 bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm )
457 // SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm);
458 SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
459 _PTR(Study) aStudy = studyDS(); // shared_ptr cannot be used here
460 _PTR(SComponent) aSComp;
462 // 1. aModule == 0 means that this is a light module (no CORBA enigine)
464 anEngine = SalomeApp_Application::defaultEngineIOR();
465 aSComp = aStudy->FindComponent(dm->module()->name().toStdString());
468 SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
470 QString anId = aDM->getRootEntry( this );
471 if ( anId.isEmpty() )
472 return true; // Probably nothing to load
473 anEngine = aDM->getModule()->engineIOR();
474 if ( anEngine.isEmpty() )
476 aSComp = aStudy->FindComponentID( std::string( anId.toLatin1() ) );
480 _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() );
483 aBuilder->LoadWith( aSComp, std::string( anEngine.toLatin1() ) );
485 catch( const SALOME::SALOME_Exception& ) {
486 // Oops, something went wrong while loading -> return an error
489 // Something has been read -> create data model tree
490 //SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
491 // aDM->buildTree( aSComp, 0, this );
494 // Don't return false here, for there might be no data
495 // for a given component in the study yet
497 QStringList listOfFiles;
498 openModuleData(dm->module()->name(), listOfFiles);
499 if (dm && dm->open(studyName, this, listOfFiles)) {
500 // Remove the files and temporary directory, created
501 // for this module by LightApp_Engine_i::Load()
502 bool isMultiFile = false; // TODO: decide, how to access this parameter
503 RemoveTemporaryFiles( dm->module()->name().toStdString().c_str(), isMultiFile );
505 // Something has been read -> create data model tree
506 LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>( dm );
508 aDM->update(NULL, this);
515 Create new study name.
517 QString SalomeApp_Study::newStudyName() const
519 std::vector<std::string> studies = SalomeApp_Application::studyMgr()->GetOpenStudies();
520 QString prefix( "Study%1" ), newName, curName;
521 int i = 1, j, n = studies.size();
522 while ( newName.isEmpty() ){
523 curName = prefix.arg( i );
524 for ( j = 0 ; j < n; j++ ){
525 if ( !strcmp( studies[j].c_str(), curName.toLatin1() ) )
537 \return list of files used by module: to be used by CORBAless modules
538 \param theModuleName - name of module
540 std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleName ) const
542 SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
544 return aDefaultEngine->GetListOfFiles(id(), theModuleName);
546 std::vector<std::string> aListOfFiles;
551 Sets list of files used by module: to be used by CORBAless modules
552 \param theModuleName - name of module
553 \param theListOfFiles - list of files
555 void SalomeApp_Study::SetListOfFiles ( const char* theModuleName,
556 const std::vector<std::string> theListOfFiles )
558 SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
560 aDefaultEngine->SetListOfFiles(theListOfFiles, id(), theModuleName);
564 \return temporary directory for saving files of modules
566 std::string SalomeApp_Study::GetTmpDir ( const char* theURL, const bool isMultiFile )
568 std::string anURLDir = SALOMEDS_Tool::GetDirFromPath(theURL);
569 std::string aTmpDir = isMultiFile ? anURLDir : SALOMEDS_Tool::GetTmpDir();
574 Removes temporary files
576 void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bool isMultiFile ) const
581 std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName );
582 if (aListOfFiles.size() > 0) {
583 std::string aTmpDir = aListOfFiles[0];
585 const int n = aListOfFiles.size() - 1;
586 SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
588 for (int i = 0; i < n; i++)
589 aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str());
591 SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
596 Mark the study as saved in the file
597 \param theFileName - the name of file
599 void SalomeApp_Study::markAsSavedIn(QString theFileName)
601 setStudyName(theFileName);
606 Deletes all references to object
609 void SalomeApp_Study::deleteReferencesTo( _PTR( SObject ) obj )
611 _PTR(StudyBuilder) sb = studyDS()->NewBuilder();
612 std::vector<_PTR(SObject)> aRefs = studyDS()->FindDependances( obj );
613 for( int i=0, n=aRefs.size(); i<n; i++ )
615 _PTR( SObject ) o = aRefs[i];
616 if( o->GetFatherComponent()->ComponentDataType()==obj->GetFatherComponent()->ComponentDataType() )
618 sb->RemoveReference( o );
619 sb->RemoveObjectWithChildren( o );
625 \return real entry by entry of reference
626 \param entry - entry of reference object
628 QString SalomeApp_Study::referencedToEntry( const QString& entry ) const
630 _PTR(SObject) obj = studyDS()->FindObjectID( entry.toStdString() );
631 _PTR(SObject) refobj;
633 if( obj && obj->ReferencedObject( refobj ) )
634 return refobj->GetID().c_str();
635 return LightApp_Study::referencedToEntry( entry );
639 \return component data type for entry
641 QString SalomeApp_Study::componentDataType( const QString& entry ) const
643 _PTR(SObject) obj( studyDS()->FindObjectID( entry.toStdString() ) );
645 return LightApp_Study::componentDataType( entry );
646 return obj->GetFatherComponent()->ComponentDataType().c_str();
650 \return true if entry corresponds to component
652 bool SalomeApp_Study::isComponent( const QString& entry ) const
654 _PTR(SObject) obj( studyDS()->FindObjectID( entry.toStdString() ) );
655 return obj && QString( obj->GetID().c_str() ) == obj->GetFatherComponent()->GetID().c_str();
659 \return entries of object children
661 void SalomeApp_Study::children( const QString& entry, QStringList& child_entries ) const
663 _PTR(SObject) SO = studyDS()->FindObjectID( entry.toStdString() );
664 _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( SO ) );
665 anIter->InitEx( true );
666 while( anIter->More() )
668 _PTR(SObject) val( anIter->Value() );
669 child_entries.append( val->GetID().c_str() );
675 Fills list with components names
676 \param comp - list to be filled
678 void SalomeApp_Study::components( QStringList& comps ) const
680 for( _PTR(SComponentIterator) it ( studyDS()->NewComponentIterator() ); it->More(); it->Next() )
682 _PTR(SComponent) aComponent ( it->Value() );
683 if( aComponent && aComponent->ComponentDataType() == "Interface Applicative" )
684 continue; // skip the magic "Interface Applicative" component
685 comps.append( aComponent->ComponentDataType().c_str() );
690 \return a list of saved points' IDs
692 std::vector<int> SalomeApp_Study::getSavePoints()
696 _PTR(SObject) so = studyDS()->FindComponent("Interface Applicative");
699 _PTR(StudyBuilder) builder = studyDS()->NewBuilder();
700 _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( so ) );
701 for(; anIter->More(); anIter->Next())
703 _PTR(SObject) val( anIter->Value() );
704 _PTR(GenericAttribute) genAttr;
705 if(builder->FindAttribute(val, genAttr, "AttributeParameter")) v.push_back(val->Tag());
712 Removes a given save point
714 void SalomeApp_Study::removeSavePoint(int savePoint)
716 if(savePoint <= 0) return;
717 _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
718 _PTR(SObject) so = AP->GetSObject();
719 _PTR(StudyBuilder) builder = studyDS()->NewBuilder();
720 builder->RemoveObjectWithChildren(so);
724 \return a name of save point
726 QString SalomeApp_Study::getNameOfSavePoint(int savePoint)
728 _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
729 _PTR(IParameters) ip = ClientFactory::getIParameters(AP);
730 return ip->getProperty("AP_SAVEPOINT_NAME").c_str();
734 Sets a name of save point
736 void SalomeApp_Study::setNameOfSavePoint(int savePoint, const QString& nameOfSavePoint)
738 _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
739 _PTR(IParameters) ip = ClientFactory::getIParameters(AP);
740 ip->setProperty("AP_SAVEPOINT_NAME", nameOfSavePoint.toStdString());
744 \return a name of the component where visual parameters are stored
746 std::string SalomeApp_Study::getVisualComponentName()
748 return "Interface Applicative";
752 * \brief Restores the study state
754 void SalomeApp_Study::restoreState(int savePoint)
756 SalomeApp_VisualState((SalomeApp_Application*)application()).restoreState(savePoint);
761 Slot: called on change of a root of a data model. Redefined from CAM_Study
763 void SalomeApp_Study::updateModelRoot( const CAM_DataModel* dm )
765 LightApp_Study::updateModelRoot( dm );
767 // calling updateSavePointDataObjects in order to set correct order of "Gui states" object
768 // it must always be the last one.
769 ((SalomeApp_Application*)application())->updateSavePointDataObjects( this );