Salome HOME
Merge Python 3 porting.
[modules/gui.git] / src / SalomeApp / SalomeApp_Application.cxx
index fb974086a328efb353da385fa5091d575b9f42b8..2dec0819855955b2435cb3abdad9e360e75bb22f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  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
@@ -6,7 +6,7 @@
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 // Created:   10/22/2004 3:23:45 PM
 // Author:    Sergey LITONIN
 
-#ifdef WNT
-// E.A. : On windows with python 2.6, there is a conflict
-// E.A. : between pymath.h and Standard_math.h which define
-// E.A. : some same symbols : acosh, asinh, ...
-#include <Standard_math.hxx>
-#include <pymath.h>
+#ifdef WIN32
+  // E.A. : On windows with python 2.6, there is a conflict
+  // E.A. : between pymath.h and Standard_math.h which define
+  // E.A. : some same symbols : acosh, asinh, ...
+  #include <Standard_math.hxx>
+  #ifndef DISABLE_PYCONSOLE
+    #include <pymath.h>
+  #endif
 #endif
 
-#include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
+#ifndef DISABLE_PYCONSOLE
+  #include "SalomeApp_PyInterp.h"
+  #include "SalomeApp_NoteBook.h"
+  #include "LightApp_PyEditor.h"
+  #include "PyConsole_Console.h"
+#endif
 #include "SalomeApp_Application.h"
 #include "SalomeApp_Study.h"
 #include "SalomeApp_DataModel.h"
 #include "SalomeApp_VisualState.h"
 #include "SalomeApp_StudyPropertiesDlg.h"
 #include "SalomeApp_LoadStudiesDlg.h"
-#include "SalomeApp_NoteBook.h"
-
 #include "SalomeApp_ExitDlg.h"
 
 #include <LightApp_Application.h>
+#include <LightApp_FileValidator.h>
 #include <LightApp_Module.h>
 #include <LightApp_Preferences.h>
 #include <LightApp_SelectionMgr.h>
 #include <LightApp_NameDlg.h>
 #include <LightApp_DataOwner.h>
-#include <LightApp_Displayer.h>
 
 #include <CAM_Module.h>
 
@@ -59,7 +64,6 @@
 #include <SUIT_Desktop.h>
 #include <SUIT_DataBrowser.h>
 #include <SUIT_FileDlg.h>
-#include <SUIT_FileValidator.h>
 #include <SUIT_MessageBox.h>
 #include <SUIT_ResourceMgr.h>
 #include <SUIT_TreeModel.h>
 // temporary commented
 //#include <OB_ListItem.h>
 
-#include <PyConsole_Console.h>
 
 #include <Utils_ORB_INIT.hxx>
 #include <Utils_SINGLETON.hxx>
 #include <SALOME_LifeCycleCORBA.hxx>
 
 #include <QApplication>
+#include <QWidget>
 #include <QAction>
 #include <QRegExp>
 #include <QCheckBox>
 #include <Basics_Utils.hxx>
 
 #include <SALOME_ListIO.hxx>
-#include <SALOME_ListIteratorOfListIO.hxx>
 #include <SALOME_Prs.h>
 
 
@@ -160,10 +163,9 @@ extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
 
 /*!Constructor.*/
 SalomeApp_Application::SalomeApp_Application()
-  : LightApp_Application()
+  : LightApp_Application(),
+    myIsCloseFromExit( false )
 {
-  connect( desktop(), SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
-           this,      SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
 }
 
 /*!Destructor.
@@ -175,13 +177,29 @@ SalomeApp_Application::~SalomeApp_Application()
   //SALOME_EventFilter::Destroy();
 }
 
+QStringList __getArgsList(QString argsString)
+{
+  // Special process if some items of 'args:' list are themselves lists
+  // Note that an item can be a list, but not a list of lists...
+  // So we can have something like this:
+  // myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok"
+  // With such a call, argsString variable contains the string representing "[file1,file2]", "val1", "done", "[1,2,3]", "[True,False]", "ok"
+  // We have to split argsString to obtain: [[file1,file2],val1,done,[1,2,3],[True,False],ok]
+  argsString.replace("\\\"", "'"); // replace escaped double quotes by simple quotes
+  bool containsList = (QRegExp("(\\[[^\\]]*\\])").indexIn(argsString) >= 0);
+  if (containsList) {
+    QStringList sl = argsString.split("\"", QString::SkipEmptyParts);
+    sl.removeAll(", ");
+    return sl;
+  }
+  else
+    return argsString.split(",", QString::SkipEmptyParts);
+}
+
 /*!Start application.*/
 void SalomeApp_Application::start()
 {
-  LightApp_Application::start();
-
-  SALOME_EventFilter::Init();
-
+  // process the command line options before start: to createActions in accordance to the options
   static bool isFirst = true;
   if ( isFirst ) {
     isFirst = false;
@@ -189,9 +207,9 @@ void SalomeApp_Application::start()
     QString hdffile;
     QStringList pyfiles;
 
-    for (int i = 1; i < qApp->argc(); i++) {
+    for (int i = 1; i < qApp->arguments().size(); i++) {
       QRegExp rxs ("--study-hdf=(.+)");
-      if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
+      if ( rxs.indexIn( qApp->arguments()[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) {
         QString file = rxs.capturedTexts()[1];
         QFileInfo fi ( file );
         QString extension = fi.suffix().toLower();
@@ -199,66 +217,72 @@ void SalomeApp_Application::start()
           hdffile = fi.absoluteFilePath();
       }
       else {
-        QRegExp rxp ("--pyscript=(.+)");
-        if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
-          QStringList files = rxp.capturedTexts()[1].split(",",QString::SkipEmptyParts);
-          pyfiles += files;
+        QRegExp rxp ("--pyscript=\\[(.+)\\]");
+        if ( rxp.indexIn( qApp->arguments()[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) {
+          // pyscript
+          QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
+          for (int k = 0; k < dictList.count(); ++k) {
+            QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
+            if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
+              for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
+                pyfiles += rxd.capturedTexts()[m];
+              }
+            }
+          }
         }
       }
     }
+    // Here pyfiles elements are: "script_name": [list_of_"arg"s]
+    // For example: "/absolute/path/to/my_script.py": ["1", "2"]
+
+    LightApp_Application::start();
+    SALOME_EventFilter::Init();
 
-    if ( !hdffile.isEmpty() )       // open hdf file given as parameter
+    setProperty("open_study_from_command_line", true);
+    if ( !hdffile.isEmpty() ) // open hdf file given as parameter
       onOpenDoc( hdffile );
-    else if ( pyfiles.count() > 0 ) // create new study
-      onNewDoc();
+    setProperty("open_study_from_command_line", QVariant());
 
+#ifndef DISABLE_PYCONSOLE
     // import/execute python scripts
     if ( pyfiles.count() > 0 && activeStudy() ) {
       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++ ) {
-            QFileInfo fi ( pyfiles[j] );
-            QFileInfo fipy ( pyfiles[j] + ".py" );
-            QString command = QString( "execfile(r\"%1\")" );
-            if ( fi.isAbsolute() ) {
-              if ( fi.exists() )
-                pyConsole->exec( command.arg( fi.absoluteFilePath() ) );
-              else if ( fipy.exists() )
-                pyConsole->exec( command.arg( fipy.absoluteFilePath() ) );
-              else
-                qDebug() << "Can't execute file" << pyfiles[j];
-            }
-            else {
-              bool found = false;
-              QStringList dirs;
-              dirs << QDir::currentPath();
-              if ( ::getenv( "PYTHONPATH" ) )
-                dirs += QString( ::getenv( "PYTHONPATH" ) ).split( QRegExp( "[:|;]" ) );
-              foreach( QString dir, dirs ) {
-                qDebug() << "try" << QFileInfo( dir, pyfiles[j] ).absoluteFilePath();
-                qDebug() << "try" << QFileInfo( dir, pyfiles[j] + ".py" ).absoluteFilePath();
-                if ( QFileInfo( dir, pyfiles[j] ).exists() ) {
-                  pyConsole->exec( command.arg( QFileInfo( dir, pyfiles[j] ).absoluteFilePath() ) );
-                  found = true;
-                  break;
-                }
-                else if ( QFileInfo( dir, pyfiles[j] + ".py" ).exists() ) {
-                  pyConsole->exec( command.arg( QFileInfo( dir, pyfiles[j] + ".py" ).absoluteFilePath() ) );
-                  found = true;
-                  break;
-                }
+            // 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 argList = __getArgsList(rxp.capturedTexts()[2]);
+              for (uint k = 0; k < argList.count(); k++ ) {
+                QString arg = argList[k].trimmed();
+                arg.remove( QRegExp("^[\"]") );
+                arg.remove( QRegExp("[\"]$") );
+                args += arg+",";
               }
-              if ( !found ) {
-                qDebug() << "Can't execute file" << pyfiles[j];
+              args.remove( QRegExp("[,]$") );
+              if (!args.isEmpty()) {
+                args = "args:"+args;
               }
+
+              script.remove( QRegExp("^python.*[\\s]+") );
+              QString cmd = script+" "+args;
+              QString command = QString( "exec(open(\"%1\").read())" ).arg(cmd.trimmed());
+              pyConsole->exec(command);
             }
-          }
+          } // end for loop on pyfiles QStringList
         }
       }
     }
+#endif
+  } else {
+    LightApp_Application::start();
+    SALOME_EventFilter::Init();
   }
 }
 
@@ -279,7 +303,7 @@ void SalomeApp_Application::createActions()
   createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
                 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
                 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
-  
+
   //! Load script
   createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
                 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
@@ -300,12 +324,17 @@ void SalomeApp_Application::createActions()
                 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
                 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
 
-  //SRN: BugID IPAL9021, add an action "Load"
-  createAction( FileLoadId, tr( "TOT_DESK_FILE_LOAD" ),
-                resourceMgr()->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ),
-                tr( "MEN_DESK_FILE_LOAD" ), tr( "PRP_DESK_FILE_LOAD" ),
+  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() ) );
-  //SRN: BugID IPAL9021: End
+  //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 );
@@ -314,10 +343,11 @@ void SalomeApp_Application::createActions()
   // creation of menu item is moved to VISU
   //  createMenu( SaveGUIStateId, fileMenu, 10, -1 );
 
-  createMenu( FileLoadId,   fileMenu, 0 );  //SRN: BugID IPAL9021, add a menu item "Load"
+  createMenu( ConnectId,    fileMenu, 5 );
+  createMenu( DisconnectId, fileMenu, 5 );
+  createMenu( separator(),  fileMenu, -1, 5 );
 
   createMenu( DumpStudyId, fileMenu, 10, -1 );
-  createMenu( separator(), fileMenu, -1, 10, -1 );
   createMenu( LoadScriptId, fileMenu, 10, -1 );
   createMenu( separator(), fileMenu, -1, 10, -1 );
   createMenu( PropertiesId, fileMenu, 10, -1 );
@@ -330,31 +360,22 @@ void SalomeApp_Application::createActions()
 
   createExtraActions();
 
+#ifndef DISABLE_PYCONSOLE
+#ifndef DISABLE_SALOMEOBJECT
   // import Python module that manages SALOME plugins
-  PyGILState_STATE gstate = PyGILState_Ensure();
-  PyObject* pluginsmanager=PyImport_ImportModule((char*)"salome_pluginsmanager");
-  PyObject* res=PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_PLUGINS_TOOLS").toStdString().c_str(),tr("MEN_DESK_PLUGINS").toStdString().c_str());
-  if(res==NULL)
-    PyErr_Print();
-  Py_XDECREF(res);
-  Py_XDECREF(pluginsmanager);
-  PyGILState_Release(gstate);
+  {
+    PyLockWrapper lck; // acquire GIL
+    PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
+    PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_TOOLS").toUtf8().data(),tr("MEN_DESK_PLUGINS").toUtf8().data());
+    if ( !res )
+      PyErr_Print();
+  }
   // end of SALOME plugins loading
+#endif
+#endif
 
 }
 
-
-/*!Set desktop:*/
-void SalomeApp_Application::setDesktop( SUIT_Desktop* desk )
-{
-  LightApp_Application::setDesktop( desk );
-
-  if ( desk ) {
-    connect( desk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
-             this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
-  }
-}
-
 /*!
   \brief Close application.
 */
@@ -369,8 +390,11 @@ void SalomeApp_Application::onExit()
     killServers = dlg.isServersShutdown();
   }
 
-  if ( result )
+  if ( result ) {
+    if ( !killServers ) myIsCloseFromExit = true;
     SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
+    if ( SUIT_Session::session()->applications().count() > 0 ) myIsCloseFromExit = false;
+  }
 }
 
 /*!SLOT. Load document.*/
@@ -378,8 +402,11 @@ void SalomeApp_Application::onLoadDoc()
 {
   QString studyName;
 
-  std::vector<std::string> List = studyMgr()->GetOpenStudies();
+  // rnv: According to the single-study approach on the server side
+  //      can be only one study. So if it is exists connect to them,
+  //      overwise show warning message: "No active study on the server"
 
+  /*
   SUIT_Session* aSession = SUIT_Session::session();
   QList<SUIT_Application*> aAppList = aSession->applications();
 
@@ -401,10 +428,19 @@ void SalomeApp_Application::onLoadDoc()
      if ( !isAlreadyOpen )
        unloadedStudies << studyName;
   }
-
   studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
   if ( studyName.isEmpty() )
     return;
+  */
+
+  if(!activeStudy()) {
+    SUIT_MessageBox::warning( desktop(),
+                              QObject::tr("WRN_WARNING"),
+                              QObject::tr("WRN_NO_STUDY_ON SERV") );
+    return;
+  }
+
+  studyName = activeStudy()->studyName();
 
 #ifndef WIN32
   // this code replaces marker of windows drive and path become invalid therefore
@@ -419,6 +455,31 @@ void SalomeApp_Application::onLoadDoc()
   }
 }
 
+/*!SLOT. Unload document.*/
+void SalomeApp_Application::onUnloadDoc( bool ask )
+{
+  if ( ask ) {
+    activeStudy()->abortAllOperations();
+    if ( activeStudy()->isModified() ) {
+      QString docName = activeStudy()->studyName().trimmed();
+      int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
+                                            tr( "DISCONNECT_DESCRIPTION" ),
+                                            tr( "DISCONNECT_SAVE" ),
+                                            tr( "DISCONNECT_WO_SAVE" ),
+                                            tr( "APPCLOSE_CANCEL" ), 0 );
+      if ( answer == 0 ) { // save before unload
+        if ( activeStudy()->isSaved() )
+          onSaveDoc();
+        else if ( !onSaveAsDoc() )
+          return;
+      }
+      else if ( answer == 2 ) // Cancel
+        return;
+    }
+  }
+  closeActiveDoc( false );
+}
+
 /*!SLOT. Create new study and load script*/
 void SalomeApp_Application::onNewWithScript()
 {
@@ -436,12 +497,14 @@ void SalomeApp_Application::onNewWithScript()
   {
     onNewDoc();
 
-    QString command = QString("execfile(r\"%1\")").arg(aFile);
+    QString command = QString("exec(open(\"%1\").read())").arg(aFile);
 
+#ifndef DISABLE_PYCONSOLE
     PyConsole_Console* pyConsole = pythonConsole();
 
     if ( pyConsole )
       pyConsole->exec( command );
+#endif
   }
 }
 
@@ -449,6 +512,9 @@ void SalomeApp_Application::onNewWithScript()
 /*!SLOT. Load document with \a aName.*/
 bool SalomeApp_Application::onLoadDoc( const QString& aName )
 {
+  if ( !LightApp_Application::closeDoc() )
+    return false;
+
   bool res = true;
   if ( !activeStudy() ) {
     // if no study - load in current desktop
@@ -479,6 +545,43 @@ bool SalomeApp_Application::onLoadDoc( const QString& aName )
   return res;
 }
 
+/*!SLOT. Parse message for desktop.*/
+void SalomeApp_Application::onDesktopMessage( const QString& message )
+{
+  if (message.indexOf("studyCreated") == 0) {
+    if (!activeStudy()) {
+      onNewDoc();
+      updateCommandsStatus();
+    }
+  }
+  if (message.indexOf("studyCleared") == 0) {
+    // Disconnect GUI from active study, because it was closed on DS side.
+    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 (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()
 {
@@ -489,7 +592,7 @@ 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 );
@@ -497,7 +600,7 @@ void SalomeApp_Application::onCopy()
     {
       _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
       try {
-        studyMgr()->Copy(so);
+        stdDS->Copy(so);
         onSelectionChanged();
       }
       catch(...) {
@@ -515,7 +618,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() ) {
@@ -530,7 +633,7 @@ void SalomeApp_Application::onPaste()
     {
       _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
       try {
-        studyMgr()->Paste(so);
+        stdDS->Paste(so);
         updateObjectBrowser( true );
         updateActions(); //SRN: BugID IPAL9377, case 3
       }
@@ -550,21 +653,18 @@ 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;
 
-    }
   }
-
   LightApp_Application::onCloseDoc( ask );
+
+  // reinitialize study to have empty data
+  getStudy()->Init();
 }
 
 /*!Sets enable or disable some actions on selection changed.*/
@@ -577,21 +677,21 @@ void SalomeApp_Application::onSelectionChanged()
    bool canCopy  = false;
    bool canPaste = false;
 
-   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
-   if (study != NULL) {
-     _PTR(Study) stdDS = study->studyDS();
+   LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
 
-     if (stdDS) {
-       SALOME_ListIteratorOfListIO it ( list );
+   if ( m ) {
+     canCopy  = m->canCopy();
+     canPaste = m->canPaste();
+   }
 
-       if (it.More() && list.Extent() == 1) {
-         _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
+   SALOME_ListIteratorOfListIO it ( list );
 
-         if ( so ) {
-             canCopy = studyMgr()->CanCopy(so);
-             canPaste = studyMgr()->CanPaste(so);
-         }
-       }
+   if (it.More() && list.Extent() == 1) {
+     _PTR(SObject) so = getStudy()->FindObjectID(it.Value()->getEntry());
+
+     if ( so ) {
+       canCopy  = canCopy  || getStudy()->CanCopy(so);
+       canPaste = canPaste || getStudy()->CanPaste(so);
      }
    }
 
@@ -609,8 +709,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;
 
@@ -659,9 +758,11 @@ SUIT_Study* SalomeApp_Application::createNewStudy()
   connect( aStudy, SIGNAL( saved  ( SUIT_Study* ) ), this, SLOT( onStudySaved  ( SUIT_Study* ) ) );
   connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
 
+#ifndef DISABLE_PYCONSOLE
   //to receive signal in application that NoteBook's variable was modified
-  connect( aStudy, SIGNAL(notebookVarUpdated(QString)), 
+  connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
            this, SIGNAL(notebookVarUpdated(QString)) );
+#endif
 
   return aStudy;
 }
@@ -678,10 +779,12 @@ void SalomeApp_Application::updateCommandsStatus()
   if ( a )
     a->setEnabled( activeStudy() );
 
+#ifndef DISABLE_PYCONSOLE
   // Load script menu
   a = action( LoadScriptId );
-  if ( a )
-    a->setEnabled( activeStudy() );
+  if( a )
+    a->setEnabled( pythonConsole() );
+#endif
 
   // Properties menu
   a = action( PropertiesId );
@@ -693,6 +796,16 @@ void SalomeApp_Application::updateCommandsStatus()
   if( a )
     a->setEnabled( activeStudy() );
 
+  // Connect study menu
+  a = action( ConnectId );
+  if( a )
+    a->setEnabled( !activeStudy() );
+
+  // Disconnect study menu
+  a = action( DisconnectId );
+  if( a )
+    a->setEnabled( activeStudy() );
+
   // update state of Copy/Paste menu items
   onSelectionChanged();
 }
@@ -736,32 +849,11 @@ public:
   QCheckBox* mySaveGUIChk;
 };
 
-class DumpStudyFileValidator : public SUIT_FileValidator
-{
- public:
-  DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
-  virtual ~DumpStudyFileValidator() {};
-  virtual bool canSave( const QString& file, bool permissions );
-};
-
-bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
-{
-  QFileInfo fi( file );
-  if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
-    SUIT_MessageBox::critical( parent(),
-                               QObject::tr("WRN_WARNING"),
-                               QObject::tr("WRN_FILE_NAME_BAD") );
-    return false;
-  }
-  return SUIT_FileValidator::canSave( file, permissions);
-}
-
 /*!Private SLOT. On dump study.*/
 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" ) );
@@ -777,9 +869,9 @@ void SalomeApp_Application::onDumpStudy( )
   }
 
   DumpStudyFileDlg fd( desktop() );
-  fd.setValidator( new DumpStudyFileValidator( &fd ) );
+  fd.setValidator( new LightApp_PyFileValidator( &fd ) );
   fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
-  fd.setFilters( aFilters );
+  fd.setNameFilters( aFilters );
   fd.myPublishChk->setChecked( anIsPublish );
   fd.myMultiFileChk->setChecked( anIsMultiFile );
   fd.mySaveGUIChk->setChecked( anIsSaveGUI );
@@ -795,7 +887,7 @@ void SalomeApp_Application::onDumpStudy( )
       QFileInfo aFileInfo(aFileName);
       if( aFileInfo.isDir() ) // IPAL19257
         return;
-      
+
       // Issue 21377 - dump study implementation moved to SalomeApp_Study class
       bool res;
       {
@@ -813,11 +905,7 @@ void SalomeApp_Application::onDumpStudy( )
 /*!Private SLOT. On load script.*/
 void SalomeApp_Application::onLoadScript( )
 {
-  SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
-  if ( !appStudy ) return;
-  _PTR(Study) aStudy = appStudy->studyDS();
-
-  if ( aStudy->GetProperties()->IsLocked() ) {
+  if ( getStudy()->GetProperties()->IsLocked() ) {
     SUIT_MessageBox::warning( desktop(),
                               QObject::tr("WRN_WARNING"),
                               QObject::tr("WRN_STUDY_LOCKED") );
@@ -836,12 +924,14 @@ void SalomeApp_Application::onLoadScript( )
 
   if ( !aFile.isEmpty() )
   {
-    QString command = QString("execfile(r\"%1\")").arg(aFile);
+    QString command = QString("exec(open(\"%1\").read())").arg(aFile);
 
+#ifndef DISABLE_PYCONSOLE
     PyConsole_Console* pyConsole = pythonConsole();
 
     if ( pyConsole )
       pyConsole->exec( command );
+#endif
   }
 }
 
@@ -857,19 +947,27 @@ void SalomeApp_Application::onSaveGUIState()
   updateActions();
 }
 
-/*!Gets file filter.
- *\retval QString "(*.hdf)"
- */
-QString SalomeApp_Application::getFileFilter() const
+/*!Public SLOT. Performs some actions when dockable windows are triggered.*/
+void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
 {
-  return "(*.hdf)";
+  LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
+  QAction* send = ::qobject_cast<QAction*>( sender() );
+  if ( !send )
+    return;
+  QString aWinName = send->data().toString();
+  if ( theIsVisible && aWinName == "objectBrowser" )
+    objectBrowserColumnsVisibility();
 }
 
 /*!Create window.*/
 QWidget* SalomeApp_Application::createWindow( const int flag )
 {
   QWidget* wid = 0;
+#ifndef DISABLE_PYCONSOLE
   if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
+#else
+  wid = LightApp_Application::createWindow(flag);
+#endif
 
   SUIT_ResourceMgr* resMgr = resourceMgr();
 
@@ -914,6 +1012,12 @@ QWidget* SalomeApp_Application::createWindow( const int flag )
       ob->setResizeOnExpandItem(resizeOnExpandItem);
       ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
 
+      for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
+      {
+        bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
+        ob->treeView()->setColumnHidden( i, !shown );
+      }
+
       // temporary commented
       /*
       for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
@@ -932,29 +1036,29 @@ QWidget* SalomeApp_Application::createWindow( const int flag )
       */
     }
   }
+#ifndef DISABLE_PYCONSOLE
   else if ( flag == WT_PyConsole )
   {
-    PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
+    PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new LightApp_PyEditor( getPyInterp() ) );
+    pyCons->setObjectName( "pythonConsole" );
     pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
     pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
     pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
+    pyCons->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) );
     pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
     wid = pyCons;
-    //pyCons->resize( pyCons->width(), desktop()->height()/4 );
-    pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
   }
   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" );
   }
+#endif
   return wid;
 }
 
@@ -999,16 +1103,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 );
       }
     }
   }
@@ -1018,19 +1116,27 @@ void SalomeApp_Application::updateDesktopTitle() {
 
 int SalomeApp_Application::closeChoice( const QString& docName )
 {
-  int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
-                                          tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
-                                          tr ("APPCLOSE_UNLOAD"), tr ("APPCLOSE_CANCEL"), 0 );
-
-  int res = CloseCancel;
-  if ( answer == 0 )
-    res = CloseSave;
-  else if ( answer == 1 )
-    res = CloseDiscard;
-  else if ( answer == 2 )
-    res = CloseUnload;
+  QStringList buttons;
+  QMap<int, int> choices;
+  int idx = 0;
+  buttons << tr ("APPCLOSE_SAVE");                // Save & Clear
+  choices.insert( idx++, CloseSave );             // ...
+  buttons << tr ("APPCLOSE_CLOSE");               // Clear w/o saving
+  choices.insert( idx++, CloseDiscard );          // ...
+  if ( myIsCloseFromExit ) {
+    buttons << tr ("APPCLOSE_UNLOAD_SAVE");       // Save & Disconnect
+    choices.insert( idx++, CloseDisconnectSave );     // ...
+    buttons << tr ("APPCLOSE_UNLOAD");            // Disconnect
+    choices.insert( idx++, CloseDisconnect );         // ...
+  }
+  buttons << tr ("APPCLOSE_CANCEL");              // Cancel
+  choices.insert( idx++, CloseCancel );           // ...
 
-  return res;
+  if( !activeStudy()->isModified() )
+    return CloseCancel;
+  int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
+                                          tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
+  return choices[answer];
 }
 
 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
@@ -1046,14 +1152,19 @@ bool SalomeApp_Application::closeAction( const int choice, bool& closePermanentl
     break;
   case CloseDiscard:
     break;
-  case CloseUnload:
+  case CloseDisconnectSave:
+    if ( activeStudy()->isSaved() )
+      onSaveDoc();
+    else if ( !onSaveAsDoc() )
+      res = false;
+  case CloseDisconnect:
+    closeActiveDoc( false );
     closePermanently = false;
     break;
   case CloseCancel:
   default:
     res = false;
   }
-
   return res;
 }
 
@@ -1064,12 +1175,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 ),
@@ -1098,12 +1206,7 @@ bool SalomeApp_Application::openAction( const int aChoice, const QString& aName
   {
   case OpenRefresh:
     {
-      _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
-      if ( aStudy )
-      {
-        studyMgr()->Close( aStudy );
-        choice = OpenNew;
-      }
+      choice = OpenNew;
     }
   default:
     res = LightApp_Application::openAction( choice, aName );
@@ -1131,7 +1234,9 @@ bool SalomeApp_Application::openAction( const int aChoice, const QString& aName
 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
 {
   QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
+
   opmap.insert( LoadStudyId,     tr( "ACTIVATE_MODULE_OP_LOAD" ) );
+
   opmap.insert( NewAndScriptId,  tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
   return opmap;
 }
@@ -1163,17 +1268,27 @@ void SalomeApp_Application::moduleActionSelected( const int id )
 /*!Gets CORBA::ORB_var*/
 CORBA::ORB_var SalomeApp_Application::orb()
 {
-  ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
-  static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
+  static CORBA::ORB_var _orb;
+
+  if ( CORBA::is_nil( _orb ) ) {
+    Qtx::CmdLineArgs args;
+    ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
+    _orb = init( args.argc(), args.argv() );
+  }
+
   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.*/
@@ -1244,20 +1359,20 @@ 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());
-  _PTR(Study) aStudyDS = aStudy->studyDS();
-  _PTR(SObject) anObj;
 
+  _PTR(SObject) anObj;
   for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
+  {
     if( it.Value()->hasEntry() )
     {
-      _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
+      _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;
     }
+  }
 
   // Add "Delete reference" item to popup
   if ( isInvalidRefs )
@@ -1277,22 +1392,16 @@ void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePop
     // 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]);
-              }
-            }
+      _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]);
           }
         }
       }
@@ -1322,25 +1431,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 );
     }
   }
 
@@ -1381,13 +1486,14 @@ void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
     SUIT_DataOwnerPtrList aList;
     aList.append( new LightApp_DataOwner( entry ) );
     selectionMgr()->setSelected( aList, false );
-    
+
     SUIT_DataBrowser* ob = objectBrowser();
 
     QModelIndexList aSelectedIndexes = ob->selectedIndexes();
     if ( !aSelectedIndexes.isEmpty() )
       ob->treeView()->scrollTo( aSelectedIndexes.first() );
   }
+  emit objectDoubleClicked( theObj );
 }
 
 /*!
@@ -1400,7 +1506,7 @@ SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
 }
 
 
-/*!Global utility funciton, returns selected GUI Save point object's ID */
+/*!Global utility function, returns selected GUI Save point object's ID */
 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
 {
   SALOME_ListIO aList;
@@ -1446,43 +1552,28 @@ void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
 {
   LightApp_Application::onStudyCreated( study );
 
-  desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ), 
-                               windowDock( getWindow( WT_ObjectBrowser ) ) );
+//#ifndef DISABLE_PYCONSOLE
+//  desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
+//                               windowDock( getWindow( WT_ObjectBrowser ) ) );
+//#endif
 
   loadDockWindowsState();
 
-  connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
-           this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
-
-
   objectBrowserColumnsVisibility();
 }
 
-/*!Called on Save study operation*/
-void SalomeApp_Application::onStudySaved( SUIT_Study* study )
-{
-  LightApp_Application::onStudySaved( study );
-
-  // temporary commented
-  /*if ( objectBrowser() ) {
-    updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
-    objectBrowser()->updateTree( study->root() );
-  }*/
-}
-
 /*!Called on Open study operation*/
 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
 {
   LightApp_Application::onStudyOpened( study );
 
-  desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ), 
-                               windowDock( getWindow( WT_ObjectBrowser ) ) );
+//#ifndef DISABLE_PYCONSOLE
+//  desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
+//                               windowDock( getWindow( WT_ObjectBrowser ) ) );
+//#endif
 
   loadDockWindowsState();
 
-  connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
-           this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
-
   objectBrowserColumnsVisibility();
 
   // temporary commented
@@ -1499,7 +1590,7 @@ void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
   SUIT_DataBrowser* ob = objectBrowser();
   LightApp_SelectionMgr* selMgr = selectionMgr();
 
-  if ( !study || !ob || !selMgr ) 
+  if ( !study || !ob || !selMgr )
     return;
 
   // find GUI states root object
@@ -1522,7 +1613,7 @@ void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
     selMgr->clearSelected();
     ob->setAutoUpdate(true);
     DataObjectList ch = guiRootObj->children();
-    for( int i = 0; i < ch.size(); i++ ) 
+    for( int i = 0; i < ch.size(); i++ )
       delete ch[i];
     delete guiRootObj;
     ob->setAutoUpdate(isAutoUpdate);
@@ -1610,6 +1701,7 @@ void SalomeApp_Application::objectBrowserColumnsVisibility()
     }
 }
 
+#ifndef DISABLE_PYCONSOLE
 /*! Set SalomeApp_NoteBook pointer */
 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
 {
@@ -1621,6 +1713,7 @@ SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
 {
   return myNoteBook;
 }
+#endif
 
 /*!
  * Define extra actions defined in module definition XML file.
@@ -1713,80 +1806,6 @@ void SalomeApp_Application::onExtAction()
     printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
 }
 
-/*!
- * Called when window activated
- */
-void SalomeApp_Application::onWindowActivated( SUIT_ViewWindow* theViewWindow )
-{
-  SUIT_DataBrowser* anOB = objectBrowser();
-  if( !anOB )
-    return;
-  SUIT_DataObject* rootObj = anOB->root();
-  if( !rootObj )
-    return;
-
-  DataObjectList listObj = rootObj->children( true );
-
-  SUIT_ViewModel* vmod = 0;
-  if ( SUIT_ViewManager* vman = theViewWindow->getViewManager() )
-    vmod = vman->getViewModel();
-  updateVisibilityState( listObj, vmod );
-}
-
-/*!
-  Update visibility state of given objects
- */
-void SalomeApp_Application::updateVisibilityState( DataObjectList& theList,
-                                                   SUIT_ViewModel*  theViewModel )
-{
-  LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
-
-  if(!theViewModel)
-    return;
-
-  SALOME_View* aView = dynamic_cast<SALOME_View*>( theViewModel );
-
-  if (theList.isEmpty() || !aView || !aStudy)
-    return;
-
-  for ( DataObjectList::iterator itr = theList.begin(); itr != theList.end(); ++itr ) {
-    LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>(*itr);
-
-    if (!obj || aStudy->isComponent(obj->entry()))
-      continue;
-
-    LightApp_Module* anObjModule = dynamic_cast<LightApp_Module*>(obj->module());
-    Qtx::VisibilityState anObjState = Qtx::UnpresentableState;
-
-    if(anObjModule) {
-      LightApp_Displayer* aDisplayer = anObjModule->displayer();
-      if(aDisplayer) {
-        if( aDisplayer->canBeDisplayed(obj->entry(), theViewModel->getType()) ) {
-          if(aDisplayer->IsDisplayed(obj->entry(),aView))
-            anObjState = Qtx::ShownState;
-          else
-            anObjState = Qtx::HiddenState;
-        }
-      }
-      aStudy->setVisibilityState( obj->entry(), anObjState );
-    }
-  }
-}
-
-/*!
-  Called then view manager removed
-*/
-void SalomeApp_Application::onViewManagerRemoved( SUIT_ViewManager* )
-{
-  ViewManagerList lst;
-  viewManagers(lst);
-  if( lst.count() == 1) { // in case if closed last view window
-    LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
-    if(aStudy)
-      aStudy->setVisibilityStateForAll(Qtx::UnpresentableState);
-  }
-}
-
 /*!
   Checks that an object can be renamed.
   \param entry entry of the object
@@ -1823,31 +1842,7 @@ bool SalomeApp_Application::renameObject( const QString& entry, const QString& n
   return false;
 }
 
-/*!
-  \return default windows( Object Browser, Python Console )
-  Adds to map \a aMap.
-*/
-void SalomeApp_Application::defaultWindows( QMap<int, int>& aMap ) const
-{
-  LightApp_Application::defaultWindows(aMap);
-  if ( !aMap.contains( WT_NoteBook ) ) { 
-    if ( !myNoteBook ) {
-      aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
-    }
-  }
-}
-
-/*!
-  Gets current windows.
-  \param winMap - output current windows map.
-*/
-void SalomeApp_Application::currentWindows(QMap<int, int>& aMap) const
-{
-  LightApp_Application::currentWindows( aMap );
-  if ( !aMap.contains( WT_NoteBook) && myNoteBook )
-    aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
-}
-
+#ifndef DISABLE_PYCONSOLE
 //============================================================================
 /*! Function : onUpdateStudy
  *  Purpose  : Slot to update the study.
@@ -1859,7 +1854,7 @@ void SalomeApp_Application::onUpdateStudy()
 
   if( !updateStudy() )
     SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
-    
+
   QApplication::restoreOverrideCursor();
 }
 
@@ -1878,8 +1873,6 @@ 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() )
@@ -1897,12 +1890,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.
 
@@ -1915,20 +1908,20 @@ bool SalomeApp_Application::updateStudy()
   int anIndex = aList.indexOf( this );
 
   // Disconnect dialog from application desktop in case if:
-  // 1) Application is not the first application in the session 
+  // 1) Application is not the first application in the session
   // 2) Application is the first application in session but not the only.
   bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
+  if( changeDesktop ) {
 
-  SalomeApp_Application* app;
-  if( anIndex > 0 && anIndex < aList.count() )
-    app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
-  else if(anIndex == 0 && aList.count() > 1)
-    app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
+    SalomeApp_Application* app = this;
+    if( anIndex > 0 && anIndex < aList.count() )
+      app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
+    else if(anIndex == 0 && aList.count() > 1)
+      app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
 
-  if( !app )
-    return false;
+    if( !app )
+      return false;
 
-  if( changeDesktop ) {
     // creation a new study and restoring will be done in another application
     connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
              app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
@@ -1941,37 +1934,37 @@ bool SalomeApp_Application::updateStudy()
   onCloseDoc( false );
 
   if( !changeDesktop ) {
-    ok = onRestoreStudy( aDumpScript, 
-                         aStudyName, 
+    ok = onRestoreStudy( aDumpScript,
+                         aStudyName,
                          isStudySaved );
   }
 
   return ok;
 }
+#endif
 
 //============================================================================
 /*! Function : onRestoreStudy
  *  Purpose  : Load the dumped study from Python script
  */
 //============================================================================
-bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript, 
-                                            const QString& theStudyName, 
+bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
+                                            const QString& theStudyName,
                                             bool theIsStudySaved )
 {
   bool ok = true;
 
-  // create a new study
-  onNewDoc();
-
   // get active application
   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 );
+  QString command = QString( "exec(open(\"%1\").read())" ).arg( theDumpScript );
 
+#ifndef DISABLE_PYCONSOLE
   PyConsole_Console* pyConsole = app->pythonConsole();
   if ( pyConsole )
     pyConsole->execAndWait( command );
+#endif
 
   // remove temporary directory
   QFileInfo aScriptInfo = QFileInfo( theDumpScript );
@@ -1985,12 +1978,14 @@ bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
 
   if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
   {
-    _PTR(Study) aStudyDS = newStudy->studyDS();
-    app->getNoteBook()->Init( aStudyDS );
+#ifndef DISABLE_PYCONSOLE
+    if ( app->getNoteBook() )
+      app->getNoteBook()->Init();
     newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
     newStudy->Modified();
     updateDesktopTitle();
     updateActions();
+#endif
   }
   else
     ok = false;
@@ -2001,13 +1996,33 @@ bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
 /*!
   Close the Application
 */
-void SalomeApp_Application::closeApplication()
+void SalomeApp_Application::afterCloseDoc()
 {
+#ifndef DISABLE_PYCONSOLE
   // emit signal to restore study from Python script
   if ( myNoteBook ) {
-    emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(), 
-                            myNoteBook->getDumpedStudyName(), 
+    emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
+                            myNoteBook->getDumpedStudyName(),
                             myNoteBook->isDumpedStudySaved() );
   }
-  LightApp_Application::closeApplication();
+#endif
+  LightApp_Application::afterCloseDoc();
+}
+
+/*
+  Asks to close existing document.
+*/
+bool SalomeApp_Application::checkExistingDoc()
+{
+  return LightApp_Application::checkExistingDoc();
 }
+
+
+#ifndef DISABLE_PYCONSOLE
+
+PyConsole_Interp* SalomeApp_Application::createPyInterp()
+{
+  return new SalomeApp_PyInterp;
+}
+
+#endif // DISABLE_PYCONSOLE