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/ or email : webmaster.salome@opencascade.com
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"
26 #include "SalomeApp_VisualState.h"
28 #include "LightApp_RootObject.h"
30 #include <OB_Browser.h>
32 #include <SUIT_ResourceMgr.h>
35 #include <qapplication.h>
38 #include "utilities.h"
43 #include <SUIT_Session.h>
45 #include "SALOMEDS_Tool.hxx"
47 #include "SALOMEDSClient_ClientFactory.hxx"
48 #include "SALOMEDSClient_IParameters.hxx"
50 #include <SALOMEconfig.h>
51 #include CORBA_SERVER_HEADER(SALOME_Exception)
58 SalomeApp_Study::SalomeApp_Study( SUIT_Application* app )
59 : LightApp_Study( app )
66 SalomeApp_Study::~SalomeApp_Study()
73 int SalomeApp_Study::id() const
77 id = studyDS()->StudyId();
84 _PTR(Study) SalomeApp_Study::studyDS() const
92 void SalomeApp_Study::createDocument()
94 MESSAGE( "openDocument" );
96 // initialize myStudyDS, read HDF file
97 QString aName = newStudyName();
98 _PTR(Study) study ( SalomeApp_Application::studyMgr()->NewStudy( aName.latin1() ) );
103 setStudyName( aName );
106 setRoot( new LightApp_RootObject( this ) );
108 CAM_Study::createDocument();
109 emit created( this );
114 \param theFileName - name of file
116 bool SalomeApp_Study::openDocument( const QString& theFileName )
118 MESSAGE( "openDocument" );
120 // initialize myStudyDS, read HDF file
121 _PTR(Study) study ( SalomeApp_Application::studyMgr()->Open( (char*) theFileName.latin1() ) );
127 setRoot( new LightApp_RootObject( this ) ); // create myRoot
129 // update loaded data models: call open() and update() on them.
132 for ( ModelListIterator it( dm_s ); it.current(); ++it )
133 openDataModel( studyName(), it.current() );
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 );
140 bool res = CAM_Study::openDocument( theFileName );
143 study->IsSaved(true);
145 bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
147 std::vector<int> savePoints = getSavePoints();
148 if ( savePoints.size() > 0 )
149 SalomeApp_VisualState( (SalomeApp_Application*)application() ).restoreState( savePoints[savePoints.size()-1] );
156 Connects GUI study to SALOMEDS one already loaded into StudyManager
157 \param theStudyName - name of study
159 bool SalomeApp_Study::loadDocument( const QString& theStudyName )
161 MESSAGE( "loadDocument" );
163 // obtain myStudyDS from StudyManager
164 _PTR(Study) study ( SalomeApp_Application::studyMgr()->GetStudyByName( (char*) theStudyName.latin1() ) );
170 setRoot( new LightApp_RootObject( this ) ); // create myRoot
172 //SRN: BugID IPAL9021, put there the same code as in a method openDocument
174 // update loaded data models: call open() and update() on them.
178 for ( ModelListIterator it( dm_s ); it.current(); ++it )
179 openDataModel( studyName(), it.current() );
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 );
186 bool res = CAM_Study::openDocument( theStudyName );
189 bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
191 std::vector<int> savePoints = getSavePoints();
192 if ( savePoints.size() > 0 )
193 SalomeApp_VisualState( (SalomeApp_Application*)application() ).restoreState( savePoints[savePoints.size()-1] );
196 //SRN: BugID IPAL9021: End
203 \param theFileName - name of file
205 bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
207 bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", false );
209 SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
211 ModelList list; dataModels( list );
213 SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
214 QStringList listOfFiles;
215 for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
217 aModel->saveAs( theFileName, this, listOfFiles );
218 if ( !listOfFiles.isEmpty() )
219 saveModuleData(aModel->module()->name(), listOfFiles);
222 // save SALOMEDS document
223 SUIT_ResourceMgr* resMgr = application()->resourceMgr();
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 );
234 res = res && saveStudyData(theFileName);
243 Saves previously opened document
245 bool SalomeApp_Study::saveDocument()
247 bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
249 SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
251 ModelList list; dataModels( list );
253 SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
254 QStringList listOfFiles;
255 for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
257 aModel->save(listOfFiles);
258 if ( !listOfFiles.isEmpty() )
259 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).latin1();
352 SetListOfFiles(theModuleName, 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 );
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 SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
382 std::vector<std::string> listOfFiles(0);
383 for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() )
384 SetListOfFiles(aModel->module()->name(), listOfFiles);
391 bool SalomeApp_Study::openStudyData( const QString& theFileName )
399 void SalomeApp_Study::setStudyDS( const _PTR(Study)& s )
407 void SalomeApp_Study::dataModelInserted (const CAM_DataModel* dm)
409 MESSAGE("SalomeApp_Study::dataModelInserted() : module name() = " << dm->module()->name());
411 CAM_Study::dataModelInserted(dm);
417 Create SComponent for module, using default engine (CORBAless)
419 void SalomeApp_Study::addComponent(const CAM_DataModel* dm)
421 SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
422 // 1. aModule == 0 means that this is a light module (no CORBA enigine)
424 // Check SComponent existance
425 _PTR(Study) aStudy = studyDS();
428 _PTR(SComponent) aComp = aStudy->FindComponent(dm->module()->name());
431 _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
432 aComp = aBuilder->NewComponent(dm->module()->name());
433 aBuilder->SetName(aComp, dm->module()->moduleName().latin1());
434 QString anIconName = dm->module()->iconName();
435 if (!anIconName.isEmpty()) {
436 _PTR(AttributePixMap) anAttr = aBuilder->FindOrCreateAttribute(aComp, "AttributePixMap");
438 anAttr->SetPixMap(anIconName.latin1());
440 // Set default engine IOR
441 aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().latin1());
442 //SalomeApp_DataModel::BuildTree( aComp, root(), this, /*skipExisitng=*/true );
443 SalomeApp_DataModel::synchronize( aComp, this );
451 bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm )
456 // SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm);
457 SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
458 _PTR(Study) aStudy = studyDS(); // shared_ptr cannot be used here
459 _PTR(SComponent) aSComp;
461 // 1. aModule == 0 means that this is a light module (no CORBA enigine)
463 anEngine = SalomeApp_Application::defaultEngineIOR();
464 aSComp = aStudy->FindComponent(dm->module()->name());
467 SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
469 QString anId = aDM->getRootEntry( this );
470 if ( anId.isEmpty() )
471 return true; // Probably nothing to load
472 anEngine = aDM->getModule()->engineIOR();
473 if ( anEngine.isEmpty() )
475 aSComp = aStudy->FindComponentID( std::string( anId.latin1() ) );
479 _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() );
482 aBuilder->LoadWith( aSComp, std::string( anEngine.latin1() ) );
484 catch( const SALOME::SALOME_Exception& ) {
485 // Oops, something went wrong while loading -> return an error
488 // Something has been read -> create data model tree
489 //SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
490 // aDM->buildTree( aSComp, 0, this );
493 // Don't return false here, for there might be no data
494 // for a given component in the study yet
496 QStringList listOfFiles;
497 openModuleData(dm->module()->name(), listOfFiles);
498 if (dm && dm->open(studyName, this, listOfFiles)) {
499 // Remove the files and temporary directory, created
500 // for this module by LightApp_Engine_i::Load()
501 bool isMultiFile = false; // TODO: decide, how to access this parameter
502 RemoveTemporaryFiles( dm->module()->name(), isMultiFile );
504 // Something has been read -> create data model tree
505 LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>( dm );
507 aDM->update(NULL, this);
514 Create new study name.
516 QString SalomeApp_Study::newStudyName() const
518 std::vector<std::string> studies = SalomeApp_Application::studyMgr()->GetOpenStudies();
519 QString prefix( "Study%1" ), newName, curName;
520 int i = 1, j, n = studies.size();
521 while ( newName.isEmpty() ){
522 curName = prefix.arg( i );
523 for ( j = 0 ; j < n; j++ ){
524 if ( !strcmp( studies[j].c_str(), curName.latin1() ) )
536 \return list of files used by module: to be used by CORBAless modules
537 \param theModuleName - name of module
539 std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleName ) const
541 SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
543 return aDefaultEngine->GetListOfFiles(id(), theModuleName);
545 std::vector<std::string> aListOfFiles;
550 Sets list of files used by module: to be used by CORBAless modules
551 \param theModuleName - name of module
552 \param theListOfFiles - list of files
554 void SalomeApp_Study::SetListOfFiles ( const char* theModuleName,
555 const std::vector<std::string> theListOfFiles )
557 SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
559 aDefaultEngine->SetListOfFiles(theListOfFiles, id(), theModuleName);
563 \return temporary directory for saving files of modules
565 std::string SalomeApp_Study::GetTmpDir ( const char* theURL, const bool isMultiFile )
567 std::string anURLDir = SALOMEDS_Tool::GetDirFromPath(theURL);
568 std::string aTmpDir = isMultiFile ? anURLDir : SALOMEDS_Tool::GetTmpDir();
573 Removes temporary files
575 void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bool isMultiFile ) const
580 std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName );
581 if (aListOfFiles.size() > 0) {
582 std::string aTmpDir = aListOfFiles[0];
584 const int n = aListOfFiles.size() - 1;
585 SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
587 for (int i = 0; i < n; i++)
588 aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str());
590 SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
595 Deletes all references to object
598 void SalomeApp_Study::deleteReferencesTo( _PTR( SObject ) obj )
600 _PTR(StudyBuilder) sb = studyDS()->NewBuilder();
601 std::vector<_PTR(SObject)> aRefs = studyDS()->FindDependances( obj );
602 for( int i=0, n=aRefs.size(); i<n; i++ )
604 _PTR( SObject ) o = aRefs[i];
605 if( o->GetFatherComponent()->ComponentDataType()==obj->GetFatherComponent()->ComponentDataType() )
607 sb->RemoveReference( o );
608 sb->RemoveObjectWithChildren( o );
614 \return real entry by entry of reference
615 \param entry - entry of reference object
617 QString SalomeApp_Study::referencedToEntry( const QString& entry ) const
619 _PTR(SObject) obj = studyDS()->FindObjectID( entry.latin1() );
620 _PTR(SObject) refobj;
622 if( obj && obj->ReferencedObject( refobj ) )
623 return refobj->GetID().c_str();
624 return LightApp_Study::referencedToEntry( entry );
628 \return component data type for entry
630 QString SalomeApp_Study::componentDataType( const QString& entry ) const
632 _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) );
634 return LightApp_Study::componentDataType( entry );
635 return obj->GetFatherComponent()->ComponentDataType().c_str();
639 \return true if entry corresponds to component
641 bool SalomeApp_Study::isComponent( const QString& entry ) const
643 _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) );
644 return obj && QString( obj->GetID().c_str() ) == obj->GetFatherComponent()->GetID().c_str();
648 \return entries of object children
650 void SalomeApp_Study::children( const QString& entry, QStringList& child_entries ) const
652 _PTR(SObject) SO = studyDS()->FindObjectID( entry.latin1() );
653 _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( SO ) );
654 anIter->InitEx( true );
655 while( anIter->More() )
657 _PTR(SObject) val( anIter->Value() );
658 child_entries.append( val->GetID().c_str() );
664 Fills list with components names
665 \param comp - list to be filled
667 void SalomeApp_Study::components( QStringList& comps ) const
669 for( _PTR(SComponentIterator) it ( studyDS()->NewComponentIterator() ); it->More(); it->Next() )
671 _PTR(SComponent) aComponent ( it->Value() );
672 if( aComponent && aComponent->ComponentDataType() == "Interface Applicative" )
673 continue; // skip the magic "Interface Applicative" component
674 comps.append( aComponent->ComponentDataType().c_str() );
679 \return a list of saved points' IDs
681 std::vector<int> SalomeApp_Study::getSavePoints()
685 _PTR(SObject) so = studyDS()->FindComponent("Interface Applicative");
688 _PTR(StudyBuilder) builder = studyDS()->NewBuilder();
689 _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( so ) );
690 for(; anIter->More(); anIter->Next())
692 _PTR(SObject) val( anIter->Value() );
693 _PTR(GenericAttribute) genAttr;
694 if(builder->FindAttribute(val, genAttr, "AttributeParameter")) v.push_back(val->Tag());
701 Removes a given save point
703 void SalomeApp_Study::removeSavePoint(int savePoint)
705 if(savePoint <= 0) return;
706 _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
707 _PTR(SObject) so = AP->GetSObject();
708 _PTR(StudyBuilder) builder = studyDS()->NewBuilder();
709 builder->RemoveObjectWithChildren(so);
713 \return a name of save point
715 QString SalomeApp_Study::getNameOfSavePoint(int savePoint)
717 _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
718 _PTR(IParameters) ip = ClientFactory::getIParameters(AP);
719 return ip->getProperty("AP_SAVEPOINT_NAME").c_str();
723 Sets a name of save point
725 void SalomeApp_Study::setNameOfSavePoint(int savePoint, const QString& nameOfSavePoint)
727 _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
728 _PTR(IParameters) ip = ClientFactory::getIParameters(AP);
729 ip->setProperty("AP_SAVEPOINT_NAME", nameOfSavePoint.latin1());
733 \return a name of the component where visual parameters are stored
735 std::string SalomeApp_Study::getVisualComponentName()
737 return "Interface Applicative";
741 * \brief Restores the study state
743 void SalomeApp_Study::restoreState(int savePoint)
745 SalomeApp_VisualState((SalomeApp_Application*)application()).restoreState(savePoint);
750 Slot: called on change of a root of a data model. Redefined from CAM_Study
752 void SalomeApp_Study::updateModelRoot( const CAM_DataModel* dm )
754 LightApp_Study::updateModelRoot( dm );
756 // calling updateSavePointDataObjects in order to set correct order of "Gui states" object
757 // it must always be the last one.
758 ((SalomeApp_Application*)application())->updateSavePointDataObjects( this );