Salome HOME
Extra paths in embedded interpreter
[modules/gui.git] / src / SalomeApp / SalomeApp_Application.cxx
index eaec2acdeb3e7d91c20c81c446b34dbed6c7e80f..0cf0f4c81ef558432a70332cbe501666f6f42cac 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2021  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
@@ -80,8 +80,6 @@
 //#include <OB_ListItem.h>
 
 
-#include <Utils_ORB_INIT.hxx>
-#include <Utils_SINGLETON.hxx>
 #include <SALOME_LifeCycleCORBA.hxx>
 
 #include <QApplication>
@@ -97,7 +95,9 @@
 #include <QtDebug>
 
 #include <SALOMEDSClient_ClientFactory.hxx>
+#include <ArgvKeeper.hxx>
 #include <Basics_Utils.hxx>
+#include <OpUtil.hxx>
 
 #include <SALOME_ListIO.hxx>
 #include <SALOME_Prs.h>
 
 #include <SALOMEDS_Tool.hxx>
 
+std::unique_ptr<SALOME_NamingService_Abstract> SalomeApp_Application::_ns;
+
 /*!Internal class that updates object browser item properties */
 // temporary commented
 /*class SalomeApp_Updater : public OB_Updater
@@ -155,17 +157,50 @@ void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
   //}
 }*/
 
-/*!Create new instance of SalomeApp_Application.*/
-extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
+namespace
 {
-  return new SalomeApp_Application();
+  /*!
+    \brief Flag locker.
+  */
+  class MessageLocker
+  {
+  public:
+    //! Constructor. Sets passed boolean flag to \c true.
+    MessageLocker( bool& Lock ) : myPrevState( Lock ), myLock( Lock ) { myLock = true; }
+    //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false.
+    ~MessageLocker() { myLock = myPrevState; }
+  private:
+    bool  myPrevState;
+    bool& myLock; //! External 'Lock state' boolean flag
+  };
+
+  /*!
+    \brief Dynamic property manager
+  */
+  class PropertyMgr
+  {
+    QObject* myObject;
+    QString myProperty;
+  public:
+    PropertyMgr(QObject* object, const QString& property, const QVariant& value)
+      : myObject(object), myProperty(property)
+    {
+      myObject->setProperty(qPrintable(myProperty), value);
+    }
+    ~PropertyMgr()
+    {
+      myObject->setProperty(qPrintable(myProperty), QVariant());
+    }
+  };
 }
 
 /*!Constructor.*/
-SalomeApp_Application::SalomeApp_Application()
-  : LightApp_Application(),
-    myIsCloseFromExit( false )
+SalomeApp_Application::SalomeApp_Application(SALOME_NamingService_Abstract *ns):myIsCloseFromExit( false ),myToIgnoreMessages( false )
 {
+  if(!ns)
+    _ns.reset(new SALOME_NamingService(orb()));
+  else
+    _ns.reset(ns);
 }
 
 /*!Destructor.
@@ -206,11 +241,11 @@ void SalomeApp_Application::start()
 
     QString hdffile;
     QStringList pyfiles;
-    QString loadStudy;
 
-    for (int i = 1; i < qApp->arguments().size(); i++) {
+    QStringList args = QApplication::arguments();
+    for (int i = 1; i < args.count(); i++) {
       QRegExp rxs ("--study-hdf=(.+)");
-      if ( rxs.indexIn( qApp->arguments()[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) {
+      if ( rxs.indexIn( args[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) {
         QString file = rxs.capturedTexts()[1];
         QFileInfo fi ( file );
         QString extension = fi.suffix().toLower();
@@ -219,7 +254,7 @@ void SalomeApp_Application::start()
       }
       else {
         QRegExp rxp ("--pyscript=\\[(.+)\\]");
-        if ( rxp.indexIn( qApp->arguments()[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) {
+        if ( rxp.indexIn( args[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) {
           // pyscript
           QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
           for (int k = 0; k < dictList.count(); ++k) {
@@ -239,16 +274,12 @@ void SalomeApp_Application::start()
     LightApp_Application::start();
     SALOME_EventFilter::Init();
 
-    setProperty("open_study_from_command_line", true);
-    if ( !hdffile.isEmpty() )       // open hdf file given as parameter
+    if ( !hdffile.isEmpty() )
+    {
+      // open hdf file given as parameter
+      PropertyMgr propm( this, "open_study_from_command_line", true );
       onOpenDoc( hdffile );
-    else if ( pyfiles.count() > 0 ) // create new study
-      onNewDoc();
-    else if (!loadStudy.isEmpty()) {// load study by name
-      if (onLoadDoc(loadStudy))
-        updateObjectBrowser(true);
     }
-    setProperty("open_study_from_command_line", QVariant());
 
 #ifndef DISABLE_PYCONSOLE
     // import/execute python scripts
@@ -256,31 +287,28 @@ void SalomeApp_Application::start()
       SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
       PyConsole_Console* pyConsole = pythonConsole();
       if ( appStudy && pyConsole ) {
-        _PTR(Study) aStudy = appStudy->studyDS();
-        if ( !aStudy->GetProperties()->IsLocked() ) {
+        if ( !getStudy()->GetProperties()->IsLocked() ) {
           // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
           // Path is absolute, script has .py extension
-          for (uint j = 0; j < pyfiles.count(); j++ ) {
+          for (int j = 0; j < pyfiles.count(); j++ ) {
             // Extract scripts and their arguments, if any
             QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
             if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
               QString script = rxp.capturedTexts()[1];
-              QString args = "";
+              QStringList args;
               QStringList argList = __getArgsList(rxp.capturedTexts()[2]);
-              for (uint k = 0; k < argList.count(); k++ ) {
+              for (int k = 0; k < argList.count(); k++ ) {
                 QString arg = argList[k].trimmed();
                 arg.remove( QRegExp("^[\"]") );
                 arg.remove( QRegExp("[\"]$") );
-                args += arg+",";
-              }
-              args.remove( QRegExp("[,]$") );
-              if (!args.isEmpty()) {
-                args = "args:"+args;
+                args << QString("\"%1\"").arg(arg);
               }
+              if (args.count() == 1)
+                args << "";
 
               script.remove( QRegExp("^python.*[\\s]+") );
-              QString cmd = script+" "+args;
-              QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
+              QString command = QString( "exec(open(\"%1\", \"rb\").read(), args=(%2))" ).arg(script).arg(args.join(","));
+              PropertyMgr propm( this, "IsLoadedScript", true );
               pyConsole->exec(command);
             }
           } // end for loop on pyfiles QStringList
@@ -320,7 +348,7 @@ void SalomeApp_Application::createActions()
   //! Properties
   createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
                 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
-                Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
+                0, desk, false, this, SLOT( onProperties() ) );
 
   //! Catalog Generator
   createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ),  QIcon(),
@@ -335,10 +363,14 @@ void SalomeApp_Application::createActions()
   createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
                 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
                 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
+  //no need at this action for mono-study application because study is always exists
+  action( ConnectId )->setVisible( false );
 
   createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
                 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
                 Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) );
+  //no need at this action for mono-study application because study is always exists
+  action( DisconnectId )->setVisible( false );
 
 
   int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
@@ -385,6 +417,8 @@ void SalomeApp_Application::createActions()
 */
 void SalomeApp_Application::onExit()
 {
+  //MessageLocker ml( myToIgnoreMessages );
+
   bool killServers = false;
   bool result = true;
 
@@ -401,12 +435,20 @@ void SalomeApp_Application::onExit()
   }
 }
 
+/*!SLOT. Create a document.*/
+void SalomeApp_Application::onNewDoc()
+{
+  MessageLocker ml( myToIgnoreMessages );
+
+  LightApp_Application::onNewDoc();
+}
+
 /*!SLOT. Load document.*/
 void SalomeApp_Application::onLoadDoc()
 {
-  QString studyName;
+  MessageLocker ml( myToIgnoreMessages );
 
-  std::vector<std::string> List = studyMgr()->GetOpenStudies();
+  QString studyName;
 
   // rnv: According to the single-study approach on the server side
   //      can be only one study. So if it is exists connect to them,
@@ -439,14 +481,14 @@ void SalomeApp_Application::onLoadDoc()
     return;
   */
 
-  if(List.size() <= 0) {
+  if(!activeStudy()) {
     SUIT_MessageBox::warning( desktop(),
                               QObject::tr("WRN_WARNING"),
                               QObject::tr("WRN_NO_STUDY_ON SERV") );
     return;
   }
 
-  studyName = List[0].c_str();
+  studyName = activeStudy()->studyName();
 
 #ifndef WIN32
   // this code replaces marker of windows drive and path become invalid therefore
@@ -503,11 +545,10 @@ void SalomeApp_Application::onNewWithScript()
   {
     onNewDoc();
 
-    QString command = QString("execfile(r\"%1\")").arg(aFile);
-
 #ifndef DISABLE_PYCONSOLE
+    QString command = QString("exec(open(\"%1\", \"rb\").read())").arg(aFile);
     PyConsole_Console* pyConsole = pythonConsole();
-
+    PropertyMgr propm( this, "IsLoadedScript", true );
     if ( pyConsole )
       pyConsole->exec( command );
 #endif
@@ -518,10 +559,9 @@ void SalomeApp_Application::onNewWithScript()
 /*!SLOT. Load document with \a aName.*/
 bool SalomeApp_Application::onLoadDoc( const QString& aName )
 {
-#ifdef SINGLE_DESKTOP
   if ( !LightApp_Application::closeDoc() )
     return false;
-#endif
+
   bool res = true;
   if ( !activeStudy() ) {
     // if no study - load in current desktop
@@ -555,31 +595,51 @@ bool SalomeApp_Application::onLoadDoc( const QString& aName )
 /*!SLOT. Parse message for desktop.*/
 void SalomeApp_Application::onDesktopMessage( const QString& message )
 {
-  if (message.indexOf("studyCreated:") == 0) {
-    // Enable 'Connect' action
-    updateCommandsStatus();
+  if ( myToIgnoreMessages )
+    return; // a message from SALOMEDS is caused by GUI action
+
+  MessageLocker ml( myToIgnoreMessages );
+
+  if (message.indexOf("studyCreated") == 0) {
+    if (!activeStudy()) {
+      onNewDoc();
+      updateCommandsStatus();
+    }
   }
-  else if (message.indexOf("studyClosed:") == 0) {
-    /* message also contains ID of the closed study,
-       but as soon as SALOME is mono-study application for the moment,
-       this ID is not needed now.*/
-    //long aStudyId = message.section(':', 1).toLong();
+  if (message.indexOf("studyCleared") == 0) {
     // Disconnect GUI from active study, because it was closed on DS side.
-    closeActiveDoc( false );
-    // Disable 'Connect' action
-    QAction* a = action( ConnectId );
-    if ( a )
-      a->setEnabled( false );
+    if (activeStudy()) {
+      closeActiveDoc( false );
+      // Disable 'Connect' action
+      QAction* a = action( ConnectId );
+      if ( a )
+        a->setEnabled( false );
+    }
   }
   else if ( message.toLower() == "connect_to_study" ) {
-    onLoadDoc();
+    if ( activeStudy() )
+      useStudy( activeStudy()->studyName() );
+  }
+  if (message.indexOf("studyNameChanged") == 0) {
+    updateDesktopTitle();
   }
   LightApp_Application::onDesktopMessage( message );
 }
 
+/*!On module activation action.*/
+void SalomeApp_Application::onModuleActivation( const QString& modName )
+{
+  if (!activeStudy() && !modName.isEmpty())
+    getStudy()->Init();
+
+  LightApp_Application::onModuleActivation( modName );
+}
+
 /*!SLOT. Copy objects to study maneger from selection maneger..*/
 void SalomeApp_Application::onCopy()
 {
+  LightApp_Application::onCopy();
+
   SALOME_ListIO list;
   LightApp_SelectionMgr* mgr = selectionMgr();
   mgr->selectedObjects(list);
@@ -587,18 +647,21 @@ void SalomeApp_Application::onCopy()
   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
   if(study == NULL) return;
 
-  _PTR(Study) stdDS = study->studyDS();
+  _PTR(Study) stdDS = getStudy();
   if(!stdDS) return;
 
   SALOME_ListIteratorOfListIO it( list );
   if(it.More())
     {
       _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
-      try {
-        studyMgr()->Copy(so);
-        onSelectionChanged();
-      }
-      catch(...) {
+      if( so )
+      {
+        try {
+          stdDS->Copy(so);
+          onSelectionChanged();
+        }
+        catch(...) {
+        }
       }
     }
 }
@@ -606,6 +669,8 @@ void SalomeApp_Application::onCopy()
 /*!SLOT. Paste objects to study maneger from selection manager.*/
 void SalomeApp_Application::onPaste()
 {
+  LightApp_Application::onPaste();
+
   SALOME_ListIO list;
   LightApp_SelectionMgr* mgr = selectionMgr();
   mgr->selectedObjects(list);
@@ -613,7 +678,7 @@ void SalomeApp_Application::onPaste()
   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
   if(study == NULL) return;
 
-  _PTR(Study) stdDS = study->studyDS();
+  _PTR(Study) stdDS = getStudy();
   if(!stdDS) return;
 
   if ( stdDS->GetProperties()->IsLocked() ) {
@@ -627,12 +692,15 @@ void SalomeApp_Application::onPaste()
   if(it.More())
     {
       _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
-      try {
-        studyMgr()->Paste(so);
-        updateObjectBrowser( true );
-        updateActions(); //SRN: BugID IPAL9377, case 3
-      }
-      catch(...) {
+      if( so )
+      {
+        try {
+          stdDS->Paste(so);
+          updateObjectBrowser( true );
+          updateActions(); //SRN: BugID IPAL9377, case 3
+        }
+        catch(...) {
+        }
       }
     }
 }
@@ -648,20 +716,45 @@ bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
 /*! Check if the study is locked */
 void SalomeApp_Application::onCloseDoc( bool ask )
 {
-  SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
-
-  if (study != NULL) {
-    _PTR(Study) stdDS = study->studyDS();
-    if(stdDS && stdDS->IsStudyLocked()) {
-      if ( SUIT_MessageBox::question( desktop(),
-                                      QObject::tr( "WRN_WARNING" ),
-                                      QObject::tr( "CLOSE_LOCKED_STUDY" ),
-                                      SUIT_MessageBox::Yes | SUIT_MessageBox::No,
-                                      SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
+  if(getStudy()->IsStudyLocked()) {
+    if ( SUIT_MessageBox::question( desktop(),
+                                    QObject::tr( "WRN_WARNING" ),
+                                    QObject::tr( "CLOSE_LOCKED_STUDY" ),
+                                    SUIT_MessageBox::Yes | SUIT_MessageBox::No,
+                                    SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
 
-    }
   }
+  MessageLocker ml( myToIgnoreMessages );
+
   LightApp_Application::onCloseDoc( ask );
+
+  // reinitialize study to have empty data
+  //getStudy()->Init();
+}
+
+/*!SLOT. Reload document from the file.*/
+bool SalomeApp_Application::onReopenDoc()
+{
+  MessageLocker ml( myToIgnoreMessages );
+
+  return LightApp_Application::onReopenDoc();
+}
+
+
+/*!SLOT. Load document.*/
+void SalomeApp_Application::onOpenDoc()
+{
+  MessageLocker ml( myToIgnoreMessages );
+
+  LightApp_Application::onOpenDoc();
+}
+
+/*!SLOT. Load document.*/
+bool SalomeApp_Application::onOpenDoc(const QString& name)
+{
+  MessageLocker ml( myToIgnoreMessages );
+
+  return LightApp_Application::onOpenDoc(name);
 }
 
 /*!Sets enable or disable some actions on selection changed.*/
@@ -681,21 +774,14 @@ void SalomeApp_Application::onSelectionChanged()
      canPaste = m->canPaste();
    }
 
-   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
-   if (study) {
-     _PTR(Study) stdDS = study->studyDS();
+   SALOME_ListIteratorOfListIO it ( list );
 
-     if (stdDS) {
-       SALOME_ListIteratorOfListIO it ( list );
+   if (it.More() && list.Extent() == 1) {
+     _PTR(SObject) so = getStudy()->FindObjectID(it.Value()->getEntry());
 
-       if (it.More() && list.Extent() == 1) {
-         _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
-
-         if ( so ) {
-           canCopy  = canCopy  || studyMgr()->CanCopy(so);
-           canPaste = canPaste || studyMgr()->CanPaste(so);
-         }
-       }
+     if ( so ) {
+       canCopy  = canCopy  || getStudy()->CanCopy(so);
+       canPaste = canPaste || getStudy()->CanPaste(so);
      }
    }
 
@@ -713,8 +799,7 @@ void SalomeApp_Application::onDeleteInvalidReferences()
   if( aList.IsEmpty() )
     return;
 
-  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
-  _PTR(Study) aStudyDS = aStudy->studyDS();
+  _PTR(Study) aStudyDS = getStudy();
   _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
   _PTR(SObject) anObj;
 
@@ -746,6 +831,8 @@ void SalomeApp_Application::onOpenWith()
   Handle(SALOME_InteractiveObject) aIObj = aList.First();
   QString aModuleName(aIObj->getComponentDataType());
   QString aModuleTitle = moduleTitle(aModuleName);
+  if (aModuleTitle.isEmpty()) // no gui
+    aModuleTitle = moduleDisplayer(aModuleName);
   activateModule(aModuleTitle);
   QApplication::restoreOverrideCursor();
 }
@@ -769,6 +856,8 @@ SUIT_Study* SalomeApp_Application::createNewStudy()
            this, SIGNAL(notebookVarUpdated(QString)) );
 #endif
 
+  getStudy()->Init();
+
   return aStudy;
 }
 
@@ -804,7 +893,7 @@ void SalomeApp_Application::updateCommandsStatus()
   // Connect study menu
   a = action( ConnectId );
   if( a )
-    a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
+    a->setEnabled( !activeStudy() );
 
   // Disconnect study menu
   a = action( DisconnectId );
@@ -859,7 +948,6 @@ void SalomeApp_Application::onDumpStudy( )
 {
   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
   if ( !appStudy ) return;
-  _PTR(Study) aStudy = appStudy->studyDS();
 
   QStringList aFilters;
   aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
@@ -898,6 +986,7 @@ void SalomeApp_Application::onDumpStudy( )
       bool res;
       {
         SUIT_OverrideCursor wc;
+        ensureShaperIsActivated();
         res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
       }
       if ( !res )
@@ -911,15 +1000,11 @@ void SalomeApp_Application::onDumpStudy( )
 /*!Private SLOT. On load script.*/
 void SalomeApp_Application::onLoadScript( )
 {
-  SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
-  if ( appStudy ) {
-    _PTR(Study) aStudy = appStudy->studyDS();
-    if ( aStudy->GetProperties()->IsLocked() ) {
-      SUIT_MessageBox::warning( desktop(),
-                                QObject::tr("WRN_WARNING"),
-                                QObject::tr("WRN_STUDY_LOCKED") );
-      return;
-    }
+  if ( getStudy()->GetProperties()->IsLocked() ) {
+    SUIT_MessageBox::warning( desktop(),
+                              QObject::tr("WRN_WARNING"),
+                              QObject::tr("WRN_STUDY_LOCKED") );
+    return;
   }
 
   QStringList filtersList;
@@ -934,13 +1019,12 @@ void SalomeApp_Application::onLoadScript( )
 
   if ( !aFile.isEmpty() )
   {
-    QString command = QString("execfile(r\"%1\")").arg(aFile);
-
 #ifndef DISABLE_PYCONSOLE
+    QString command = QString("exec(compile(open('%1', 'rb').read(), '%1', 'exec'))").arg(aFile);
     PyConsole_Console* pyConsole = pythonConsole();
-
+    PropertyMgr propm( this, "IsLoadedScript", true );
     if ( pyConsole )
-      pyConsole->exec( command );
+      pyConsole->exec(command);
 #endif
   }
 }
@@ -969,14 +1053,6 @@ void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
     objectBrowserColumnsVisibility();
 }
 
-/*!Gets file filter.
- *\retval QString "(*.hdf)"
- */
-QString SalomeApp_Application::getFileFilter() const
-{
-  return "(*.hdf)";
-}
-
 /*!Create window.*/
 QWidget* SalomeApp_Application::createWindow( const int flag )
 {
@@ -1068,14 +1144,11 @@ QWidget* SalomeApp_Application::createWindow( const int flag )
   }
   else if ( flag == WT_NoteBook )
   {
-    SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
-    if ( appStudy ) {
-      _PTR(Study) aStudy = appStudy->studyDS();
-      setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
-      //to receive signal in NoteBook that it's variable was modified
-      connect( this, SIGNAL( notebookVarUpdated( QString ) ),
-               getNoteBook(), SLOT( onVarUpdate( QString ) ) );
-    }
+    setNoteBook( new SalomeApp_NoteBook( desktop() ) );
+    //to receive signal in NoteBook that it's variable was modified
+    connect( this, SIGNAL( notebookVarUpdated( QString ) ),
+             getNoteBook(), SLOT( onVarUpdate( QString ) ) );
+
     wid = getNoteBook();
     wid->setObjectName( "noteBook" );
   }
@@ -1124,16 +1197,10 @@ void SalomeApp_Application::updateDesktopTitle() {
   {
     QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
     if ( !sName.isEmpty() ) {
-      SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
-      if ( study ) {
-        _PTR(Study) stdDS = study->studyDS();
-        if(stdDS) {
-          if ( stdDS->GetProperties()->IsLocked() ) {
-            aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
-          } else {
-            aTitle += QString( " - [%1]" ).arg( sName );
-          }
-        }
+      if ( getStudy()->GetProperties()->IsLocked() ) {
+        aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
+      } else {
+        aTitle += QString( " - [%1]" ).arg( sName );
       }
     }
   }
@@ -1141,14 +1208,14 @@ void SalomeApp_Application::updateDesktopTitle() {
   desktop()->setWindowTitle( aTitle );
 }
 
-int SalomeApp_Application::closeChoice( const QString& docName )
+int SalomeApp_Application::closeChoice( const QString& /*docName*/ )
 {
   QStringList buttons;
   QMap<int, int> choices;
   int idx = 0;
-  buttons << tr ("APPCLOSE_SAVE");                // Save & Close
+  buttons << tr ("APPCLOSE_SAVE");                // Save & Clear
   choices.insert( idx++, CloseSave );             // ...
-  buttons << tr ("APPCLOSE_CLOSE");               // Close w/o saving
+  buttons << tr ("APPCLOSE_CLOSE");               // Clear w/o saving
   choices.insert( idx++, CloseDiscard );          // ...
   if ( myIsCloseFromExit ) {
     buttons << tr ("APPCLOSE_UNLOAD_SAVE");       // Save & Disconnect
@@ -1159,6 +1226,8 @@ int SalomeApp_Application::closeChoice( const QString& docName )
   buttons << tr ("APPCLOSE_CANCEL");              // Cancel
   choices.insert( idx++, CloseCancel );           // ...
 
+  if( !activeStudy()->isModified() )
+    return CloseCancel;
   int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
                                           tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
   return choices[answer];
@@ -1182,6 +1251,7 @@ bool SalomeApp_Application::closeAction( const int choice, bool& closePermanentl
       onSaveDoc();
     else if ( !onSaveAsDoc() )
       res = false;
+    // fall through!
   case CloseDisconnect:
     closeActiveDoc( false );
     closePermanently = false;
@@ -1200,12 +1270,9 @@ int SalomeApp_Application::openChoice( const QString& aName )
   if ( QFileInfo( aName ).exists() ) {
     if ( choice == OpenNew ) { // The document isn't already open.
       bool exist = false;
-      std::vector<std::string> lst = studyMgr()->GetOpenStudies();
-      for ( uint i = 0; i < lst.size() && !exist; i++ ) {
-        if ( aName == QString( lst[i].c_str() ) )
-          exist = true;
-      }
-      // The document already exists in the study manager.
+      if ( aName == getStudy()->Name().c_str() )
+        exist = true;
+      // The document already exists in the study.
       // Do you want to reload it?
       if ( exist ) {
         int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
@@ -1219,7 +1286,7 @@ int SalomeApp_Application::openChoice( const QString& aName )
   } else { // file is not exist on disk
     SUIT_MessageBox::warning( desktop(),
                               QObject::tr("WRN_WARNING"),
-                              QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
+                              QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toUtf8().data()));
     return false;
   }
 
@@ -1233,14 +1300,8 @@ bool SalomeApp_Application::openAction( const int aChoice, const QString& aName
   switch ( choice )
   {
   case OpenRefresh:
-    {
-      _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
-      if ( aStudy )
-      {
-        studyMgr()->Close( aStudy );
-        choice = OpenNew;
-      }
-    }
+    choice = OpenNew;
+    // fall through!
   default:
     res = LightApp_Application::openAction( choice, aName );
     break;
@@ -1305,26 +1366,29 @@ CORBA::ORB_var SalomeApp_Application::orb()
 
   if ( CORBA::is_nil( _orb ) ) {
     Qtx::CmdLineArgs args;
-    ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
-    _orb = init( args.argc(), args.argv() );
+    SetArgcArgv( args.argc(), args.argv() );
+    _orb = KERNEL::GetRefToORB();
   }
 
   return _orb;
 }
 
-/*!Create and return SALOMEDS_StudyManager.*/
-SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
+/*!Create and return SALOMEDS_Study.*/
+_PTR(Study) SalomeApp_Application::getStudy()
 {
-  static _PTR(StudyManager) _sm;
-  if(!_sm) _sm = ClientFactory::StudyManager();
-  return _sm.get();
+  static _PTR(Study) _study;
+  if(!_study) {
+    CORBA::Object_var aSObject = namingService()->Resolve("/Study");
+    SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(aSObject);
+    _study = ClientFactory::Study(aStudy);
+  }
+  return _study;
 }
 
 /*!Create and return SALOME_NamingService.*/
-SALOME_NamingServiceSalomeApp_Application::namingService()
+SALOME_NamingService_Abstract *SalomeApp_Application::namingService()
 {
-  static SALOME_NamingService _ns(orb());
-  return &_ns;
+  return _ns.get();
 }
 
 /*!Create and return SALOME_LifeCycleCORBA.*/
@@ -1388,71 +1452,66 @@ void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePop
 
   // isInvalidRefs will be true, if at least one of selected objects is invalid reference
   bool isInvalidRefs = false;
-  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
-  if ( aStudy ) {
-    _PTR(Study) aStudyDS = aStudy->studyDS();
-    _PTR(SObject) anObj;
 
-    for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
+  _PTR(SObject) anObj;
+  for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
+  {
+    if( it.Value()->hasEntry() )
     {
-      if( it.Value()->hasEntry() )
-      {
-        _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
-        while( aRefObj && aRefObj->ReferencedObject( anObj ) )
-          aRefObj = anObj;
+      _PTR(SObject) aSObject = getStudy()->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
+      while( aRefObj && aRefObj->ReferencedObject( anObj ) )
+        aRefObj = anObj;
 
-        if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
-          isInvalidRefs = true;
-      }
+      if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
+        isInvalidRefs = true;
     }
+  }
 
-    // Add "Delete reference" item to popup
-    if ( isInvalidRefs )
-    {
-      thePopup->addSeparator();
-      thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
-      return;
-    }
+  // Add "Delete reference" item to popup
+  if ( isInvalidRefs )
+  {
+    thePopup->addSeparator();
+    thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
+    return;
+  }
 
-    // "Activate module" item should appear only if it's necessary
-    if ( aList.Extent() == 1 ) {
-      aList.Clear();
-      mgr->selectedObjects( aList );
-
-      Handle(SALOME_InteractiveObject) aIObj = aList.First();
-
-      // add extra popup menu (defined in XML)
-      if ( myExtActions.size() > 0 ) {
-        // Use only first selected object
-        SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
-        if ( study ) {
-          _PTR(Study) stdDS = study->studyDS();
-          if ( stdDS ) {
-            _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
-            if ( aSO ) {
-              _PTR( GenericAttribute ) anAttr;
-              std::string auid = "AttributeUserID";
-              auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
-              if ( aSO->FindAttribute( anAttr, auid ) ) {
-                _PTR(AttributeUserID) aAttrID = anAttr;
-                QString aId = aAttrID->Value().c_str();
-                if ( myExtActions.contains( aId ) ) {
-                  thePopup->addAction(myExtActions[aId]);
-                }
-              }
-            }
+  // "Activate module" item should appear only if it's necessary
+  if ( aList.Extent() == 1 ) {
+    aList.Clear();
+    mgr->selectedObjects( aList );
+
+    Handle(SALOME_InteractiveObject) aIObj = aList.First();
+
+    // add extra popup menu (defined in XML)
+    if ( myExtActions.size() > 0 ) {
+      // Use only first selected object
+      _PTR(SObject) aSO = getStudy()->FindObjectID( aIObj->getEntry() );
+      if ( aSO ) {
+        _PTR( GenericAttribute ) anAttr;
+        std::string auid = "AttributeUserID";
+        auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
+        if ( aSO->FindAttribute( anAttr, auid ) ) {
+          _PTR(AttributeUserID) aAttrID = anAttr;
+          QString aId = aAttrID->Value().c_str();
+          if ( myExtActions.contains( aId ) ) {
+            thePopup->addAction(myExtActions[aId]);
           }
         }
       }
+    }
 
-      // check if item is a "GUI state" item (also a first level object)
-      QString entry( aIObj->getEntry() );
-      if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
-        QString aModuleName( aIObj->getComponentDataType() );
-        QString aModuleTitle = moduleTitle( aModuleName );
-        CAM_Module* currentModule = activeModule();
-        if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
-          thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
+    // check if item is a "GUI state" item (also a first level object)
+    QString entry( aIObj->getEntry() );
+    if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
+      QString aModuleName( aIObj->getComponentDataType() );
+      QString aModuleTitle = moduleTitle( aModuleName );
+      if (aModuleTitle.isEmpty()) {
+        // use displayer module, if given
+        aModuleTitle = moduleDisplayer( aModuleName );
+      }
+      CAM_Module* currentModule = activeModule();
+      if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() ) {
+        thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
       }
     }
   }
@@ -1470,25 +1529,21 @@ void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
   if ( study )
   {
-    _PTR(Study) stdDS = study->studyDS();
-    if( stdDS )
+    for ( _PTR(SComponentIterator) it ( getStudy()->NewComponentIterator() ); it->More(); it->Next() )
     {
-      for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
-      {
-        _PTR(SComponent) aComponent ( it->Value() );
+      _PTR(SComponent) aComponent ( it->Value() );
 
 #ifndef WITH_SALOMEDS_OBSERVER
-        // with GUI observers this check is not needed anymore
-        if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
-          continue; // skip the magic "Interface Applicative" component
+      // with GUI observers this check is not needed anymore
+      if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
+        continue; // skip the magic "Interface Applicative" component
 #endif
-        if ( !objectBrowser() )
-          getWindow( WT_ObjectBrowser );
-        const bool isAutoUpdate = objectBrowser()->autoUpdate();
-        objectBrowser()->setAutoUpdate( false );
-        SalomeApp_DataModel::synchronize( aComponent, study );
-        objectBrowser()->setAutoUpdate( isAutoUpdate );
-      }
+      if ( !objectBrowser() )
+        getWindow( WT_ObjectBrowser );
+      const bool isAutoUpdate = objectBrowser()->autoUpdate();
+      objectBrowser()->setAutoUpdate( false );
+      SalomeApp_DataModel::synchronize( aComponent, study );
+      objectBrowser()->setAutoUpdate( isAutoUpdate );
     }
   }
 
@@ -1536,6 +1591,7 @@ void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
     if ( !aSelectedIndexes.isEmpty() )
       ob->treeView()->scrollTo( aSelectedIndexes.first() );
   }
+  emit objectDoubleClicked( theObj );
 }
 
 /*!
@@ -1688,7 +1744,7 @@ void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
 
   // iterate new save points.  if DataObject with such ID not found in map - create DataObject
   // if in the map - remove it from map.
-  for ( int i = 0; i < savePoints.size(); i++ )
+  for ( size_t i = 0; i < savePoints.size(); i++ )
     if ( !mapDO.contains( savePoints[i] ) )
       new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
     else
@@ -1864,7 +1920,7 @@ bool SalomeApp_Application::renameAllowed( const QString& entry) const
   \param name new name of the object
   \brief Return \c true if rename operation finished successfully, \c false otherwise.
 */
-bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
+bool SalomeApp_Application::renameObject( const QString& /*entry*/, const QString& name )
 {
   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
 
@@ -1915,10 +1971,9 @@ bool SalomeApp_Application::updateStudy()
   myNoteBook->setIsDumpedStudySaved( study->isSaved() );
   myNoteBook->setDumpedStudyName( study->studyName() );
 
-  _PTR(Study) studyDS = study->studyDS();
-
   // get unique temporary directory name
   QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
+
   if( aTmpDir.isEmpty() )
     return false;
 
@@ -1934,12 +1989,12 @@ bool SalomeApp_Application::updateStudy()
   int savePoint;
   _PTR(AttributeParameter) ap;
   _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
-  if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //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(studyDS);
+    ip->setDumpPython();
     savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
   }
-  bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
+  bool ok = getStudy()->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
   if ( toSaveGUI )
     study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
 
@@ -2005,16 +2060,18 @@ bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
 
   // load study from the temporary directory
-  QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
+  QFileInfo aScriptInfo = QFileInfo(theDumpScript);
+  QString command = QString( "exec(open(\"%1\" ,\"rb\").read())" ).arg(aScriptInfo.canonicalFilePath());
 
 #ifndef DISABLE_PYCONSOLE
   PyConsole_Console* pyConsole = app->pythonConsole();
-  if ( pyConsole )
+  if ( pyConsole ) {
+    PropertyMgr propm( this, "IsLoadedScript", true );
     pyConsole->execAndWait( command );
+  }
 #endif
 
   // remove temporary directory
-  QFileInfo aScriptInfo = QFileInfo( theDumpScript );
   QString aStudyName = aScriptInfo.baseName();
   QDir aDir = aScriptInfo.absoluteDir();
   QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
@@ -2026,8 +2083,8 @@ bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
   if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
   {
 #ifndef DISABLE_PYCONSOLE
-    _PTR(Study) aStudyDS = newStudy->studyDS();
-    app->getNoteBook()->Init( aStudyDS );
+    if ( app->getNoteBook() )
+      app->getNoteBook()->Init();
     newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
     newStudy->Modified();
     updateDesktopTitle();
@@ -2056,23 +2113,20 @@ void SalomeApp_Application::afterCloseDoc()
   LightApp_Application::afterCloseDoc();
 }
 
+bool SalomeApp_Application::canOpenDoc( const QString& url )
+{
+  _PTR(Study) aStudyDS = getStudy();
+  if ( aStudyDS )
+    return aStudyDS->CanOpen( url.toUtf8().data() );
+  return false;
+}
+
 /*
   Asks to close existing document.
 */
 bool SalomeApp_Application::checkExistingDoc()
 {
-  bool result = LightApp_Application::checkExistingDoc();
-  if ( result && !activeStudy() ) {
-    SALOMEDSClient_StudyManager* aMgr = studyMgr();
-    if ( aMgr ) {
-      std::vector<std::string> List = studyMgr()->GetOpenStudies();
-      if( List.size() > 0 ) {
-        SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
-        result = false;
-      }
-    }
-  }
-  return result;
+  return LightApp_Application::checkExistingDoc();
 }
 
 
@@ -2080,7 +2134,25 @@ bool SalomeApp_Application::checkExistingDoc()
 
 PyConsole_Interp* SalomeApp_Application::createPyInterp()
 {
-  return new SalomeApp_PyInterp();
+  return new SalomeApp_PyInterp( resourceMgr() );
 }
 
 #endif // DISABLE_PYCONSOLE
+
+void SalomeApp_Application::ensureShaperIsActivated()
+{
+  SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
+  _PTR(Study) studyDS = getStudy();
+  if ( study && studyDS )
+  {
+    _PTR(SObject) shaper = studyDS->FindObjectByPath("/Shaper"); // non null result if shaper data is present in the study
+    bool shaperIsActive = false;
+    QList<CAM_DataModel*> models;
+    study->dataModels( models );
+    for( int i = 0; i < models.count() && !shaperIsActive; i++ )
+      shaperIsActive = models[i]->module()->moduleName() == "Shaper";
+       
+    if (shaper && !shaperIsActive)
+      onDesktopMessage("register_module_in_study/Shaper");
+  }
+}