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"
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 "SALOMEDS_IParameters.hxx"
49 #include <SALOMEconfig.h>
50 #include CORBA_SERVER_HEADER(SALOME_Exception)
57 SalomeApp_Study::SalomeApp_Study( SUIT_Application* app )
58 : LightApp_Study( app )
65 SalomeApp_Study::~SalomeApp_Study()
72 int SalomeApp_Study::id() const
76 id = studyDS()->StudyId();
83 _PTR(Study) SalomeApp_Study::studyDS() const
91 void SalomeApp_Study::createDocument()
93 MESSAGE( "openDocument" );
95 // initialize myStudyDS, read HDF file
96 QString aName = newStudyName();
97 _PTR(Study) study ( SalomeApp_Application::studyMgr()->NewStudy( aName.latin1() ) );
102 setStudyName( aName );
105 setRoot( new LightApp_RootObject( this ) );
107 CAM_Study::createDocument();
108 emit created( this );
111 //=======================================================================
112 // name : openDocument
113 /*! Purpose : Open document*/
114 //=======================================================================
115 bool SalomeApp_Study::openDocument( const QString& theFileName )
117 MESSAGE( "openDocument" );
119 // initialize myStudyDS, read HDF file
120 _PTR(Study) study ( SalomeApp_Application::studyMgr()->Open( (char*) theFileName.latin1() ) );
126 setRoot( new LightApp_RootObject( this ) ); // create myRoot
128 // update loaded data models: call open() and update() on them.
131 for ( ModelListIterator it( dm_s ); it.current(); ++it )
132 openDataModel( studyName(), it.current() );
134 // this will build a SUIT_DataObject-s tree under myRoot member field
135 // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
136 // but tree that corresponds to not-loaded data models will be updated any way.
137 ((SalomeApp_Application*)application())->updateObjectBrowser( false );
139 bool res = CAM_Study::openDocument( theFileName );
142 study->IsSaved(true);
144 bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
146 std::vector<int> savePoints = getSavePoints();
147 if ( savePoints.size() > 0 )
148 SalomeApp_VisualState( (SalomeApp_Application*)application() ).restoreState( savePoints[savePoints.size()-1] );
154 //=======================================================================
155 // name : loadDocument
156 /*! Purpose : Connects GUI study to SALOMEDS one already loaded into StudyManager*/
157 //=======================================================================
158 bool SalomeApp_Study::loadDocument( const QString& theStudyName )
160 MESSAGE( "loadDocument" );
162 // obtain myStudyDS from StudyManager
163 _PTR(Study) study ( SalomeApp_Application::studyMgr()->GetStudyByName( (char*) theStudyName.latin1() ) );
169 setRoot( new LightApp_RootObject( this ) ); // create myRoot
171 //SRN: BugID IPAL9021, put there the same code as in a method openDocument
173 // update loaded data models: call open() and update() on them.
177 for ( ModelListIterator it( dm_s ); it.current(); ++it )
178 openDataModel( studyName(), it.current() );
180 // this will build a SUIT_DataObject-s tree under myRoot member field
181 // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
182 // but tree that corresponds to not-loaded data models will be updated any way.
183 ((SalomeApp_Application*)application())->updateObjectBrowser( false );
185 bool res = CAM_Study::openDocument( theStudyName );
188 bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
190 std::vector<int> savePoints = getSavePoints();
191 if ( savePoints.size() > 0 )
192 SalomeApp_VisualState( (SalomeApp_Application*)application() ).restoreState( savePoints[savePoints.size()-1] );
195 //SRN: BugID IPAL9021: End
200 //=======================================================================
201 // name : saveDocumentAs
202 /*! Purpose : Save document*/
203 //=======================================================================
204 bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
206 bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
208 SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
210 ModelList list; dataModels( list );
212 SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
213 QStringList listOfFiles;
214 for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
216 aModel->saveAs( theFileName, this, listOfFiles );
217 if ( !listOfFiles.isEmpty() )
218 saveModuleData(aModel->module()->name(), listOfFiles);
221 // save SALOMEDS document
222 SUIT_ResourceMgr* resMgr = application()->resourceMgr();
226 bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ),
227 isAscii = resMgr->booleanValue( "Study", "ascii_file", false ),
229 SalomeApp_Application::studyMgr()->SaveAsASCII( theFileName.latin1(), studyDS(), isMultiFile ) :
230 SalomeApp_Application::studyMgr()->SaveAs ( theFileName.latin1(), studyDS(), isMultiFile ) &&
231 CAM_Study::saveDocumentAs( theFileName ) && //SRN: BugID IPAL9377, removed usage of uninitialized variable <res>
232 saveStudyData(theFileName);
240 //=======================================================================
241 // name : saveDocument
242 /*! Purpose : Save document*/
243 //=======================================================================
244 bool SalomeApp_Study::saveDocument()
246 bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
248 SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
250 ModelList list; dataModels( list );
252 SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
253 QStringList listOfFiles;
254 for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
256 aModel->save(listOfFiles);
257 if ( !listOfFiles.isEmpty() )
258 saveModuleData(aModel->module()->name(), listOfFiles);
261 // save SALOMEDS document
262 SUIT_ResourceMgr* resMgr = application()->resourceMgr();
266 bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ),
267 isAscii = resMgr->booleanValue( "Study", "ascii_file", false ),
269 SalomeApp_Application::studyMgr()->SaveASCII( studyDS(), isMultiFile ) :
270 SalomeApp_Application::studyMgr()->Save ( studyDS(), isMultiFile ) && CAM_Study::saveDocument();
272 res = res && saveStudyData(studyName());
279 //================================================================
280 // Function : closeDocument
281 /*! Purpose : Close document*/
282 //================================================================
283 void SalomeApp_Study::closeDocument(bool permanently)
285 LightApp_Study::closeDocument(permanently);
287 // close SALOMEDS document
288 _PTR(Study) studyPtr = studyDS();
291 if(permanently) SalomeApp_Application::studyMgr()->Close( studyPtr );
292 SALOMEDSClient_Study* aStudy = 0;
293 setStudyDS( _PTR(Study)(aStudy) );
297 //================================================================
298 // Function : isModified
300 //================================================================
301 bool SalomeApp_Study::isModified() const
303 bool isAnyChanged = studyDS() && studyDS()->IsModified();
305 isAnyChanged = LightApp_Study::isModified();
310 //================================================================
311 // Function : isSaved
312 /*! Purpose : Check: data model is saved?*/
313 //================================================================
314 bool SalomeApp_Study::isSaved() const
316 bool isAllSaved = studyDS() && studyDS()->GetPersistentReference().size();
318 isAllSaved = LightApp_Study::isModified();
323 //=======================================================================
324 // name : saveModuleData
325 /*! Purpose : save list file for module 'theModuleName' */
326 //=======================================================================
327 void SalomeApp_Study::saveModuleData( QString theModuleName, QStringList theListOfFiles )
329 int aNb = theListOfFiles.count();
333 std::vector<std::string> aListOfFiles ( aNb );
335 for ( QStringList::Iterator it = theListOfFiles.begin(); it != theListOfFiles.end(); ++it ) {
336 if ( (*it).isEmpty() )
338 aListOfFiles[anIndex] = (*it).latin1();
341 SetListOfFiles(theModuleName, aListOfFiles);
344 //=======================================================================
345 // name : openModuleData
346 /*! Purpose : gets list of file for module 'theModuleNam' */
347 //=======================================================================
348 void SalomeApp_Study::openModuleData( QString theModuleName, QStringList& theListOfFiles )
350 std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName );
352 int i, aLength = aListOfFiles.size() - 1;
356 //Get a temporary directory for saved a file
357 theListOfFiles.append(aListOfFiles[0].c_str());
359 for(i = 0; i < aLength; i++)
360 theListOfFiles.append(aListOfFiles[i+1].c_str());
363 //=======================================================================
364 // name : saveStudyData
365 /*! Purpose : save data from study */
366 //=======================================================================
367 bool SalomeApp_Study::saveStudyData( const QString& theFileName )
369 ModelList list; dataModels( list );
370 SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
371 std::vector<std::string> listOfFiles(0);
372 for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() )
373 SetListOfFiles(aModel->module()->name(), listOfFiles);
377 //=======================================================================
378 // name : openStudyData
379 /*! Purpose : open data for study */
380 //=======================================================================
381 bool SalomeApp_Study::openStudyData( const QString& theFileName )
389 void SalomeApp_Study::setStudyDS( const _PTR(Study)& s )
397 void SalomeApp_Study::dataModelInserted (const CAM_DataModel* dm)
399 MESSAGE("SalomeApp_Study::dataModelInserted() : module name() = " << dm->module()->name());
401 CAM_Study::dataModelInserted(dm);
407 Create SComponent for module, using default engine (CORBAless)
409 void SalomeApp_Study::addComponent(const CAM_DataModel* dm)
411 SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
412 // 1. aModule == 0 means that this is a light module (no CORBA enigine)
414 // Check SComponent existance
415 _PTR(Study) aStudy = studyDS();
418 _PTR(SComponent) aComp = aStudy->FindComponent(dm->module()->name());
421 _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
422 aComp = aBuilder->NewComponent(dm->module()->name());
423 aBuilder->SetName(aComp, dm->module()->moduleName().latin1());
424 QString anIconName = dm->module()->iconName();
425 if (!anIconName.isEmpty()) {
426 _PTR(AttributePixMap) anAttr = aBuilder->FindOrCreateAttribute(aComp, "AttributePixMap");
428 anAttr->SetPixMap(anIconName.latin1());
430 // Set default engine IOR
431 aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().latin1());
432 //SalomeApp_DataModel::BuildTree( aComp, root(), this, /*skipExisitng=*/true );
433 SalomeApp_DataModel::synchronize( aComp, this );
441 bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm )
446 // SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm);
447 SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
448 _PTR(Study) aStudy = studyDS(); // shared_ptr cannot be used here
449 _PTR(SComponent) aSComp;
451 // 1. aModule == 0 means that this is a light module (no CORBA enigine)
453 anEngine = SalomeApp_Application::defaultEngineIOR();
454 aSComp = aStudy->FindComponent(dm->module()->name());
457 SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
459 QString anId = aDM->getRootEntry( this );
460 if ( anId.isEmpty() )
461 return true; // Probably nothing to load
462 anEngine = aDM->getModule()->engineIOR();
463 if ( anEngine.isEmpty() )
465 aSComp = aStudy->FindComponentID( std::string( anId.latin1() ) );
469 _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() );
472 aBuilder->LoadWith( aSComp, std::string( anEngine.latin1() ) );
474 catch( const SALOME::SALOME_Exception& ) {
475 // Oops, something went wrong while loading -> return an error
478 // Something has been read -> create data model tree
479 //SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
480 // aDM->buildTree( aSComp, 0, this );
483 // Don't return false here, for there might be no data
484 // for a given component in the study yet
486 QStringList listOfFiles;
487 openModuleData(dm->module()->name(), listOfFiles);
488 if (dm && dm->open(studyName, this, listOfFiles)) {
489 // Remove the files and temporary directory, created
490 // for this module by LightApp_Engine_i::Load()
491 bool isMultiFile = false; // TODO: decide, how to access this parameter
492 RemoveTemporaryFiles( dm->module()->name(), isMultiFile );
494 // Something has been read -> create data model tree
495 LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>( dm );
497 aDM->update(NULL, this);
504 Create new study name.
506 QString SalomeApp_Study::newStudyName() const
508 std::vector<std::string> studies = SalomeApp_Application::studyMgr()->GetOpenStudies();
509 QString prefix( "Study%1" ), newName, curName;
510 int i = 1, j, n = studies.size();
511 while ( newName.isEmpty() ){
512 curName = prefix.arg( i );
513 for ( j = 0 ; j < n; j++ ){
514 if ( !strcmp( studies[j].c_str(), curName.latin1() ) )
525 //================================================================
526 // Function : GetListOfFiles
527 /*! Purpose : to be used by CORBAless modules*/
528 //================================================================
529 std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleName ) const
531 SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
533 return aDefaultEngine->GetListOfFiles(id(), theModuleName);
535 std::vector<std::string> aListOfFiles;
539 //================================================================
540 // Function : SetListOfFiles
541 /*! Purpose : to be used by CORBAless modules*/
542 //================================================================
543 void SalomeApp_Study::SetListOfFiles ( const char* theModuleName,
544 const std::vector<std::string> theListOfFiles )
546 SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
548 aDefaultEngine->SetListOfFiles(theListOfFiles, id(), theModuleName);
551 //================================================================
552 // Function : GetTmpDir
553 /*! Purpose : to be used by CORBAless modules*/
554 //================================================================
555 std::string SalomeApp_Study::GetTmpDir ( const char* theURL, const bool isMultiFile )
557 std::string anURLDir = SALOMEDS_Tool::GetDirFromPath(theURL);
558 std::string aTmpDir = isMultiFile ? anURLDir : SALOMEDS_Tool::GetTmpDir();
562 //================================================================
563 // Function : RemoveTemporaryFiles
564 /*! Purpose : to be used by CORBAless modules*/
565 //================================================================
566 void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bool isMultiFile ) const
571 std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName );
572 if (aListOfFiles.size() > 0) {
573 std::string aTmpDir = aListOfFiles[0];
575 const int n = aListOfFiles.size() - 1;
576 SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
578 for (int i = 0; i < n; i++)
579 aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str());
581 SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
585 // END: methods to be used by CORBAless modules
587 void SalomeApp_Study::deleteReferencesTo( _PTR( SObject ) obj )
589 _PTR(StudyBuilder) sb = studyDS()->NewBuilder();
590 std::vector<_PTR(SObject)> aRefs = studyDS()->FindDependances( obj );
591 for( int i=0, n=aRefs.size(); i<n; i++ )
593 _PTR( SObject ) o = aRefs[i];
594 if( o->GetFatherComponent()->ComponentDataType()==obj->GetFatherComponent()->ComponentDataType() )
596 sb->RemoveReference( o );
597 sb->RemoveObjectWithChildren( o );
602 //================================================================
603 // Function : referencedToEntry
604 /*! Purpose : Return referenced entry from entry*/
605 //================================================================
606 QString SalomeApp_Study::referencedToEntry( const QString& entry ) const
608 _PTR(SObject) obj = studyDS()->FindObjectID( entry.latin1() );
609 _PTR(SObject) refobj;
611 if( obj && obj->ReferencedObject( refobj ) )
612 return refobj->GetID().c_str();
613 return LightApp_Study::referencedToEntry( entry );
616 //================================================================
617 // Function : componentDataType
618 /*! Purpose : Return component data type from entry*/
619 //================================================================
620 QString SalomeApp_Study::componentDataType( const QString& entry ) const
622 _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) );
624 return LightApp_Study::componentDataType( entry );
625 return obj->GetFatherComponent()->ComponentDataType().c_str();
628 //================================================================
629 // Function : componentDataType
630 /*! Purpose : Return component data type from entry*/
631 //================================================================
632 bool SalomeApp_Study::isComponent( const QString& entry ) const
634 _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) );
635 return obj && QString( obj->GetID().c_str() ) == obj->GetFatherComponent()->GetID().c_str();
638 //================================================================
639 // Function : children
640 /*! Purpose : Return entries of children of object*/
641 //================================================================
642 void SalomeApp_Study::children( const QString& entry, QStringList& child_entries ) const
644 _PTR(SObject) SO = studyDS()->FindObjectID( entry.latin1() );
645 _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( SO ) );
646 anIter->InitEx( true );
647 while( anIter->More() )
649 _PTR(SObject) val( anIter->Value() );
650 child_entries.append( val->GetID().c_str() );
655 void SalomeApp_Study::components( QStringList& comps ) const
657 for( _PTR(SComponentIterator) it ( studyDS()->NewComponentIterator() ); it->More(); it->Next() )
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() );
666 //================================================================
667 // Function : getSavePoints
668 /*! Purpose : returns a list of saved points' IDs
670 //================================================================
671 std::vector<int> SalomeApp_Study::getSavePoints()
675 _PTR(SObject) so = studyDS()->FindComponent("Interface Applicative");
678 _PTR(StudyBuilder) builder = studyDS()->NewBuilder();
679 _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( so ) );
680 for(; anIter->More(); anIter->Next())
682 _PTR(SObject) val( anIter->Value() );
683 _PTR(GenericAttribute) genAttr;
684 if(builder->FindAttribute(val, genAttr, "AttributeParameter")) v.push_back(val->Tag());
690 //================================================================
691 // Function :removeSavePoint
692 /*! Purpose : remove a given save point
694 //================================================================
695 void SalomeApp_Study::removeSavePoint(int savePoint)
697 if(savePoint <= 0) return;
698 _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
699 _PTR(SObject) so = AP->GetSObject();
700 _PTR(StudyBuilder) builder = studyDS()->NewBuilder();
701 builder->RemoveObjectWithChildren(so);
704 //================================================================
705 // Function : getNameOfSavePoint
706 /*! Purpose : returns a name of save point
708 //================================================================
709 QString SalomeApp_Study::getNameOfSavePoint(int savePoint)
711 _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
712 SALOMEDS_IParameters ip(AP);
713 return ip.getProperty("AP_SAVEPOINT_NAME").c_str();
716 //================================================================
717 // Function : setNameOfSavePoint
718 /*! Purpose : sets a name of save point
720 //================================================================
721 void SalomeApp_Study::setNameOfSavePoint(int savePoint, const QString& nameOfSavePoint)
723 _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
724 SALOMEDS_IParameters ip(AP);
725 ip.setProperty("AP_SAVEPOINT_NAME", nameOfSavePoint.latin1());
728 //================================================================
729 // Function : getVisualComponentName
730 /*! Purpose : returns a name of the component where visual
731 * parameters are stored
733 //================================================================
734 std::string SalomeApp_Study::getVisualComponentName()
736 return "Interface Applicative";
739 //================================================================
740 // Function : updateModelRoot
741 /*! Purpose : slot called on change of a root of a data model. redefined from CAM_Study*/
742 //================================================================
743 void SalomeApp_Study::updateModelRoot( const CAM_DataModel* dm )
745 LightApp_Study::updateModelRoot( dm );
747 // calling updateSavePointDataObjects in order to set correct order of "Gui states" object
748 // it must always be the last one.
749 ((SalomeApp_Application*)application())->updateSavePointDataObjects( this );