Salome HOME
updated copyright message
[modules/gui.git] / src / SalomeApp / SalomeApp_Study.cxx
index 8598e2bdb9b52c409bd9c5708a1f90e564e096f0..d08a14074cda308ba5ffeca603f41c893da2d5f0 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
+#ifndef DISABLE_PYCONSOLE
+  #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
+#endif
+
 #include "SalomeApp_Study.h"
 
 #include "SalomeApp_Module.h"
 
 #include <LightApp_Displayer.h>
 
-#ifndef DISABLE_PYCONSOLE
-  #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
-#endif
-
 #include "utilities.h"
 
 #include "SALOMEDS_Tool.hxx"
@@ -82,9 +82,8 @@ class SalomeApp_Study::Observer_i : public virtual POA_SALOMEDS::Observer, QObje
 
 public:
 
-  Observer_i(_PTR(Study) aStudyDS, SalomeApp_Study* aStudy):QObject(aStudy)
+  Observer_i( SalomeApp_Study* aStudy):QObject(aStudy)
   {
-    myStudyDS=aStudyDS;
     myStudy=aStudy;
     fillEntryMap();
   }
@@ -122,7 +121,7 @@ public:
     switch(event) {
     case 1:
       { //Add sobject
-        _PTR(SObject) aSObj = myStudyDS->FindObjectID(theID);
+        _PTR(SObject) aSObj = SalomeApp_Application::getStudy()->FindObjectID(theID);
         _PTR(SComponent) aSComp = aSObj->GetFatherComponent();
 
         if (!aSComp || aSComp->IsNull()) {
@@ -131,7 +130,7 @@ public:
         }
 
         // Mantis issue 0020136: Drag&Drop in OB
-        _PTR(UseCaseBuilder) aUseCaseBuilder = myStudyDS->GetUseCaseBuilder();
+        _PTR(UseCaseBuilder) aUseCaseBuilder = SalomeApp_Application::getStudy()->GetUseCaseBuilder();
         if (aUseCaseBuilder->IsUseCaseNode(aSComp)) { // BEGIN: work with tree nodes structure
           if (!aUseCaseBuilder->IsUseCaseNode(aSObj)) {
             // tree node is not yet set, it is a normal situation
@@ -155,12 +154,18 @@ public:
           SalomeApp_DataObject* aFatherDO = it->second;
 
           it = entry2SuitObject.find(theID);
-          if (it != entry2SuitObject.end()) { // this SOobject is already added somethere
+          if (it != entry2SuitObject.end()) { // this SOobject is already added somewhere
             suit_obj = it->second;
             SUIT_DataObject* oldFather = suit_obj->parent();
             if (oldFather) {
               oldFather->removeChild(suit_obj, false);
               SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( myStudy->application() );
+//              MESSAGE("myStudy: " << myStudy->id() << " app " << app);
+//              MESSAGE("objectBrowser: "<< app->objectBrowser());
+              if (!app->objectBrowser()) {
+                MESSAGE("Object Browser not found. Problem ??");
+                return;
+              }
               SUIT_AbstractModel* model = dynamic_cast<SUIT_AbstractModel*>(app->objectBrowser()->model());
               model->forgetObject( suit_obj );
                 
@@ -176,36 +181,27 @@ public:
 
           suit_obj->updateItem();
           // define position in the data tree (in aFatherDO) to insert the aSObj
-          int pos = -1;
-          //int childDataObjCount = aFatherDO->childCount();
-          _PTR(UseCaseIterator) aUseCaseIter = aUseCaseBuilder->GetUseCaseIterator(aFatherSO);
-          for (int cur = 0; aUseCaseIter->More() && pos < 0; cur++, aUseCaseIter->Next()) {
-            if (aUseCaseIter->Value()->GetID() == theID) {
-              pos = cur;
-              break;
-            }
-          }
+          int pos = aUseCaseBuilder->GetIndexInFather(aFatherSO, aSObj);
 
           aFatherDO->insertChildAtPos(suit_obj, pos);
           //aFatherDO->insertChild(suit_obj, pos);
           aFatherDO->updateItem();
 
-         /* Define visibility state */
-         bool isComponent = dynamic_cast<SalomeApp_ModuleObject*>( suit_obj ) != 0;
-         if ( suit_obj && !isComponent && myStudy->visibilityState( theID.c_str() ) == Qtx::UnpresentableState ) {
-           QString moduleTitle = ((CAM_Application*)myStudy->application())->moduleTitle(suit_obj->componentDataType());
-           if (!moduleTitle.isEmpty()) {
-             LightApp_Displayer* aDisplayer = LightApp_Displayer::FindDisplayer(moduleTitle,false);
-             if (aDisplayer) {
-               if(aDisplayer->canBeDisplayed(theID.c_str())) {
-                 myStudy->setVisibilityState( theID.c_str(), Qtx::HiddenState ); //hide the just added object
-                 //MESSAGE("Object with entry : "<< theID <<" CAN be displayed !!!");
-               }
-               else
-                 MESSAGE("Object with entry : "<< theID <<" CAN'T be displayed !!!");
-             }
-           }
-         }
+          /* Define visibility state */
+          bool isComponent = dynamic_cast<SalomeApp_ModuleObject*>( suit_obj ) != 0;
+          if ( suit_obj && !isComponent && myStudy->visibilityState( theID.c_str() ) == Qtx::UnpresentableState ) {
+            LightApp_Displayer* aDisplayer = LightApp_Displayer::FindDisplayer
+              (suit_obj->componentDataType(),false);
+            if (aDisplayer) {
+              if (aDisplayer->canBeDisplayed(theID.c_str())) {
+                //hide the just added object
+                myStudy->setVisibilityState( theID.c_str(), Qtx::HiddenState );
+                //MESSAGE("Object with entry : "<< theID <<" CAN be displayed !!!");
+              }
+              //else
+              //  MESSAGE("Object with entry : "<< theID <<" CAN'T be displayed !!!");
+            }
+          }
         } // END: work with tree nodes structure
         else { // BEGIN: work with study structure
           EntryMapIter it = entry2SuitObject.find( theID );
@@ -214,7 +210,7 @@ public:
             return;
           }
 
-          int last2Pnt_pos = theID.rfind( ":" );
+          int last2Pnt_pos = (int)theID.rfind( ":" ); //!< TODO: conversion from size_t to int
           std::string parent_id = theID.substr( 0, last2Pnt_pos );
           int tag = atoi( theID.substr( last2Pnt_pos+1 ).c_str() );
 
@@ -326,17 +322,15 @@ public:
         /* Define visibility state */
         bool isComponent = dynamic_cast<SalomeApp_ModuleObject*>( suit_obj ) != 0;
         if ( suit_obj && !isComponent ) {
-          QString moduleTitle = ((CAM_Application*)myStudy->application())->moduleTitle(suit_obj->componentDataType());
-          if (!moduleTitle.isEmpty()) {
-            LightApp_Displayer* aDisplayer = LightApp_Displayer::FindDisplayer(moduleTitle,false);
-            if (aDisplayer) {
-              if(aDisplayer->canBeDisplayed(theID.c_str())) {
-                myStudy->setVisibilityState( theID.c_str(), Qtx::HiddenState );
-                //MESSAGE("Object with entry : "<< theID <<" CAN be displayed !!!");
-              }
-              else
-                MESSAGE("Object with entry : "<< theID <<" CAN'T be displayed !!!");
+          LightApp_Displayer* aDisplayer = LightApp_Displayer::FindDisplayer
+            (suit_obj->componentDataType(),false);
+          if (aDisplayer) {
+            if (aDisplayer->canBeDisplayed(theID.c_str())) {
+              myStudy->setVisibilityState( theID.c_str(), Qtx::HiddenState );
+              //MESSAGE("Object with entry : "<< theID <<" CAN be displayed !!!");
             }
+            //else
+            //  MESSAGE("Object with entry : "<< theID <<" CAN'T be displayed !!!");
           }
         }
         break;
@@ -344,8 +338,8 @@ public:
 #ifndef DISABLE_PYCONSOLE
     case 6: //NoteBook variables were modified
       {
-       myStudy->onNoteBookVarUpdate( QString( theID.c_str() ) );
-       break;
+        myStudy->onNoteBookVarUpdate( QString( theID.c_str() ) );
+        break;
       }
 #endif
     default:MESSAGE("Unknown event: "  << event);break;
@@ -360,7 +354,7 @@ private:
     while (o) {
       SalomeApp_DataObject* so = dynamic_cast<SalomeApp_DataObject*>( o );
       if ( so ) {
-        std::string entry = so->entry().toLatin1().constData();
+        std::string entry = so->entry().toUtf8().constData();
         if ( entry.size() )
           entry2SuitObject[entry] = so;
       }
@@ -368,7 +362,7 @@ private:
         // parse the children
         o = o->firstChild();
       }
-      else if ( o->nextBrother() > 0 ) {
+      else if ( o->nextBrother() ) {
         o = o->nextBrother();
       }
       else {
@@ -386,7 +380,6 @@ private:
   }
 
 private:
-  _PTR(Study)      myStudyDS;
   SalomeApp_Study* myStudy;
   EntryMap         entry2SuitObject;
 };
@@ -398,6 +391,7 @@ private:
 SalomeApp_Study::SalomeApp_Study( SUIT_Application* app )
 : LightApp_Study( app ), myObserver( 0 )
 {
+  myStudyDS = SalomeApp_Application::getStudy();
 }
 
 /*!
@@ -408,6 +402,7 @@ SalomeApp_Study::~SalomeApp_Study()
   if ( myObserver ) {
     PortableServer::ObjectId_var oid = myObserver->_default_POA()->servant_to_id( myObserver );
     myObserver->_default_POA()->deactivate_object( oid.in() );
+    myObserver = 0;
   }
 }
 
@@ -418,17 +413,6 @@ void SalomeApp_Study::onNoteBookVarUpdate( QString theVarName)
 }
 #endif
 
-/*!
-  Gets study id.
-*/
-int SalomeApp_Study::id() const
-{
-  int id = -1;
-  if ( studyDS() )
-    id = studyDS()->StudyId();
-  return id;
-}
-
 /*!
   Get study name.
 */
@@ -438,7 +422,9 @@ QString SalomeApp_Study::studyName() const
   // it can be changed outside of GUI
   // TEMPORARILY SOLUTION: better to be implemented with help of SALOMEDS observers
   if ( studyDS() ) {
-    QString newName = QString::fromUtf8(studyDS()->Name().c_str());
+    QString newName = QString::fromUtf8(studyDS()->URL().c_str());
+    if ( newName.isEmpty() )
+      newName = QString::fromUtf8(studyDS()->Name().c_str());
     if ( LightApp_Study::studyName() != newName ) {
       SalomeApp_Study* that = const_cast<SalomeApp_Study*>( this );
       that->setStudyName( newName );
@@ -463,35 +449,7 @@ bool SalomeApp_Study::createDocument( const QString& theStr )
 {
   MESSAGE( "createDocument" );
 
-  // initialize myStudyDS, read HDF file
-  QString aName = newStudyName();
-
-  _PTR(Study) study;
-  bool showError = !application()->property("open_study_from_command_line").isValid() || 
-    !application()->property("open_study_from_command_line").toBool();
-  try {
-    study = _PTR(Study)( SalomeApp_Application::studyMgr()->NewStudy( aName.toUtf8().data() ) );
-  }
-  catch(const SALOME_Exception& ex) {
-    application()->putInfo(tr(ex.what()));
-    if ( showError )
-      SUIT_MessageBox::critical( SUIT_Session::session()->activeApplication()->desktop(),
-                                 tr("ERR_ERROR"), tr(ex.what()));
-    return false;
-  } 
-  catch(...) {
-    application()->putInfo(tr("CREATE_DOCUMENT_PROBLEM"));
-    if ( showError )
-      SUIT_MessageBox::critical( SUIT_Session::session()->activeApplication()->desktop(),
-                                 tr("ERR_ERROR"), tr("CREATE_DOCUMENT_PROBLEM"));
-    return false;
-  }
-
-  if ( !study )
-    return false;
-
-  setStudyDS( study );
-  setStudyName( aName );
+  setStudyName( QString::fromUtf8(myStudyDS->URL().c_str()) );
 
   // create myRoot
   SalomeApp_RootObject* aRoot=new SalomeApp_RootObject( this );
@@ -503,7 +461,7 @@ bool SalomeApp_Study::createDocument( const QString& theStr )
   bool aRet = CAM_Study::createDocument( theStr );
 
 #ifdef WITH_SALOMEDS_OBSERVER
-  myObserver = new Observer_i(myStudyDS,this);
+  myObserver = new Observer_i(this);
   //attach an observer to the study with notification of modifications
   myStudyDS->attach(myObserver->_this(),true);
 #endif
@@ -521,12 +479,12 @@ bool SalomeApp_Study::openDocument( const QString& theFileName )
 {
   MESSAGE( "openDocument" );
 
-  // initialize myStudyDS, read HDF file
-  _PTR(Study) study;
-  bool showError = !application()->property("open_study_from_command_line").isValid() || 
+  // read HDF file
+  bool res = false;
+  bool showError = !application()->property("open_study_from_command_line").isValid() ||
     !application()->property("open_study_from_command_line").toBool();
   try {
-    study = _PTR(Study) ( SalomeApp_Application::studyMgr()->Open( theFileName.toUtf8().data() ) );
+    res = myStudyDS->Open( theFileName.toUtf8().data() );
   }
   catch(const SALOME_Exception& ex) {
     application()->putInfo(tr(ex.what()));
@@ -534,7 +492,7 @@ bool SalomeApp_Study::openDocument( const QString& theFileName )
       SUIT_MessageBox::critical( SUIT_Session::session()->activeApplication()->desktop(),
                                  tr("ERR_ERROR"), tr(ex.what()));
     return false;
-  } 
+  }
   catch(...) {
     application()->putInfo(tr("OPEN_DOCUMENT_PROBLEM"));
     if ( showError )
@@ -543,11 +501,9 @@ bool SalomeApp_Study::openDocument( const QString& theFileName )
     return false;
   }
 
-  if ( !study )
+  if ( !res)
     return false;
 
-  setStudyDS( study );
-
   setRoot( new SalomeApp_RootObject( this ) ); // create myRoot
 
   // update loaded data models: call open() and update() on them.
@@ -564,15 +520,15 @@ bool SalomeApp_Study::openDocument( const QString& theFileName )
 
 #ifdef WITH_SALOMEDS_OBSERVER
   dynamic_cast<SalomeApp_RootObject*>( root() )->setToSynchronize(false);
-  myObserver = new Observer_i(myStudyDS,this);
+  myObserver = new Observer_i(this);
   //attach an observer to the study with notification of modifications
   myStudyDS->attach(myObserver->_this(),true);
 #endif
 
-  bool res = CAM_Study::openDocument( theFileName );
+  res = CAM_Study::openDocument( theFileName );
 
   emit opened( this );
-  study->IsSaved(true);
+  myStudyDS->IsSaved(true);
 
   bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
   if ( restore ) {
@@ -586,20 +542,13 @@ bool SalomeApp_Study::openDocument( const QString& theFileName )
 }
 
 /*!
-  Connects GUI study to SALOMEDS one already loaded into StudyManager
+  Connects GUI study to SALOMEDS one
   \param theStudyName - name of study
 */
 bool SalomeApp_Study::loadDocument( const QString& theStudyName )
 {
   MESSAGE( "loadDocument" );
 
-  // obtain myStudyDS from StudyManager
-  _PTR(Study) study ( SalomeApp_Application::studyMgr()->GetStudyByName( theStudyName.toUtf8().data() ) );
-  if ( !study )
-    return false;
-
-  setStudyDS( study );
-
   setRoot( new SalomeApp_RootObject( this ) ); // create myRoot
 
   //SRN: BugID IPAL9021, put there the same code as in a method openDocument
@@ -612,6 +561,13 @@ bool SalomeApp_Study::loadDocument( const QString& theStudyName )
   while ( it.hasNext() )
     openDataModel( studyName(), it.next() );
 
+  bool res = CAM_Study::openDocument( theStudyName );
+
+  //rnv: to fix the "0051779: TC7.2.0: Save operation works incorrectly for study loaded from data server"
+  //     mark study as "not saved" after call openDocument( ... ) method.
+  setIsSaved(false);
+  emit opened( this ); // myRoot is set to Object Browser here
+
   // 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.
@@ -619,18 +575,11 @@ bool SalomeApp_Study::loadDocument( const QString& theStudyName )
 
 #ifdef WITH_SALOMEDS_OBSERVER
   dynamic_cast<SalomeApp_RootObject*>( root() )->setToSynchronize(false);
-  myObserver = new Observer_i(myStudyDS,this);
+  myObserver = new Observer_i(this);
   //attach an observer to the study with notification of modifications
   myStudyDS->attach(myObserver->_this(),true);
 #endif
 
-  bool res = CAM_Study::openDocument( theStudyName );
-  
-  //rnv: to fix the "0051779: TC7.2.0: Save operation works incorrectly for study loaded from data server"
-  //     mark study as "not saved" after call openDocument( ... ) method.
-  setIsSaved(false);
-  emit opened( this );
-
   bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
   if ( restore ) {
     std::vector<int> savePoints = getSavePoints();
@@ -664,7 +613,8 @@ bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
       listOfFiles.clear();
       aModel->saveAs( theFileName, this, listOfFiles );
       if ( !listOfFiles.isEmpty() )
-        saveModuleData(aModel->module()->name(), listOfFiles);
+        saveModuleData(aModel->module()->name(), 0, // 0 means persistence file
+                       listOfFiles);
     }
   }
 
@@ -675,12 +625,10 @@ bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
 
   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false );
   bool isAscii = resMgr->booleanValue( "Study", "ascii_file", false );
-  bool res = (isAscii ?
-    SalomeApp_Application::studyMgr()->SaveAsASCII( theFileName.toUtf8().data(), studyDS(), isMultiFile ) :
-    SalomeApp_Application::studyMgr()->SaveAs     ( theFileName.toUtf8().data(), studyDS(), isMultiFile ))
+  bool res = studyDS()->SaveAs( theFileName.toUtf8().data(), isMultiFile, isAscii )
     && CAM_Study::saveDocumentAs( theFileName );
 
-  res = res && saveStudyData(theFileName);
+  res = res && saveStudyData(theFileName, 0); // 0 means persistence file
 
   if ( res )
     emit saved( this );
@@ -709,7 +657,8 @@ bool SalomeApp_Study::saveDocument()
       listOfFiles.clear();
       aModel->save(listOfFiles);
       if ( !listOfFiles.isEmpty() )
-        saveModuleData(aModel->module()->name(), listOfFiles);
+        saveModuleData(aModel->module()->name(), 0, // 0 means persistence file
+                       listOfFiles);
     }
   }
 
@@ -720,11 +669,9 @@ bool SalomeApp_Study::saveDocument()
 
   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false );
   bool isAscii = resMgr->booleanValue( "Study", "ascii_file", false );
-  bool res = (isAscii ?
-    SalomeApp_Application::studyMgr()->SaveASCII( studyDS(), isMultiFile ) :
-    SalomeApp_Application::studyMgr()->Save     ( studyDS(), isMultiFile )) && CAM_Study::saveDocument();
+  bool res = studyDS()->Save( isMultiFile, isAscii ) && CAM_Study::saveDocument();
 
-  res = res && saveStudyData(studyName());
+  res = res && saveStudyData(studyName(), 0); // 0 means persistence file
   if ( res )
     emit saved( this );
 
@@ -739,24 +686,18 @@ void SalomeApp_Study::closeDocument(bool permanently)
   LightApp_Study::closeDocument(permanently);
 
   // close SALOMEDS document
-  _PTR(Study) studyPtr = studyDS();
-  if ( studyPtr )
-  {
-    if ( myObserver )
-      myStudyDS->detach( myObserver->_this() );
-    if ( permanently ) {
-      SUIT_Desktop* desk = SUIT_Session::session()->activeApplication()->desktop();
-      bool isBlocked = desk->signalsBlocked();
-      desk->blockSignals( true );
-      SalomeApp_Application::studyMgr()->Close( studyPtr );
-      desk->blockSignals( isBlocked );
+  if ( myObserver )
+    myStudyDS->detach( myObserver->_this() );
+  if ( permanently ) {
+    SUIT_Desktop* desk = SUIT_Session::session()->activeApplication()->desktop();
+    bool isBlocked = desk->signalsBlocked();
+    desk->blockSignals( true );
+    myStudyDS->Clear();
+    desk->blockSignals( isBlocked );
 #ifndef DISABLE_PYCONSOLE
-      SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( application() );
-      app->getPyInterp()->destroy();
+    SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( application() );
+    app->getPyInterp()->destroy();
 #endif
-    }
-    SALOMEDSClient_Study* aStudy = 0;
-    setStudyDS( _PTR(Study)(aStudy) );
   }
 }
 
@@ -780,16 +721,15 @@ bool SalomeApp_Study::dump( const QString& theFileName,
                             bool isMultiFile,
                             bool toSaveGUI )
 {
-  int savePoint;
+  int savePoint = 0;
   _PTR(AttributeParameter) ap;
   _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
-  _PTR(Study) aStudy = studyDS();
 
-  if( ip->isDumpPython( aStudy ) ) 
-    ip->setDumpPython( aStudy ); //Unset DumpPython flag.
+  if( ip->isDumpPython() )
+    ip->setDumpPython(); //Unset DumpPython flag.
 
   if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
-    ip->setDumpPython( aStudy );
+    ip->setDumpPython();
     //SRN: create a temporary save point
     savePoint = SalomeApp_VisualState( 
       dynamic_cast<SalomeApp_Application*>( application() ) ).storeState(); 
@@ -812,24 +752,25 @@ bool SalomeApp_Study::dump( const QString& theFileName,
         // This call simply passes the data model's dump output to SalomeApp_Engine servant.
         // This code is shared with persistence mechanism.
         // NOTE: this should be revised if behavior of saveModuleData() changes!
-        saveModuleData(aModel->module()->name(), listOfFiles);
+        saveModuleData(aModel->module()->name(), 1, // 1 means dump file
+                       listOfFiles);
     }
   }
 
   // Now dump SALOMEDS part that also involves SalomeApp_Engine in case if 
   // any light module is present in the current configuration
   QFileInfo aFileInfo( theFileName );
-  bool res = aStudy->DumpStudy( aFileInfo.absolutePath().toUtf8().data(),
-                                aFileInfo.baseName().toUtf8().data(),
-                                toPublish,
-                                isMultiFile);
+  bool res = myStudyDS->DumpStudy( aFileInfo.absolutePath().toUtf8().data(),
+                                  aFileInfo.baseName().toUtf8().data(),
+                                  toPublish,
+                                  isMultiFile);
   if ( toSaveGUI )
     removeSavePoint( savePoint ); //SRN: remove the created temporary save point.
 
   // Issue 21377 - Clean up light module data in SalomeApp_Engine servant
   // This code is shared with persistence mechanism.
   // NOTE: this should be revised if behavior of saveStudyData() changes!
-  saveStudyData( theFileName );
+  saveStudyData( theFileName, 1 ); // 0 means persistence file
 
   return res;
 }
@@ -851,8 +792,7 @@ bool SalomeApp_Study::isModified() const
  */
 void SalomeApp_Study::Modified()
 {
-  if(_PTR(Study) aStudy = studyDS())
-    aStudy->Modified();
+  myStudyDS->Modified();
   LightApp_Study::Modified();
 }
 
@@ -873,7 +813,7 @@ bool SalomeApp_Study::isSaved() const
   \param theModuleName - name of module
   \param theListOfFiles - list of files to be saved
 */
-void SalomeApp_Study::saveModuleData( QString theModuleName, QStringList theListOfFiles )
+void SalomeApp_Study::saveModuleData( QString theModuleName, int type, QStringList theListOfFiles )
 {
   int aNb = theListOfFiles.count();
   if ( aNb == 0 )
@@ -887,7 +827,7 @@ void SalomeApp_Study::saveModuleData( QString theModuleName, QStringList theList
     aListOfFiles[anIndex] = (*it).toUtf8().data();
     anIndex++;
   }
-  SetListOfFiles(theModuleName.toStdString().c_str(), aListOfFiles);
+  SetListOfFiles(theModuleName.toStdString().c_str(), type, aListOfFiles);
 }
 
 /*!
@@ -895,11 +835,11 @@ void SalomeApp_Study::saveModuleData( QString theModuleName, QStringList theList
   \param theModuleName - name of module
   \param theListOfFiles - list of files to be loaded
 */
-void SalomeApp_Study::openModuleData( QString theModuleName, QStringList& theListOfFiles )
+void SalomeApp_Study::openModuleData( QString theModuleName, int type, QStringList& theListOfFiles )
 {
-  std::vector<std::string> aListOfFiles =  GetListOfFiles( theModuleName.toStdString().c_str() );
+  std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName.toStdString().c_str(), type );
 
-  int i, aLength = aListOfFiles.size() - 1;
+  int i, aLength = (int)aListOfFiles.size() - 1; //!< TODO: conversion from size_t to int
   if ( aLength < 0 )
     return;
 
@@ -914,18 +854,17 @@ void SalomeApp_Study::openModuleData( QString theModuleName, QStringList& theLis
   Re-implemented from LightApp_Study, actually does not save anything but
   simply cleans up light modules' data
 */
-bool SalomeApp_Study::saveStudyData( const QString& theFileName )
+bool SalomeApp_Study::saveStudyData( const QString& /*theFileName*/, int type )
 {
   ModelList list; dataModels( list );
   QListIterator<CAM_DataModel*> it( list );
-  std::vector<std::string> listOfFiles(0);
   while ( it.hasNext() ){
     LightApp_DataModel* aLModel = 
       dynamic_cast<LightApp_DataModel*>( it.next() );
     // It is safe to call SetListOfFiles() for any kind of module
     // because SetListOfFiles() does nothing for full modules :)
     if ( aLModel )
-      SetListOfFiles(aLModel->module()->name().toStdString().c_str(), listOfFiles);
+      SetListOfFiles(aLModel->module()->name().toStdString().c_str(), type, std::vector<std::string>());
   }
   return true;
 }
@@ -933,17 +872,9 @@ bool SalomeApp_Study::saveStudyData( const QString& theFileName )
 /*!
   Loads data for study
 */
-bool SalomeApp_Study::openStudyData( const QString& theFileName )
-{
- return true;
-}
-
-/*!
-  Set studyDS.
-*/
-void SalomeApp_Study::setStudyDS( const _PTR(Study)& s )
+bool SalomeApp_Study::openStudyData( const QString& /*theFileName*/, int /*type*/ )
 {
-  myStudyDS = s;
+  return true;
 }
 
 /*!
@@ -979,11 +910,7 @@ CAM_ModuleObject* SalomeApp_Study::createModuleObject( LightApp_DataModel* theDa
   }
 
   if ( !res ){
-    _PTR(Study) aStudy = studyDS();
-    if ( !aStudy )
-      return res;
-
-    _PTR(SComponent) aComp = aStudy->FindComponent( 
+    _PTR(SComponent) aComp = myStudyDS->FindComponent(
       theDataModel->module()->name().toStdString() );
     if ( !aComp )
       return res;
@@ -1015,16 +942,13 @@ void SalomeApp_Study::addComponent(const CAM_DataModel* dm)
   // 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;
 
     std::string aCompDataType = dm->module()->name().toStdString();
 
-    _PTR(SComponent) aComp = aStudy->FindComponent(aCompDataType);
+    _PTR(SComponent) aComp = myStudyDS->FindComponent(aCompDataType);
     if (!aComp) {
       // Create SComponent
-      _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
+      _PTR(StudyBuilder) aBuilder = myStudyDS->NewBuilder();
       aComp = aBuilder->NewComponent(aCompDataType);
       aBuilder->SetName(aComp, dm->module()->moduleName().toStdString());
       QString anIconName = dm->module()->iconName();
@@ -1043,7 +967,7 @@ void SalomeApp_Study::addComponent(const CAM_DataModel* dm)
       SalomeApp_DataModel::synchronize( aComp, this );
     }
     else {
-      _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
+      _PTR(StudyBuilder) aBuilder = myStudyDS->NewBuilder();
       aBuilder->SetName(aComp, dm->module()->moduleName().toStdString());
       QString anIconName = dm->module()->iconName();
       if (!anIconName.isEmpty()) {
@@ -1066,7 +990,6 @@ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm
 
   //  SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm);
   SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( 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)
@@ -1074,7 +997,7 @@ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm
     // Issue 21377 - using separate engine for each type of light module
     std::string aCompDataType = dm->module()->name().toStdString();
     anEngine = SalomeApp_Engine_i::EngineIORForComponent( aCompDataType.c_str(), true ).c_str();
-    aSComp = aStudy->FindComponent( aCompDataType );
+    aSComp = myStudyDS->FindComponent( aCompDataType );
   }
   else {
     SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
@@ -1085,11 +1008,11 @@ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm
       anEngine = aDM->getModule()->engineIOR();
       if ( anEngine.isEmpty() )
         return false;
-      aSComp = aStudy->FindComponentID( std::string( anId.toLatin1() ) );
+      aSComp = myStudyDS->FindComponentID( std::string( anId.toLatin1() ) );
     }
   }
   if ( aSComp ) {
-    _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() );
+    _PTR(StudyBuilder) aBuilder( myStudyDS->NewBuilder() );
     if ( aBuilder ) {
       try {
         aBuilder->LoadWith( aSComp, std::string( anEngine.toLatin1() ) );
@@ -1107,12 +1030,15 @@ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm
     // for a given component in the study yet
   }
   QStringList listOfFiles;
-  openModuleData(dm->module()->name(), listOfFiles);
+  openModuleData(dm->module()->name(), 0, // 0 means persistence file
+                 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().toStdString().c_str(), isMultiFile );
+    RemoveTemporaryFiles( dm->module()->name().toStdString().c_str(), isMultiFile, true );
+    SetListOfFiles( dm->module()->name().toStdString().c_str(), 0, // 0 means persistence file
+                    std::vector<std::string>() );
 
     // Something has been read -> create data model tree
     LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>( dm );
@@ -1123,28 +1049,6 @@ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm
   return false;
 }
 
-/*!
-  Create new study name.
-*/
-QString SalomeApp_Study::newStudyName() const
-{
-  std::vector<std::string> studies = SalomeApp_Application::studyMgr()->GetOpenStudies();
-  QString prefix( "Study%1" ), newName, curName;
-  int i = 1, j, n = studies.size();
-  while ( newName.isEmpty() ){
-    curName = prefix.arg( i );
-    for ( j = 0 ; j < n; j++ ){
-      if ( !strcmp( studies[j].c_str(), curName.toLatin1() ) )
-        break;
-    }
-    if ( j == n )
-      newName = curName;
-    else
-      i++;
-  }
-  return newName;
-}
-
 /*!
   Note that this method does not create or activate SalomeApp_Engine_i instance,
   therefore it can be called safely for any kind of module, but for full
@@ -1152,15 +1056,14 @@ QString SalomeApp_Study::newStudyName() const
   \return list of files used by module: to be used by CORBAless modules
   \param theModuleName - name of module
 */
-std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleName  ) const
+std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleName, int type ) const
 {
   // Issue 21377 - using separate engine for each type of light module
   SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance( theModuleName, false );
   if (aDefaultEngine)
-    return aDefaultEngine->GetListOfFiles(id());
+    return aDefaultEngine->GetListOfFiles( type );
 
-  std::vector<std::string> aListOfFiles;
-  return aListOfFiles;
+  return std::vector<std::string>();
 }
 
 /*!
@@ -1171,13 +1074,13 @@ std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleN
   \param theModuleName - name of module
   \param theListOfFiles - list of files
 */
-void SalomeApp_Study::SetListOfFiles ( const char* theModuleName,
+void SalomeApp_Study::SetListOfFiles ( const char* theModuleName, int type,
                                        const std::vector<std::string> theListOfFiles )
 {
   // Issue 21377 - using separate engine for each type of light module
   SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance( theModuleName, false );
   if (aDefaultEngine)
-    aDefaultEngine->SetListOfFiles(theListOfFiles, id());
+    aDefaultEngine->SetListOfFiles(type, theListOfFiles);
 }
 
 /*!
@@ -1193,22 +1096,28 @@ std::string SalomeApp_Study::GetTmpDir ( const char* theURL, const bool  isMulti
 /*!
   Removes temporary files
 */
-void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bool isMultiFile ) const
+void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, bool isMultiFile, bool force )
 {
   if (isMultiFile)
     return;
 
-  std::vector<std::string> aListOfFiles = GetListOfFiles( theModuleName );
+  SALOMEDS_Tool::ListOfFiles aListOfFiles = GetListOfFiles( theModuleName, 0 );
   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);
+    const int n = (int)aListOfFiles.size() - 1; //!< TODO: conversion from size_t to int
+    std::vector<std::string> aSeq;
+    aSeq.reserve(n);
     for (int i = 0; i < n; i++)
-      aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str());
+      aSeq.push_back(CORBA::string_dup(aListOfFiles[i + 1].c_str()));
 
-    SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
+    SalomeApp_Engine_i* engine = SalomeApp_Engine_i::GetInstance( theModuleName, false );
+    bool toRemove = force || ( engine && !engine->keepFiles() );
+
+    if ( toRemove ) {
+      SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq, true);
+      engine->keepFiles( false );
+    }
   }
 }
 
@@ -1220,7 +1129,7 @@ void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bo
 void SalomeApp_Study::updateFromNotebook( const QString& theFileName, bool isSaved )
 {
   setStudyName(theFileName);
-  studyDS()->Name(theFileName.toStdString());
+  studyDS()->URL(theFileName.toStdString());
   setIsSaved( isSaved );
 }
 #endif
@@ -1229,7 +1138,7 @@ LightApp_DataObject* SalomeApp_Study::findObjectByEntry( const QString& theEntry
 {
   LightApp_DataObject* o = 0;
   if ( myObserver ) {
-    o = dynamic_cast<LightApp_DataObject*>( myObserver->findObject( theEntry.toLatin1().constData() ) );
+    o = dynamic_cast<LightApp_DataObject*>( myObserver->findObject( theEntry.toUtf8().constData() ) );
   }
   if ( !o ) {
     o = LightApp_Study::findObjectByEntry( theEntry );
@@ -1245,7 +1154,7 @@ 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(); i<n; i++ )
+  for( size_t i=0, n=aRefs.size(); i<n; i++ )
   {
     _PTR( SObject ) o = aRefs[i];
     if( o->GetFatherComponent()->ComponentDataType()==obj->GetFatherComponent()->ComponentDataType() )