X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSalomeApp%2FSalomeApp_Study.cxx;h=98b68ca27ec5402ab1345da10456d6f1ef336fb4;hb=1292b3367a82e807454410dea4b7853de69929c5;hp=af63f686c032a4b563f2be7cafa3040a856c4594;hpb=988355d23d6e121539539cef28f90f9086cdde9e;p=modules%2Fgui.git diff --git a/src/SalomeApp/SalomeApp_Study.cxx b/src/SalomeApp/SalomeApp_Study.cxx index af63f686c..98b68ca27 100644 --- a/src/SalomeApp/SalomeApp_Study.cxx +++ b/src/SalomeApp/SalomeApp_Study.cxx @@ -2,25 +2,45 @@ #include "SalomeApp_Module.h" #include "SalomeApp_DataModel.h" -#include "SalomeApp_RootObject.h" #include "SalomeApp_DataObject.h" #include "SalomeApp_Application.h" +#include "SalomeApp_Engine_i.hxx" + +#include "LightApp_RootObject.h" #include #include +#include + #include "utilities.h" +#include "string.h" +#include "vector.h" + +#include "SALOMEDS_Tool.hxx" +#include +#include CORBA_SERVER_HEADER(SALOME_Exception) + +/*! + Constructor. +*/ SalomeApp_Study::SalomeApp_Study( SUIT_Application* app ) -: CAM_Study( app ) +: LightApp_Study( app ) { } +/*! + Destructor. +*/ SalomeApp_Study::~SalomeApp_Study() { } +/*! + Gets study id. +*/ int SalomeApp_Study::id() const { int id = -1; @@ -29,11 +49,17 @@ int SalomeApp_Study::id() const return id; } +/*! + Gets studyDS pointer. +*/ _PTR(Study) SalomeApp_Study::studyDS() const { return myStudyDS; } +/*! + Create document. +*/ void SalomeApp_Study::createDocument() { MESSAGE( "openDocument" ); @@ -48,16 +74,15 @@ void SalomeApp_Study::createDocument() setStudyName( aName ); // create myRoot - setRoot( new SalomeApp_RootObject( this ) ); + setRoot( new LightApp_RootObject( this ) ); CAM_Study::createDocument(); - emit created( this ); } //======================================================================= // name : openDocument -// Purpose : Open document +/*! Purpose : Open document*/ //======================================================================= bool SalomeApp_Study::openDocument( const QString& theFileName ) { @@ -70,32 +95,29 @@ bool SalomeApp_Study::openDocument( const QString& theFileName ) setStudyDS( study ); - // build a SUIT_DataObject-s tree under myRoot member field - // 1. create myRoot - setRoot( new SalomeApp_RootObject( this ) ); - // 2. iterate through all components and create corresponding sub-trees under them - _PTR(SComponentIterator) it ( studyDS()->NewComponentIterator() ); - for ( ; it->More(); it->Next() ) { - // don't use shared_ptr here, for Data Object will take - // ownership of this pointer - _PTR(SComponent) aComponent ( it->Value() ); - - if ( aComponent->ComponentDataType() == "Interface Applicative" ) - continue; // skip the magic "Interface Applicative" component - - SalomeApp_DataModel::BuildTree( aComponent, root(), this ); - } + setRoot( new LightApp_RootObject( this ) ); // create myRoot - bool res = CAM_Study::openDocument( theFileName ); + // update loaded data models: call open() and update() on them. + ModelList dm_s; + dataModels( dm_s ); + for ( ModelListIterator it( dm_s ); it.current(); ++it ) + openDataModel( studyName(), it.current() ); - emit opened( this ); + // this will build a SUIT_DataObject-s tree under myRoot member field + // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step + // but tree that corresponds to not-loaded data models will be updated any way. + ((SalomeApp_Application*)application())->updateObjectBrowser( false ); + bool res = CAM_Study::openDocument( theFileName ); + + emit opened( this ); + study->IsSaved(true); return res; } //======================================================================= // name : loadDocument -// Purpose : Connects GUI study to SALOMEDS one already loaded into StudyManager +/*! Purpose : Connects GUI study to SALOMEDS one already loaded into StudyManager*/ //======================================================================= bool SalomeApp_Study::loadDocument( const QString& theStudyName ) { @@ -108,50 +130,59 @@ bool SalomeApp_Study::loadDocument( const QString& theStudyName ) setStudyDS( study ); - // build a SUIT_DataObject-s tree under myRoot member field - // 1. create myRoot - setRoot( new SalomeApp_RootObject( this ) ); - // 2. iterate through all components and create corresponding sub-trees under them - _PTR(SComponentIterator) it ( studyDS()->NewComponentIterator() ); - for ( ; it->More(); it->Next() ) { - // don't use shared_ptr here, for Data Object will take - // ownership of this pointer - _PTR(SComponent) aComponent ( it->Value() ); - - if ( aComponent->ComponentDataType() == "Interface Applicative" ) - continue; // skip the magic "Interface Applicative" component + setRoot( new LightApp_RootObject( this ) ); // create myRoot - SalomeApp_DataModel::BuildTree( aComponent, root(), this ); - } + //SRN: BugID IPAL9021, put there the same code as in a method openDocument + + // update loaded data models: call open() and update() on them. + ModelList dm_s; + dataModels( dm_s ); + + for ( ModelListIterator it( dm_s ); it.current(); ++it ) + openDataModel( studyName(), it.current() ); + + // this will build a SUIT_DataObject-s tree under myRoot member field + // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step + // but tree that corresponds to not-loaded data models will be updated any way. + ((SalomeApp_Application*)application())->updateObjectBrowser( false ); - // TODO: potentially unsafe call, since base study's openDocument() might try to access the file directly - to be improved - //bool res = true; bool res = CAM_Study::openDocument( theStudyName ); + emit opened( this ); - //emit opened( this ); + //SRN: BugID IPAL9021: End return res; } //======================================================================= // name : saveDocumentAs -// Purpose : Save document +/*! Purpose : Save document*/ //======================================================================= bool SalomeApp_Study::saveDocumentAs( const QString& theFileName ) { ModelList list; dataModels( list ); SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first(); - for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) - aModel->saveAs( theFileName, this ); + QStringList listOfFiles; + for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) { + listOfFiles.clear(); + aModel->saveAs( theFileName, this, listOfFiles ); + if ( !listOfFiles.isEmpty() ) + saveModuleData(aModel->module()->name(), listOfFiles); + } // save SALOMEDS document - bool isMultiFile = false, isAscii = false;// TODO: This information should be taken from preferences afterwards! - /* bool res = */isAscii ? SalomeApp_Application::studyMgr()->SaveAsASCII( theFileName.latin1(), studyDS(), isMultiFile ) : - SalomeApp_Application::studyMgr()->SaveAs ( theFileName.latin1(), studyDS(), isMultiFile ); + SUIT_ResourceMgr* resMgr = application()->resourceMgr(); + if( !resMgr ) + return false; - bool res = CAM_Study::saveDocumentAs( theFileName ); //SRN: BugID IPAL9377, removed usage of uninitialized variable + bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ), + isAscii = resMgr->booleanValue( "Study", "ascii_file", true ); + isAscii ? SalomeApp_Application::studyMgr()->SaveAsASCII( theFileName.latin1(), studyDS(), isMultiFile ) : + SalomeApp_Application::studyMgr()->SaveAs ( theFileName.latin1(), studyDS(), isMultiFile ); + bool res = CAM_Study::saveDocumentAs( theFileName ); //SRN: BugID IPAL9377, removed usage of uninitialized variable + res = res && saveStudyData(theFileName); if ( res ) emit saved( this ); @@ -160,46 +191,56 @@ bool SalomeApp_Study::saveDocumentAs( const QString& theFileName ) //======================================================================= // name : saveDocument -// Purpose : Save document +/*! Purpose : Save document*/ //======================================================================= -void SalomeApp_Study::saveDocument() +bool SalomeApp_Study::saveDocument() { ModelList list; dataModels( list ); SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first(); - for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) - aModel->save(); - - CAM_Study::saveDocument(); + QStringList listOfFiles; + for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) { + listOfFiles.clear(); + aModel->save(listOfFiles); + if ( !listOfFiles.isEmpty() ) + saveModuleData(aModel->module()->name(), listOfFiles); + } // save SALOMEDS document - bool isMultiFile = false, isAscii = false;// TODO: This information should be taken from preferences afterwards! + SUIT_ResourceMgr* resMgr = application()->resourceMgr(); + if( !resMgr ) + return false; + + bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ), + isAscii = resMgr->booleanValue( "Study", "ascii_file", true ); isAscii ? SalomeApp_Application::studyMgr()->SaveASCII( studyDS(), isMultiFile ) : SalomeApp_Application::studyMgr()->Save ( studyDS(), isMultiFile ); - emit saved( this ); + bool res = CAM_Study::saveDocument(); + + res = res && saveStudyData(studyName()); + if ( res ) + emit saved( this ); + + return res; } //================================================================ // Function : closeDocument -// Purpose : +/*! Purpose : Close document*/ //================================================================ -void SalomeApp_Study::closeDocument() +void SalomeApp_Study::closeDocument(bool permanently) { - // Inform everybody that this study is going to close when it's most safe to, - // i.e. in the very beginning - emit closed( this ); + LightApp_Study::closeDocument(permanently); // close SALOMEDS document _PTR(Study) studyPtr = studyDS(); if ( studyPtr ) { - SalomeApp_Application::studyMgr()->Close( studyPtr ); + if(permanently) SalomeApp_Application::studyMgr()->Close( studyPtr ); SALOMEDSClient_Study* aStudy = 0; setStudyDS( _PTR(Study)(aStudy) ); } - - CAM_Study::closeDocument(); } //================================================================ @@ -209,86 +250,207 @@ void SalomeApp_Study::closeDocument() bool SalomeApp_Study::isModified() const { bool isAnyChanged = studyDS() && studyDS()->IsModified(); - ModelList list; dataModels( list ); + if (!isAnyChanged) + isAnyChanged = LightApp_Study::isModified(); - SalomeApp_DataModel* aModel = 0; - for ( QPtrListIterator it( list ); it.current() && !isAnyChanged; ++it ){ - aModel = dynamic_cast( it.current() ); - if ( aModel ) - isAnyChanged = aModel->isModified(); - } return isAnyChanged; } //================================================================ // Function : isSaved -// Purpose : +/*! Purpose : Check: data model is saved?*/ //================================================================ bool SalomeApp_Study::isSaved() const { bool isAllSaved = studyDS() && studyDS()->GetPersistentReference().size(); - ModelList list; dataModels( list ); + if (!isAllSaved) + isAllSaved = LightApp_Study::isModified(); - SalomeApp_DataModel* aModel = 0; - for ( QPtrListIterator it( list ); it.current() && isAllSaved; ++it ){ - aModel = dynamic_cast( it.current() ); - if ( aModel ) - isAllSaved = aModel->isSaved(); - } return isAllSaved; } +//======================================================================= +// name : saveModuleData +/*! Purpose : save list file for module 'theModuleName' */ +//======================================================================= +void SalomeApp_Study::saveModuleData( QString theModuleName, QStringList theListOfFiles ) +{ + int aNb = theListOfFiles.count(); + if ( aNb == 0 ) + return; + + std::vector aListOfFiles ( aNb ); + int anIndex = 0; + for ( QStringList::Iterator it = theListOfFiles.begin(); it != theListOfFiles.end(); ++it ) { + if ( (*it).isEmpty() ) + continue; + aListOfFiles[anIndex] = (*it).latin1(); + anIndex++; + } + SetListOfFiles(theModuleName, aListOfFiles); +} + +//======================================================================= +// name : openModuleData +/*! Purpose : gets list of file for module 'theModuleNam' */ +//======================================================================= +void SalomeApp_Study::openModuleData( QString theModuleName, QStringList& theListOfFiles ) +{ + std::vector aListOfFiles = GetListOfFiles( theModuleName ); + + int i, aLength = aListOfFiles.size() - 1; + if ( aLength < 0 ) + return; + + //Get a temporary directory for saved a file + theListOfFiles.append(aListOfFiles[0].c_str()); + + for(i = 0; i < aLength; i++) + theListOfFiles.append(aListOfFiles[i+1].c_str()); +} + +//======================================================================= +// name : saveStudyData +/*! Purpose : save data from study */ +//======================================================================= +bool SalomeApp_Study::saveStudyData( const QString& theFileName ) +{ + ModelList list; dataModels( list ); + SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first(); + std::vector listOfFiles(0); + for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) + SetListOfFiles(aModel->module()->name(), listOfFiles); + return true; +} + +//======================================================================= +// name : openStudyData +/*! Purpose : open data for study */ +//======================================================================= +bool SalomeApp_Study::openStudyData( const QString& theFileName ) +{ + return true; +} + +/*! + Set studyDS. +*/ void SalomeApp_Study::setStudyDS( const _PTR(Study)& s ) { myStudyDS = s; } +/*! + Insert data model. +*/ void SalomeApp_Study::dataModelInserted (const CAM_DataModel* dm) { MESSAGE("SalomeApp_Study::dataModelInserted() : module name() = " << dm->module()->name()); CAM_Study::dataModelInserted(dm); - // Create SComponent for module, using default engine (CORBAless) - SalomeApp_Module* aModule = (SalomeApp_Module*)(dm->module()); - if (aModule) { - QString anEngineIOR = aModule->engineIOR(); - if (anEngineIOR.isEmpty()) { // CORBAless module - // Check SComponent existance - _PTR(SComponent) aComp = studyDS()->FindComponent(dm->module()->name()); - if (!aComp) { - // Create SComponent - _PTR(StudyBuilder) aBuilder = studyDS()->NewBuilder(); - aComp = aBuilder->NewComponent(dm->module()->name()); - - // Set default engine IOR - aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().latin1()); + // addComponent(dm); +} + +/*! + Create SComponent for module, using default engine (CORBAless) +*/ +void SalomeApp_Study::addComponent(const CAM_DataModel* dm) +{ + SalomeApp_Module* aModule = dynamic_cast( dm->module() ); + // 1. aModule == 0 means that this is a light module (no CORBA enigine) + if (!aModule) { + // Check SComponent existance + _PTR(Study) aStudy = studyDS(); + if (!aStudy) + return; + _PTR(SComponent) aComp = aStudy->FindComponent(dm->module()->name()); + if (!aComp) { + // Create SComponent + _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder(); + aComp = aBuilder->NewComponent(dm->module()->name()); + aBuilder->SetName(aComp, dm->module()->moduleName().latin1()); + QString anIconName = dm->module()->iconName(); + if (!anIconName.isEmpty()) { + _PTR(AttributePixMap) anAttr = aBuilder->FindOrCreateAttribute(aComp, "AttributePixMap"); + if (anAttr) + anAttr->SetPixMap(anIconName.latin1()); } + // Set default engine IOR + aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().latin1()); + SalomeApp_DataModel::BuildTree( aComp, root(), this, /*skipExisitng=*/true ); } } } +/*! + Open data model +*/ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm ) { if (!dm) return false; - SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm); - if (aDM && aDM->open(studyName, this)) { + // SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm); + SalomeApp_Module* aModule = dynamic_cast( dm->module() ); + _PTR(Study) aStudy = studyDS(); // shared_ptr cannot be used here + _PTR(SComponent) aSComp; + QString anEngine; + // 1. aModule == 0 means that this is a light module (no CORBA enigine) + if (!aModule) { + anEngine = SalomeApp_Application::defaultEngineIOR(); + aSComp = aStudy->FindComponent(dm->module()->name()); + } + else { + SalomeApp_DataModel* aDM = dynamic_cast( dm ); + if ( aDM ) { + QString anId = aDM->getRootEntry( this ); + if ( anId.isEmpty() ) + return true; // Probably nothing to load + anEngine = aDM->getModule()->engineIOR(); + if ( anEngine.isEmpty() ) + return false; + aSComp = aStudy->FindComponentID( std::string( anId.latin1() ) ); + } + } + if ( aSComp ) { + _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() ); + if ( aBuilder ) { + try { + aBuilder->LoadWith( aSComp, std::string( anEngine.latin1() ) ); + } + catch( const SALOME::SALOME_Exception& ) { + // Oops, something went wrong while loading -> return an error + return false; + } + // Something has been read -> create data model tree + //SalomeApp_DataModel* aDM = dynamic_cast( dm ); + // aDM->buildTree( aSComp, 0, this ); + } + } else { + // Don't return false here, for there might be no data + // for a given component in the study yet + } + QStringList listOfFiles; + openModuleData(dm->module()->name(), listOfFiles); + if (dm && dm->open(studyName, this, listOfFiles)) { + // Remove the files and temporary directory, created + // for this module by LightApp_Engine_i::Load() + bool isMultiFile = false; // TODO: decide, how to access this parameter + RemoveTemporaryFiles( dm->module()->name(), isMultiFile ); + // Something has been read -> create data model tree - aDM->update(NULL, this); + LightApp_DataModel* aDM = dynamic_cast( dm ); + if ( aDM ) + aDM->update(NULL, this); return true; } - return false; } -void SalomeApp_Study::updateModelRoot( const CAM_DataModel* dm ) -{ - CAM_Study::updateModelRoot( dm ); - ((SalomeApp_Application*)application())->objectBrowser()->updateTree(); -} - +/*! + Create new study name. +*/ QString SalomeApp_Study::newStudyName() const { std::vector studies = SalomeApp_Application::studyMgr()->GetOpenStudies(); @@ -307,3 +469,144 @@ QString SalomeApp_Study::newStudyName() const } return newName; } + +//================================================================ +// Function : GetListOfFiles +/*! Purpose : to be used by CORBAless modules*/ +//================================================================ +std::vector SalomeApp_Study::GetListOfFiles( const char* theModuleName ) const +{ + SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance(); + if (aDefaultEngine) + return aDefaultEngine->GetListOfFiles(id(), theModuleName); + + std::vector aListOfFiles; + return aListOfFiles; +} + +//================================================================ +// Function : SetListOfFiles +/*! Purpose : to be used by CORBAless modules*/ +//================================================================ +void SalomeApp_Study::SetListOfFiles ( const char* theModuleName, + const std::vector theListOfFiles ) +{ + SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance(); + if (aDefaultEngine) + aDefaultEngine->SetListOfFiles(theListOfFiles, id(), theModuleName); +} + +//================================================================ +// Function : GetTmpDir +/*! Purpose : to be used by CORBAless modules*/ +//================================================================ +std::string SalomeApp_Study::GetTmpDir ( const char* theURL, const bool isMultiFile ) +{ + std::string anURLDir = SALOMEDS_Tool::GetDirFromPath(theURL); + std::string aTmpDir = isMultiFile ? anURLDir : SALOMEDS_Tool::GetTmpDir(); + return aTmpDir; +} + +//================================================================ +// Function : RemoveTemporaryFiles +/*! Purpose : to be used by CORBAless modules*/ +//================================================================ +void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bool isMultiFile ) const +{ + if (isMultiFile) + return; + + std::vector aListOfFiles = GetListOfFiles( theModuleName ); + if (aListOfFiles.size() > 0) { + std::string aTmpDir = aListOfFiles[0]; + + const int n = aListOfFiles.size() - 1; + SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames; + aSeq->length(n); + for (int i = 0; i < n; i++) + aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str()); + + SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true); + } +} + +// END: methods to be used by CORBAless modules + +void SalomeApp_Study::deleteReferencesTo( _PTR( SObject ) obj ) +{ + _PTR(StudyBuilder) sb = studyDS()->NewBuilder(); + std::vector<_PTR(SObject)> aRefs = studyDS()->FindDependances( obj ); + for( int i=0, n=aRefs.size(); iGetFatherComponent()->ComponentDataType()==obj->GetFatherComponent()->ComponentDataType() ) + { + sb->RemoveReference( o ); + sb->RemoveObjectWithChildren( o ); + } + } +} + +//================================================================ +// Function : referencedToEntry +/*! Purpose : Return referenced entry from entry*/ +//================================================================ +QString SalomeApp_Study::referencedToEntry( const QString& entry ) const +{ + _PTR(SObject) obj = studyDS()->FindObjectID( entry.latin1() ); + _PTR(SObject) refobj; + + if( obj && obj->ReferencedObject( refobj ) ) + return refobj->GetID().c_str(); + return LightApp_Study::referencedToEntry( entry ); +} + +//================================================================ +// Function : componentDataType +/*! Purpose : Return component data type from entry*/ +//================================================================ +QString SalomeApp_Study::componentDataType( const QString& entry ) const +{ + _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) ); + if ( !obj ) + return LightApp_Study::componentDataType( entry ); + return obj->GetFatherComponent()->ComponentDataType().c_str(); +} + +//================================================================ +// Function : componentDataType +/*! Purpose : Return component data type from entry*/ +//================================================================ +bool SalomeApp_Study::isComponent( const QString& entry ) const +{ + _PTR(SObject) obj( studyDS()->FindObjectID( entry.latin1() ) ); + return obj && QString( obj->GetID().c_str() ) == obj->GetFatherComponent()->GetID().c_str(); +} + +//================================================================ +// Function : children +/*! Purpose : Return entries of children of object*/ +//================================================================ +void SalomeApp_Study::children( const QString& entry, QStringList& child_entries ) const +{ + _PTR(SObject) SO = studyDS()->FindObjectID( entry.latin1() ); + _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( SO ) ); + anIter->InitEx( true ); + while( anIter->More() ) + { + _PTR(SObject) val( anIter->Value() ); + child_entries.append( val->GetID() ); + anIter->Next(); + } +} + +void SalomeApp_Study::components( QStringList& comps ) const +{ + for( _PTR(SComponentIterator) it ( studyDS()->NewComponentIterator() ); it->More(); it->Next() ) + { + _PTR(SComponent) aComponent ( it->Value() ); + if( aComponent && aComponent->ComponentDataType() == "Interface Applicative" ) + continue; // skip the magic "Interface Applicative" component + comps.append( aComponent->ComponentDataType() ); + } +}