Salome HOME
bos #29467 SALOME GUI logger
[modules/gui.git] / src / SALOME_PYQT / SalomePyQt / SalomePyQt.cxx
index 75642bf48cc6c3bfe231bdb2af8d4748e37954e6..25efe528da1fd8165f57e18b5424be241d771667 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 
 #include "LightApp_SelectionMgr.h"
 #include "LogWindow.h"
+#ifndef DISABLE_OCCVIEWER
 #include "OCCViewer_ViewWindow.h"
+#include "OCCViewer_ViewFrame.h"
+#endif // DISABLE_OCCVIEWER
+#ifndef DISABLE_VTKVIEWER
+#include "SVTK_ViewWindow.h"
+#endif // DISABLE_VTKVIEWER
+#ifndef DISABLE_PLOT2DVIEWER
 #include "Plot2d_ViewManager.h"
 #include "Plot2d_ViewWindow.h"
+#endif // DISABLE_PLOT2DVIEWER
+#ifndef DISABLE_PVVIEWER
+#include "PVViewer_ViewManager.h"
+#include "PVViewer_ViewModel.h"
+#endif // DISABLE_PVVIEWER
+#ifndef DISABLE_PV3DVIEWER
+#include "PV3DViewer_ViewManager.h"
+#include "PV3DViewer_ViewModel.h"
+#endif // DISABLE_PV3DVIEWER
 #include "QtxActionMenuMgr.h"
 #include "QtxWorkstack.h"
 #include "QtxTreeView.h"
+#include "QtxInfoPanel.h"
 #include "SALOME_Event.h"
 #include "STD_TabDesktop.h"
 #include "SUIT_DataBrowser.h"
 #include "SUIT_ResourceMgr.h"
 #include "SUIT_Session.h"
 #include "SUIT_Tools.h"
+#include "SUIT_ViewManager.h"
+#include "SUIT_ViewWindow.h"
 #include "PyConsole_Console.h"
 
 #include <QAction>
 #include <QApplication>
 #include <QPaintEvent>
+#include <QCoreApplication>
+#include <QVBoxLayout>
 
-/*!
-  \brief Get the currently active application.
-  \internal
-  \return active application object or 0 if there is no any
-*/
-static LightApp_Application* getApplication()
-{
-  if ( SUIT_Session::session() )
-    return dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() );
-  return 0;
-}
+#include <utilities.h>
 
-/*!
-  \brief Get the currently active study.
-  \internal
-  \return active study or 0 if there is no study opened
-*/
-static LightApp_Study* getActiveStudy()
+namespace
 {
-  if ( getApplication() )
-    return dynamic_cast<LightApp_Study*>( getApplication()->activeStudy() );
-  return 0;
-}
+  /*!
+    \brief Get the currently active application.
+    \internal
+    \return active application object or 0 if there is no any
+  */
+  LightApp_Application* getApplication()
+  {
+    if ( SUIT_Session::session() )
+      return dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() );
+    return 0;
+  }
+  
+  /*!
+    \brief Get the currently active study.
+    \internal
+    \return active study or 0 if there is no study opened
+  */
+  LightApp_Study* getActiveStudy()
+  {
+    if ( getApplication() )
+      return dynamic_cast<LightApp_Study*>( getApplication()->activeStudy() );
+    return 0;
+  }
 
-/*!
-  \brief Get the currently active module.
-  \internal
-  This function returns correct result only if Python-based
-  module is currently active. Otherwize, 0 is returned.
-*/
-static LightApp_Module* getActiveModule()
-{
-  LightApp_Module* module = 0;
-  if ( LightApp_Application* anApp = getApplication() ) {
-    module = PyModuleHelper::getInitModule();
-    if ( !module )
-      module = dynamic_cast<LightApp_Module*>( anApp->activeModule() );
+  /*!
+    \brief Get the currently active module.
+    \internal
+    This function returns correct result only if Python-based
+    module is currently active. Otherwize, 0 is returned.
+  */
+  LightApp_Module* getActiveModule()
+  {
+    LightApp_Module* module = 0;
+    if ( LightApp_Application* anApp = getApplication() ) {
+      module = PyModuleHelper::getInitModule();
+      if ( !module )
+        module = dynamic_cast<LightApp_Module*>( anApp->activeModule() );
+    }
+    return module;
+  }
+  
+  /*!
+    \brief Get the currently active Python module's helper.
+    \internal
+    This function returns correct result only if Python-based
+    module is currently active. Otherwize, 0 is returned.
+  */
+  PyModuleHelper* getPythonHelper()
+  {
+    LightApp_Module* module = getActiveModule();
+    PyModuleHelper* helper = module ? module->findChild<PyModuleHelper*>( "python_module_helper" ) : 0;
+    return helper;
+  }
+  
+  /*!
+    \brief Get SALOME verbose level
+    \internal
+    \return \c true if SALOME debug output is allowed or \c false otherwise
+  */
+  bool verbose()
+  {
+    bool isVerbose = false;
+    if ( getenv( "SALOME_VERBOSE" ) ) {
+      QString envVar = getenv( "SALOME_VERBOSE" );
+      bool ok;
+      int value = envVar.toInt( &ok );
+      isVerbose = ok && value != 0;
+    }
+    return isVerbose;
   }
-  return module;
-}
 
-/*!
-  \brief Get the currently active Python module's helper.
-  \internal
-  This function returns correct result only if Python-based
-  module is currently active. Otherwize, 0 is returned.
-*/
-static PyModuleHelper* getPythonHelper()
-{
-  LightApp_Module* module = getActiveModule();
-  PyModuleHelper* helper = module ? qFindChild<PyModuleHelper*>( module, "python_module_helper" ) : 0;
-  return helper;
-}
+  /*!
+    \brief Get menu item title
+    \internal
+    \param menuId menu identifier
+    \return menu title (localized)
+  */
+  QString getMenuName( const QString& menuId )
+  {
+    QStringList contexts;
+    contexts << "SalomeApp_Application" << "LightApp_Application" << "STD_TabDesktop" <<
+      "STD_MDIDesktop" << "STD_Application" << "SUIT_Application" << "";
+    QString menuName = menuId;
+    for ( int i = 0; i < contexts.count() && menuName == menuId; i++ )
+      menuName = QApplication::translate( contexts[i].toLatin1().data(), menuId.toLatin1().data() );
+    return menuName;
+  }
 
-/*!
-  \brief Get SALOME verbose level
-  \internal
-  \return \c true if SALOME debug output is allowed or \c false otherwise
-*/
-static bool verbose()
-{
-  bool isVerbose = false;
-  if ( getenv( "SALOME_VERBOSE" ) ) {
-    QString envVar = getenv( "SALOME_VERBOSE" );
-    bool ok;
-    int value = envVar.toInt( &ok );
-    isVerbose = ok && value != 0;
+  /*!
+    \brief Load module icon
+    \internal
+    \param module module name
+    \param fileName path to the icon file
+    \return icon
+  */
+  QIcon loadIconInternal( const QString& module, const QString& fileName )
+  {
+    QIcon icon;
+    
+    LightApp_Application* app = getApplication();
+    
+    if ( app && !fileName.isEmpty() ) {
+      QPixmap pixmap = app->resourceMgr()->loadPixmap( module, 
+                                                       QApplication::translate( module.toLatin1().data(), 
+                                                                                fileName.toUtf8().data() ) );
+      if ( !pixmap.isNull() )
+        icon = QIcon( pixmap );
+    }
+    return icon;
+  }
+
+  /*!
+    \brief Gets window with specified identifier 
+    \internal
+    \param id window identifier 
+    \return pointer on the window
+  */
+  SUIT_ViewWindow* getWnd( const int id )
+  {
+    SUIT_ViewWindow* resWnd = 0;
+    
+    LightApp_Application* app = getApplication();
+    if ( app ) {
+      ViewManagerList vmlist = app->viewManagers();
+      foreach( SUIT_ViewManager* vm, vmlist ) {
+        QVector<SUIT_ViewWindow*> vwlist = vm->getViews();
+        foreach ( SUIT_ViewWindow* vw, vwlist ) {
+          if ( id == vw->getId() ) {
+            resWnd = vw;
+            break;
+          }
+        }
+      }
+    }
+    return resWnd;
   }
-  return isVerbose;
+
+  /*!
+    \brief Map of created selection objects.
+    \internal
+  */
+  QMap<LightApp_Application*, SALOME_Selection*> SelMap;
+
+  /*!
+    \brief Default resource file section name.
+    \internal
+  */
+  const char* DEFAULT_SECTION = "SalomePyQt";
+
+  struct Activator
+  {
+    QWidget* myActiveWindow;
+    QWidget* myFocusedWidget;
+    Activator()
+    {
+      myActiveWindow = QApplication::activeWindow();
+      myFocusedWidget = QApplication::focusWidget();
+      QApplication::setActiveWindow( getApplication()->desktop() );
+    }
+    ~Activator()
+    {
+      if ( myActiveWindow )
+       QApplication::setActiveWindow( myActiveWindow );
+      if ( myFocusedWidget )
+       myFocusedWidget->setFocus();
+    }
+  };
 }
 
 /*!
@@ -132,12 +255,6 @@ static bool verbose()
   \brief The class represents selection which can be used in Python.
 */
 
-/*!
-  \brief Map of created selection objects.
-  \internal
-*/
-static QMap<LightApp_Application*, SALOME_Selection*> SelMap;
-
 /*!
   \brief Get the selection object for the specified application.
 
@@ -156,6 +273,7 @@ SALOME_Selection* SALOME_Selection::GetSelection( LightApp_Application* app )
   return sel;
 }
 
+
 /*!
   \brief Constructor.
   \param p parent object
@@ -240,6 +358,90 @@ void SALOME_Selection::ClearFilters()
   ProcessVoidEvent( new TEvent( mySelMgr ) );
 }
 
+/*!
+  \class UserDefinedContent
+  \brief The class represents base class for user defined widget that
+  can be inserted to the Preferences dialog.
+*/
+
+/*!
+  \brief Constructor
+*/
+UserDefinedContent::UserDefinedContent()
+  : QWidget()
+{
+}
+
+/*!
+  \brief Called from Preferences dialog to store settings to the resource file.
+*/
+void UserDefinedContent::store()
+{
+}
+
+/*!
+  \brief Called from Preferences dialog to restore settings from the resource file.
+*/
+void UserDefinedContent::retrieve()
+{
+}
+
+/*!
+  \class SgPyQtUserDefinedContent
+  \brief A Wrapper for UserDefinedContent class.
+  \internal
+*/
+class SgPyQtUserDefinedContent: public QtxUserDefinedContent
+{
+public:
+  SgPyQtUserDefinedContent(UserDefinedContent*);
+  virtual ~SgPyQtUserDefinedContent();
+
+  void store( QtxResourceMgr*, QtxPreferenceMgr* );
+  void retrieve( QtxResourceMgr*, QtxPreferenceMgr* );
+
+private:
+  UserDefinedContent* myContent;
+};
+
+/*!
+  \brief Create custom item for Preferences dialog wrapping widget passed from Python.
+  \internal
+*/
+SgPyQtUserDefinedContent::SgPyQtUserDefinedContent(UserDefinedContent* content)
+  : QtxUserDefinedContent( 0 ), myContent( content )
+{
+  QVBoxLayout* l = new QVBoxLayout( this );
+  l->setContentsMargins( 0, 0, 0, 0 );
+  l->addWidget( myContent );
+}
+
+/*!
+  \brief Destructor.
+  \internal
+*/
+SgPyQtUserDefinedContent::~SgPyQtUserDefinedContent()
+{
+}
+
+/*!
+  \brief Called from Preferences dialog to store settings to the resource file.
+  \internal
+*/
+void SgPyQtUserDefinedContent::store( QtxResourceMgr*, QtxPreferenceMgr* )
+{
+  myContent->store();
+}
+
+/*!
+  \brief Called from Preferences dialog to restore settings from the resource file.
+  \internal
+*/
+void SgPyQtUserDefinedContent::retrieve( QtxResourceMgr*, QtxPreferenceMgr* )
+{
+  myContent->retrieve();
+}
+
 /*!
   \class SalomePyQt
   \brief The class provides utility functions which can be used in the Python
@@ -258,6 +460,29 @@ void SALOME_Selection::ClearFilters()
   \endcode
 */
 
+/*!
+  \fn QString SalomePyQt::getAppName();
+  \brief Get application name
+  \return application name
+*/
+
+QString SalomePyQt::getAppName()
+{
+  LightApp_Application* app = getApplication();
+  return app == 0 ? QString() : QString(app->metaObject()->className()).split("_").first();
+}
+
+/*!
+  \fn bool SalomePyQt::isLightApp();
+  \brief Check if SALOME GUI is running in "light" mode.
+  \return \c true if this is a "light" application; \c false otherwise
+*/
+
+bool SalomePyQt::isLightApp()
+{
+  return SalomePyQt::getAppName() != "SalomeApp";
+}
+
 /*!
   \fn QWidget* SalomePyQt::getDesktop();
   \brief Get the active application's desktop window.
@@ -372,23 +597,6 @@ public:
   }
 };
 
-/*!
-  \brief Get menu item title
-  \internal
-  \param menuId menu identifier
-  \return menu title (localized)
-*/
-static QString getMenuName( const QString& menuId )
-{
-  QStringList contexts;
-  contexts << "SalomeApp_Application" << "LightApp_Application" << "STD_TabDesktop" <<
-    "STD_MDIDesktop" << "STD_Application" << "SUIT_Application" << "";
-  QString menuName = menuId;
-  for ( int i = 0; i < contexts.count() && menuName == menuId; i++ )
-    menuName = QApplication::translate( contexts[i].toLatin1().data(), menuId.toLatin1().data() );
-  return menuName;
-}
-
 QMenu* SalomePyQt::getPopupMenu( const MenuName menu )
 {
   QString menuName;
@@ -430,7 +638,7 @@ public:
   virtual void Execute()
   {
     LightApp_Application* anApp = getApplication();
-    if ( anApp ) {
+    if ( anApp && anApp->objectBrowser() ) {
       myResult = anApp->objectBrowser()->treeView();
     }
   }
@@ -441,54 +649,99 @@ QTreeView* SalomePyQt::getObjectBrowser()
 }
 
 /*!
-  \fn int SalomePyQt::getStudyId();
-  \brief Get active study's identifier.
-  \return active study ID or 0 if there is no active study
+  \fn SALOME_Selection* SalomePyQt::getSelection();
+  \brief Get the selection object for the current study.
+
+  Creates a Selection object if it has not been created yet.
+
+  \return selection object (0 on error)
 */
 
-class TGetStudyIdEvent: public SALOME_Event
+class TGetSelectionEvent: public SALOME_Event 
 {
 public:
-  typedef int TResult;
+  typedef SALOME_Selection* TResult;
   TResult myResult;
-  TGetStudyIdEvent() : myResult( 0 ) {}
+  TGetSelectionEvent() : myResult( 0 ) {}
+  virtual void Execute() 
+  {
+    myResult = SALOME_Selection::GetSelection( getApplication() );
+  }
+};
+SALOME_Selection* SalomePyQt::getSelection()
+{
+  return ProcessEvent( new TGetSelectionEvent() );
+}
+
+/*!
+  \fn QStringList* SalomePyQt::setSelection(const QStringList& );
+  \brief Send local selection for notification.
+
+  The list of locally selected objects (study entries) is sent for notification of
+  other listening entities (modules, viewers...).
+*/
+
+class TSetSelectionEvent: public SALOME_Event
+{
+  QStringList myEntryList;
+public:
+  TSetSelectionEvent(const QStringList& entryList) : myEntryList(entryList) {}
   virtual void Execute()
   {
-    if ( LightApp_Study* aStudy = getActiveStudy() ) {
-      myResult = aStudy->id();
-    }
+       SALOME_PYQT_ModuleLight* module = dynamic_cast<SALOME_PYQT_ModuleLight*>( getActiveModule() );
+       if ( !module ) return;
+       module->setLocalSelected(myEntryList);
   }
 };
-int SalomePyQt::getStudyId()
+void SalomePyQt::setSelection( const QStringList& entryList)
 {
-  return ProcessEvent( new TGetStudyIdEvent() );
+  return ProcessVoidEvent( new TSetSelectionEvent(entryList) );
 }
 
 /*!
-  \fn SALOME_Selection* SalomePyQt::getSelection();
-  \brief Get the selection object for the current study.
+  \fn void SalomePyQt::enableSelector();
+  \brief enable PyQt_Selector (on module activation, for instance)
+*/
 
-  Creates a Selection object if it has not been created yet.
+class TEnableSelectorEvent: public SALOME_Event
+{
+public:
+       TEnableSelectorEvent() {}
+  virtual void Execute()
+  {
+       SALOME_PYQT_ModuleLight* module = dynamic_cast<SALOME_PYQT_ModuleLight*>( getActiveModule() );
+       if ( !module ) return;
+       module->enableSelector();
+  }
+};
+void SalomePyQt::enableSelector()
+{
+  return ProcessVoidEvent( new TEnableSelectorEvent() );
+}
 
-  \return selection object (0 on error)
+
+/*!
+  \fn void SalomePyQt::disableSelector();
+  \brief disable PyQt_Selector (on module activation, for instance)
 */
 
-class TGetSelectionEvent: public SALOME_Event 
+class TdisableSelectorEvent: public SALOME_Event
 {
 public:
-  typedef SALOME_Selection* TResult;
-  TResult myResult;
-  TGetSelectionEvent() : myResult( 0 ) {}
-  virtual void Execute() 
+       TdisableSelectorEvent() {}
+  virtual void Execute()
   {
-    myResult = SALOME_Selection::GetSelection( getApplication() );
+       SALOME_PYQT_ModuleLight* module = dynamic_cast<SALOME_PYQT_ModuleLight*>( getActiveModule() );
+       if ( !module ) return;
+       module->disableSelector();
   }
 };
-SALOME_Selection* SalomePyQt::getSelection()
+void SalomePyQt::disableSelector()
 {
-  return ProcessEvent( new TGetSelectionEvent() );
+  return ProcessVoidEvent( new TdisableSelectorEvent() );
 }
 
+
 /*!
   \fn void SalomePyQt::putInfo( const QString& msg, const int sec );
   \brief Put an information message to the current application's 
@@ -520,6 +773,123 @@ void SalomePyQt::putInfo( const QString& msg, const int sec )
   ProcessVoidEvent( new TPutInfoEvent( msg, sec ) );
 }
 
+/*!
+  \fn int SalomePyQt::showNotification( const QString& msg, const QString& title, const int sec );
+  \brief Show notification in the application's desktop window.
+
+  Optional third delay parameter (\a sec) can be used to specify
+  time of the notification diplaying in seconds. If this parameter is less
+  or equal to zero, the permanent notification will be put.
+
+  Notification can be forcibly hidden via hideNotification() method.
+
+  \param msg message text 
+  \param title title text 
+  \param sec notification displaying time in seconds
+  \return unique ID of the notification (can be used to hide notification)
+  \sa hideNotification()
+*/
+
+class TShowNotifyEvent: public SALOME_Event
+{
+  QString myMsg;
+  QString myTitle;
+  int     mySecs;
+
+public:
+  typedef int TResult;
+  TResult myResult;
+
+public:
+  TShowNotifyEvent( const QString& msg, const QString& title, const int sec = -1 ) : myMsg( msg ), myTitle( title), mySecs( sec ), myResult( -1 ) {}
+  virtual void Execute()
+  {
+    if ( LightApp_Application* anApp = getApplication() ) {
+      myResult = anApp->showNotification( myMsg, myTitle, mySecs * 1000 );
+    }
+  }
+};
+
+int SalomePyQt::showNotification( const QString& msg, const QString& title, const int sec )
+{
+  return ProcessEvent( new TShowNotifyEvent( msg, title, sec ) );
+}
+
+/*!
+  \fn void SalomePyQt::hideNotification( const QString& msg );
+  \brief Remove notification with given message text from the application's desktop.
+
+  \param msg message text
+  \sa showNotification()
+*/
+
+/*!
+  \fn void SalomePyQt::hideNotification( const int id );
+  \brief Remove notification with given \a id from the application's desktop.
+
+  \param id notification id
+  \sa showNotification()
+*/
+
+class THideNotifyEvent: public SALOME_Event
+{
+  int     myId;
+  QString myMsg;
+
+public:
+  THideNotifyEvent( const QString& msg ) : myId( -1 ), myMsg( msg ) {}
+  THideNotifyEvent( const int id ) : myId( id ) {}
+  virtual void Execute()
+  {
+    if ( LightApp_Application* anApp = getApplication() ) {
+      if ( myId >= 0 )
+       anApp->hideNotification( myId );
+      else
+       anApp->hideNotification( myMsg );
+    }
+  }
+};
+
+void SalomePyQt::hideNotification( const QString& msg )
+{
+  ProcessVoidEvent( new THideNotifyEvent( msg ) );
+}
+
+void SalomePyQt::hideNotification( const int id )
+{
+  ProcessVoidEvent( new THideNotifyEvent( id ) );
+}
+
+/*!
+  \fn QStringList SalomePyQt::getComponents();
+  \brief Get all modules used in current GUI session.
+  \return List of modules
+*/
+
+class TGetComponentsEvent: public SALOME_Event
+{
+public:
+  typedef QStringList TResult;
+  TResult myResult;
+  TGetComponentsEvent() {}
+  virtual void Execute() 
+  {
+    if ( LightApp_Application* anApp = getApplication() )
+    {
+      QStringList titles;
+      anApp->modules( titles, false );
+      foreach ( QString title, titles )
+      {
+       myResult << anApp->moduleName( title );
+      }
+    }
+  }
+};
+QStringList SalomePyQt::getComponents()
+{
+  return ProcessEvent( new TGetComponentsEvent() );
+}
+
 /*!
   \fn const QString SalomePyQt::getActiveComponent();
   \brief Get the currently active module name (for the current study).
@@ -587,6 +957,7 @@ public:
   virtual void Execute() 
   {
     if ( LightApp_Application* anApp = getApplication() ) {
+      Activator activator;
       myResult = anApp->activateModule( myModuleName );
     }
   }
@@ -597,37 +968,45 @@ bool SalomePyQt::activateModule( const QString& modName )
 }
 
 /*!
-  \brief Update an Object Browser of the specified (by identifier) study.
+  \fn void SalomePyQt::registerModule( const QString& modName);
+  \brief Registers module in the study tree
+*/
 
-  If \a studyId <= 0 the active study's object browser is updated.
-  The \a updateSelection parameter is obsolete and currently is not used. 
-  This parameter will be removed in future, so try to avoid its usage in 
-  your code.
+void SalomePyQt::registerModule( const QString& modName)
+{
+  class TEvent: public SALOME_Event
+  {
+    QString myName;
+  public:
+    TEvent(const QString& name): myName(name) {}
+    virtual void Execute()
+    {
+      if ( LightApp_Application* anApp = getApplication() ) {
+       anApp->desktop()->emitMessage(QString("register_module_in_study/%1").arg(myName));
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent(modName) );
+}
 
-  \brief studyId study identifier
-  \brief updateSelection update selection flag (not used)
-  \sa getActiveStudy()
+/*!
+  \brief Update an Object Browser of the study.
 */
-void SalomePyQt::updateObjBrowser( const int studyId, bool updateSelection )
+void SalomePyQt::updateObjBrowser()
 {  
   class TEvent: public SALOME_Event
   {
-    int  myStudyId;
-    bool myUpdateSelection;
   public:
-    TEvent( const int studyId, bool updateSelection ) 
-      : myStudyId( studyId ), myUpdateSelection( updateSelection ) {}
+    TEvent() {}
     virtual void Execute()
     {
       if ( SUIT_Session::session() ) {
-        if ( getActiveStudy() && myStudyId <= 0 )
-          myStudyId = getActiveStudy()->id();
-        if ( myStudyId > 0 ) {
+        if ( getActiveStudy() ) {
           QList<SUIT_Application*> apps = SUIT_Session::session()->applications();
           QList<SUIT_Application*>::Iterator it;
           for( it = apps.begin(); it != apps.end(); ++it ) {
             LightApp_Application* anApp = dynamic_cast<LightApp_Application*>( *it );
-            if ( anApp && anApp->activeStudy() && anApp->activeStudy()->id() == myStudyId ) {
+            if ( anApp && anApp->activeStudy() ) {
               anApp->updateObjectBrowser();
               return;
             }
@@ -636,7 +1015,7 @@ void SalomePyQt::updateObjBrowser( const int studyId, bool updateSelection )
       }
     }
   };
-  ProcessVoidEvent( new TEvent( studyId, updateSelection ) );
+  ProcessVoidEvent( new TEvent() );
 }
 
 
@@ -719,12 +1098,6 @@ void SalomePyQt::setModified( bool flag )
   ProcessVoidEvent( new TEvent( flag ) );
 }
 
-/*!
-  \brief Default resource file section name.
-  \internal
-*/
-static const char* DEFAULT_SECTION = "SalomePyQt";
-
 /*!
   \brief Add string setting to the application preferences.
 
@@ -946,6 +1319,67 @@ QString SalomePyQt::getSetting( const QString& name )
   return ProcessEvent( new TGetSettingEvent( name ) );
 }
 
+/*!
+  \fn QString SalomePyQt::constant( const QString& name );
+  \brief Get constant's value from application's resource manager.
+
+  \param name name of the constant 
+  \return value of the constant
+
+  \sa setConstant()
+*/
+
+class TGetConstantEvent: public SALOME_Event 
+{
+public:
+  typedef QString TResult;
+  TResult myResult;
+  QString myName;
+  TGetConstantEvent( const QString& name ) : myName( name ) {}
+  virtual void Execute() 
+  {
+    if ( SUIT_Session::session() )
+      myResult = SUIT_Session::session()->resourceMgr()->constant( myName );
+  }
+};
+QString SalomePyQt::constant( const QString& name )
+{
+  return ProcessEvent( new TGetConstantEvent( name ) );
+}
+
+/*!
+  \brief Add constant to the application's resource manager.
+
+  This function is useful to specify programmatically specific
+  variables that are referenced in the resource setting.
+
+  For example, some resource value can be set as "$(myroot)/data/files".
+  Then, "mypath" constant can be set programmatically by the application
+  depending on run-time requirements.
+  
+  \param section resources file section name 
+  \param name name of the constant 
+  \param value value of the constant 
+
+  \sa constant()
+*/
+void SalomePyQt::setConstant( const QString& name, const QString& value )
+{
+  class TEvent: public SALOME_Event 
+  {
+    QString myName, myValue;
+  public:
+    TEvent( const QString& name, const QString& value ) 
+      : myName( name ), myValue( value ) {}
+    virtual void Execute() 
+    {
+      if ( SUIT_Session::session() )
+        SUIT_Session::session()->resourceMgr()->setConstant( myName, myValue );
+    }
+  };
+  ProcessVoidEvent( new TEvent( name, value ) );
+}
+
 /*!
   \brief Add double setting to the application preferences.
   \param section resources file section name 
@@ -1088,6 +1522,62 @@ void SalomePyQt::addSetting( const QString& section, const QString& name, const
   ProcessVoidEvent( new TEvent( section, name, value ) );
 }
 
+/*!
+  \brief Add byte array setting to the application preferences.
+  \param section resources file section name 
+  \param name setting name
+  \param value new setting value
+*/
+void SalomePyQt::addSetting( const QString& section, const QString& name, const QByteArray& value )
+{
+  class TEvent: public SALOME_Event 
+  {
+    QString    mySection;
+    QString    myName;
+    QByteArray myValue;
+  public:
+    TEvent( const QString& section, const QString& name, const QByteArray& value ) 
+      : mySection( section ), myName( name ), myValue( value ) {}
+    virtual void Execute() 
+    {
+      if ( SUIT_Session::session() ) {
+        SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
+        if ( !mySection.isEmpty() && !myName.isEmpty() )
+          resMgr->setValue( mySection, myName, myValue );
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent( section, name, value ) );
+}
+
+/*!
+  \brief Add font setting to the application preferences.
+  \param section resources file section name 
+  \param name setting name
+  \param value new setting value
+*/
+void SalomePyQt::addSetting( const QString& section, const QString& name, const QFont& value )
+{
+  class TEvent: public SALOME_Event 
+  {
+    QString    mySection;
+    QString    myName;
+    QFont      myValue;
+  public:
+    TEvent( const QString& section, const QString& name, const QFont& value ) 
+      : mySection( section ), myName( name ), myValue( value ) {}
+    virtual void Execute() 
+    {
+      if ( SUIT_Session::session() ) {
+        SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
+        if ( !mySection.isEmpty() && !myName.isEmpty() )
+          resMgr->setValue( mySection, myName, myValue );
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent( section, name, value ) );
+}
+
 /*!
   \fn int SalomePyQt::integerSetting( const QString& section, 
                                       const QString& name, 
@@ -1181,81 +1671,152 @@ public:
   {
     if ( SUIT_Session::session() ) {
       SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
-      myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->booleanValue( mySection, myName, myDefault ) : myDefault;
+      myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->booleanValue( mySection, myName, myDefault ) : myDefault;
+    }
+  }
+};
+bool SalomePyQt::boolSetting( const QString& section, const QString& name, const bool def )
+{
+  return ProcessEvent( new TGetBoolSettingEvent( section, name, def ) );
+}
+
+/*!
+  \fn QString SalomePyQt::stringSetting( const QString& section, 
+                                         const QString& name, 
+                                         const QString& def, 
+                                         const bool subst );
+  \brief Get string setting from the application preferences.
+  \param section resources file section name 
+  \param name setting name
+  \param def default value which is returned if the setting is not found
+  \param subst \c true to make substitution, \c false to get "raw" value
+  \return setting value
+*/
+
+class TGetStrSettingEvent: public SALOME_Event
+{
+public:
+  typedef QString TResult;
+  TResult myResult;
+  QString mySection;
+  QString myName;
+  bool mySubst;
+  TResult myDefault;
+  TGetStrSettingEvent( const QString& section, const QString& name, const QString& def, const bool subst ) 
+    : mySection( section ), myName( name ), mySubst( subst ), myDefault( def ) {}
+  virtual void Execute() 
+  {
+    if ( SUIT_Session::session() ) {
+      SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
+      myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->stringValue( mySection, myName, myDefault, mySubst ) : myDefault;
+    }
+  }
+};
+QString SalomePyQt::stringSetting( const QString& section, const QString& name, const QString& def, const bool subst )
+{
+  return ProcessEvent( new TGetStrSettingEvent( section, name, def, subst ) );
+}
+
+/*!
+  \fn QColor SalomePyQt::colorSetting( const QString& section, 
+                                       const QString& name, 
+                                       const QColor def );
+  \brief Get color setting from the application preferences.
+  \param section resources file section name 
+  \param name setting name
+  \param def default value which is returned if the setting is not found
+  \return setting value
+*/
+
+class TGetColorSettingEvent: public SALOME_Event 
+{
+public:
+  typedef QColor TResult;
+  TResult myResult;
+  QString mySection;
+  QString myName;
+  TResult myDefault;
+  TGetColorSettingEvent( const QString& section, const QString& name, const QColor& def ) 
+    : mySection( section ), myName( name ), myDefault( def ) {}
+  virtual void Execute() 
+  {
+    if ( SUIT_Session::session() ) {
+      SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
+      myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->colorValue( mySection, myName, myDefault ) : myDefault;
     }
   }
 };
-bool SalomePyQt::boolSetting( const QString& section, const QString& name, const bool def )
+QColor SalomePyQt::colorSetting ( const QString& section, const QString& name, const QColor& def )
 {
-  return ProcessEvent( new TGetBoolSettingEvent( section, name, def ) );
+  return ProcessEvent( new TGetColorSettingEvent( section, name, def ) );
 }
 
 /*!
-  \fn QString SalomePyQt::stringSetting( const QString& section, 
-                                         const QString& name, 
-                                         const QString& def );
-  \brief Get string setting from the application preferences.
+  \fn QByteArray SalomePyQt::byteArraySetting( const QString& section, 
+                                               const QString& name, 
+                                               const QByteArray& def );
+  \brief Get byte array setting from the application preferences.
   \param section resources file section name 
   \param name setting name
   \param def default value which is returned if the setting is not found
   \return setting value
 */
 
-class TGetStrSettingEvent: public SALOME_Event
+class TGetByteArraySettingEvent: public SALOME_Event 
 {
 public:
-  typedef QString TResult;
+  typedef QByteArray TResult;
   TResult myResult;
   QString mySection;
   QString myName;
   TResult myDefault;
-  TGetStrSettingEvent( const QString& section, const QString& name, const QString& def ) 
+  TGetByteArraySettingEvent( const QString& section, const QString& name, const QByteArray& def ) 
     : mySection( section ), myName( name ), myDefault( def ) {}
   virtual void Execute() 
   {
     if ( SUIT_Session::session() ) {
       SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
-      myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->stringValue( mySection, myName, myDefault ) : myDefault;
+      myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->byteArrayValue( mySection, myName, myDefault ) : myDefault;
     }
   }
 };
-QString SalomePyQt::stringSetting( const QString& section, const QString& name, const QString& def )
+QByteArray SalomePyQt::byteArraySetting ( const QString& section, const QString& name, const QByteArray& def )
 {
-  return ProcessEvent( new TGetStrSettingEvent( section, name, def ) );
+  return ProcessEvent( new TGetByteArraySettingEvent( section, name, def ) );
 }
 
 /*!
-  \fn QColor SalomePyQt::colorSetting( const QString& section, 
-                                       const QString& name, 
-                                       const QColor def );
-  \brief Get color setting from the application preferences.
+  \fn QByteArray SalomePyQt::fontSetting( const QString& section, 
+                                          const QString& name, 
+                                          const QFont& def );
+  \brief Get font setting from the application preferences.
   \param section resources file section name 
   \param name setting name
   \param def default value which is returned if the setting is not found
   \return setting value
 */
 
-class TGetColorSettingEvent: public SALOME_Event 
+class TGetFontSettingEvent: public SALOME_Event 
 {
 public:
-  typedef QColor TResult;
+  typedef QFont TResult;
   TResult myResult;
   QString mySection;
   QString myName;
   TResult myDefault;
-  TGetColorSettingEvent( const QString& section, const QString& name, const QColor& def ) 
+  TGetFontSettingEvent( const QString& section, const QString& name, const QFont& def ) 
     : mySection( section ), myName( name ), myDefault( def ) {}
   virtual void Execute() 
   {
     if ( SUIT_Session::session() ) {
       SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
-      myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->colorValue( mySection, myName, myDefault ) : myDefault;
+      myResult = ( !mySection.isEmpty() && !myName.isEmpty() ) ? resMgr->fontValue( mySection, myName, myDefault ) : myDefault;
     }
   }
 };
-QColor SalomePyQt::colorSetting ( const QString& section, const QString& name, const QColor& def )
+QFont SalomePyQt::fontSetting ( const QString& section, const QString& name, const QFont& def )
 {
-  return ProcessEvent( new TGetColorSettingEvent( section, name, def ) );
+  return ProcessEvent( new TGetFontSettingEvent( section, name, def ) );
 }
 
 /*!
@@ -1291,14 +1852,14 @@ void SalomePyQt::removeSetting( const QString& section, const QString& name )
   \return \c true if setting exists
 */
 
-class THasColorSettingEvent: public SALOME_Event 
+class THasSettingEvent: public SALOME_Event 
 {
 public:
   typedef bool TResult;
   TResult myResult;
   QString mySection;
   QString myName;
-  THasColorSettingEvent( const QString& section, const QString& name ) 
+  THasSettingEvent( const QString& section, const QString& name ) 
     : mySection( section ), myName( name ) {}
   virtual void Execute() 
   {
@@ -1310,7 +1871,51 @@ public:
 };
 bool SalomePyQt::hasSetting( const QString& section, const QString& name )
 {
-  return ProcessEvent( new THasColorSettingEvent( section, name ) );
+  return ProcessEvent( new THasSettingEvent( section, name ) );
+}
+
+/*!
+  \fn QStringList SalomePyQt::parameters( const QString& section );
+  \brief Get names of preference items stored within the given section.
+  \param section resources file section's name 
+  \return \c list of preferences items
+*/
+
+/*!
+  \fn QStringList SalomePyQt::parameters( const QStringList& section );
+  \brief Get names of preference items stored within the given section.
+  \param section resources file section's name 
+  \return \c list of preferences items
+*/
+
+class TParametersEvent: public SALOME_Event 
+{
+public:
+  typedef QStringList TResult;
+  TResult myResult;
+  QStringList mySection;
+  TParametersEvent( const QString& section ) 
+  {
+    mySection << section;
+  }
+  TParametersEvent( const QStringList& section ) 
+    : mySection( section )
+  {}
+  virtual void Execute() 
+  {
+    if ( SUIT_Session::session() ) {
+      SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
+      myResult = resMgr->parameters( mySection );
+    }
+  }
+};
+QStringList SalomePyQt::parameters( const QString& section )
+{
+  return ProcessEvent( new TParametersEvent( section ) );
+}
+QStringList SalomePyQt::parameters( const QStringList& section )
+{
+  return ProcessEvent( new TParametersEvent( section ) );
 }
 
 /*!
@@ -1460,22 +2065,6 @@ QString SalomePyQt::getExistingDirectory( QWidget*       parent,
   \return icon object
 */
 
-static QIcon loadIconInternal( const QString& module, const QString& fileName )
-{
-  QIcon icon;
-
-  LightApp_Application* app = getApplication();
-
-  if ( app && !fileName.isEmpty() ) {
-    QPixmap pixmap = app->resourceMgr()->loadPixmap( module, 
-                                                    QApplication::translate( module.toLatin1().data(), 
-                                                                             fileName.toLatin1().data() ) );
-    if ( !pixmap.isNull() )
-      icon = QIcon( pixmap );
-  }
-  return icon;
-}
-
 class TLoadIconEvent: public SALOME_Event 
 {
 public:
@@ -1553,29 +2142,49 @@ public:
   CrTool( const QString& tBar, const QString& nBar ) 
     : myCase( 0 ), myTbTitle( tBar ), myTbName( nBar)  {}
   CrTool( const int id, const int tBar, const int idx ) 
-    : myCase( 1 ), myId( id ), myTbId( tBar ), myIndex( idx ) {}
+    : myCase( 1 ), myTbId( tBar ), myId( id ), myIndex( idx ) {}
   CrTool( const int id, const QString& tBar, const int idx )
-    : myCase( 2 ), myId( id ), myTbTitle( tBar ), myIndex( idx ) {}
+    : myCase( 2 ), myTbTitle( tBar ), myId( id ), myIndex( idx ) {}
   CrTool( QAction* action, const int tbId, const int id, const int idx )
-    : myCase( 3 ), myAction( action ), myTbId( tbId ), myId( id ), myIndex( idx ) {}
+    : myCase( 3 ), myTbId( tbId ), myAction( action ), myId( id ), myIndex( idx ) {}
   CrTool( QAction* action, const QString& tBar, const int id, const int idx )
-    : myCase( 4 ), myAction( action ), myTbTitle( tBar ), myId( id ), myIndex( idx ) {}
+    : myCase( 4 ), myTbTitle( tBar ), myAction( action ), myId( id ), myIndex( idx ) {}
 
-  int execute( LightApp_Module* module ) const
+  int execute() const
   {
-    if ( module ) {
-      switch ( myCase ) {
-      case 0:
-        return module->createTool( myTbTitle, myTbName );
-      case 1:
-        return module->createTool( myId, myTbId, myIndex );
-      case 2:
-        return module->createTool( myId, myTbTitle, myIndex );
-      case 3:
-        return module->createTool( myAction, myTbId, myId, myIndex );
-      case 4:
-        return module->createTool( myAction, myTbTitle, myId, myIndex );
-      }
+    switch ( myCase ) {
+    case 0:
+      if ( getActiveModule() )
+        return getActiveModule()->createTool( myTbTitle, myTbName );
+      else if ( getApplication() )
+        return getApplication()->createTool( myTbTitle, myTbName );
+      break;
+    case 1:
+      if ( getActiveModule() )
+        return getActiveModule()->createTool( myId, myTbId, myIndex );
+      else if ( getApplication() )
+        return getApplication()->createTool( myId, myTbId, myIndex );
+      break;
+    case 2:
+      if ( getActiveModule() )
+        return getActiveModule()->createTool( myId, myTbTitle, myIndex );
+      else if ( getApplication() )
+        return getApplication()->createTool( myId, myTbTitle, myIndex );
+      break;
+    case 3:
+      if ( getActiveModule() )
+        return getActiveModule()->createTool( myAction, myTbId, myId, myIndex );
+      else if ( getApplication() )
+        return getApplication()->createTool( myAction, myTbId, myId, myIndex );
+      break;
+    case 4:
+      if ( getActiveModule() )
+        return getActiveModule()->createTool( myAction, myTbTitle, myId, myIndex );
+      else if ( getApplication() )
+        return getApplication()->createTool( myAction, myTbTitle, myId, myIndex );
+      break;
+    default:
+      break;
     }
     return -1;
   }
@@ -1599,9 +2208,7 @@ public:
     : myResult( -1 ), myCrTool( crTool ) {}
   virtual void Execute() 
   {
-    LightApp_Module* module = getActiveModule();
-    if ( module )
-      myResult = myCrTool.execute( module );
+    myResult = myCrTool.execute();
   }
 };
 
@@ -1653,6 +2260,30 @@ int SalomePyQt::createTool( QAction* a, const int tBar, const int id, const int
   return ProcessEvent( new TCreateToolEvent( CrTool( a, tBar, id, idx ) ) );
 }
 
+
+/*!
+  \brief Clear given toolbar.
+  \param title toolbar's title
+*/
+void SalomePyQt::clearTool( const QString& title )
+{
+  class TEvent: public SALOME_Event
+  {
+    QString myTitle;
+  public:
+    TEvent( const QString& title ) 
+      : myTitle( title ) {}
+    virtual void Execute() 
+    {
+      if ( getActiveModule() )
+        return getActiveModule()->clearTool( myTitle );
+      else if ( getApplication() )
+        return getApplication()->clearTool( myTitle );
+    }
+  };
+  ProcessVoidEvent( new TEvent( title ) );
+}
+
 /*!
   \brief Insert action to the toolbar.
   \param a action
@@ -1670,35 +2301,59 @@ class CrMenu
 {
 public:
   CrMenu( const QString& subMenu, const int menu, const int id, const int group, const int idx ) 
-    : myCase( 0 ), mySubMenuName( subMenu ), myMenuId( menu ), myId( id ), myGroup( group ), myIndex( idx ) {}
+    : myCase( 0 ), myMenuId( menu ), mySubMenuName( subMenu ), myGroup( group ), myId( id ), myIndex( idx ) {}
   CrMenu( const QString& subMenu, const QString& menu, const int id, const int group, const int idx ) 
-    : myCase( 1 ), mySubMenuName( subMenu ), myMenuName( menu ), myId( id ), myGroup( group ), myIndex( idx ) {}
+    : myCase( 1 ), myMenuName( menu ), mySubMenuName( subMenu ), myGroup( group ), myId( id ), myIndex( idx ) {}
   CrMenu( const int id, const int menu, const int group, const int idx ) 
-    : myCase( 2 ), myId( id ), myMenuId( menu ), myGroup( group ), myIndex( idx ) {}
+    : myCase( 2 ), myMenuId( menu ), myGroup( group ), myId( id ), myIndex( idx ) {}
   CrMenu( const int id, const QString& menu, const int group, const int idx ) 
-    : myCase( 3 ), myId( id ), myMenuName( menu ), myGroup( group ), myIndex( idx ) {}
+    : myCase( 3 ), myMenuName( menu ), myGroup( group ), myId( id ), myIndex( idx ) {}
   CrMenu( QAction* action, const int menu, const int id, const int group, const int idx ) 
-    : myCase( 4 ), myAction( action ), myMenuId( menu ), myId( id ), myGroup( group ), myIndex( idx ) {}
+    : myCase( 4 ), myMenuId( menu ), myGroup( group ), myAction( action ), myId( id ), myIndex( idx ) {}
   CrMenu( QAction* action, const QString& menu, const int id, const int group, const int idx ) 
-    : myCase( 5 ), myAction( action ), myMenuName( menu ), myId( id ), myGroup( group ), myIndex( idx ) {}
+    : myCase( 5 ), myMenuName( menu ), myGroup( group ), myAction( action ), myId( id ), myIndex( idx ) {}
 
-  int execute( LightApp_Module* module ) const
+  int execute() const
   {
-    if ( module ) {
-      switch ( myCase ) {
-      case 0:
-        return module->createMenu( mySubMenuName, myMenuId, myId, myGroup, myIndex );
-      case 1:
-        return module->createMenu( mySubMenuName, myMenuName, myId, myGroup, myIndex );
-      case 2:
-        return module->createMenu( myId, myMenuId, myGroup, myIndex );
-      case 3:
-        return module->createMenu( myId, myMenuName, myGroup, myIndex );
-      case 4:
-        return module->createMenu( myAction, myMenuId, myId, myGroup, myIndex );
-      case 5:
-        return module->createMenu( myAction, myMenuName, myId, myGroup, myIndex );
-      }
+    switch ( myCase ) {
+    case 0:
+      if ( getActiveModule() )
+        return getActiveModule()->createMenu( mySubMenuName, myMenuId, myId, myGroup, myIndex );
+      else if ( getApplication() )
+        return getApplication()->createMenu( mySubMenuName, myMenuId, myId, myGroup, myIndex );
+      break;
+    case 1:
+      if ( getActiveModule() )
+        return getActiveModule()->createMenu( mySubMenuName, myMenuName, myId, myGroup, myIndex );
+      else if ( getApplication() )
+        return getApplication()->createMenu( mySubMenuName, myMenuName, myId, myGroup, myIndex );
+      break;
+    case 2:
+      if ( getActiveModule() )
+        return getActiveModule()->createMenu( myId, myMenuId, myGroup, myIndex );
+      else if ( getApplication() )
+        return getApplication()->createMenu( myId, myMenuId, myGroup, myIndex );
+      break;
+    case 3:
+      if ( getActiveModule() )
+        return getActiveModule()->createMenu( myId, myMenuName, myGroup, myIndex );
+      else if ( getApplication() )
+        return getApplication()->createMenu( myId, myMenuName, myGroup, myIndex );
+      break;
+    case 4:
+      if ( getActiveModule() )
+        return getActiveModule()->createMenu( myAction, myMenuId, myId, myGroup, myIndex );
+      else if ( getApplication() )
+        return getApplication()->createMenu( myAction, myMenuId, myId, myGroup, myIndex );
+      break;
+    case 5:
+      if ( getActiveModule() )
+        return getActiveModule()->createMenu( myAction, myMenuName, myId, myGroup, myIndex );
+      else if ( getApplication() )
+        return getApplication()->createMenu( myAction, myMenuName, myId, myGroup, myIndex );
+      break;
+    default:
+      break;
     }
     return -1;
   }
@@ -1723,9 +2378,7 @@ public:
     : myResult( -1 ), myCrMenu( crMenu ) {}
   virtual void Execute()
   {
-    LightApp_Module* module = getActiveModule();
-    if ( module )
-      myResult = myCrMenu.execute( module );
+    myResult = myCrMenu.execute();
   }
 };
 
@@ -1892,7 +2545,7 @@ public:
        myResult = (QAction*)module->createAction( myId, myTipText, icon, myMenuText, myStatusText, myKey, module, myToggle );
       }
       // for Python module, automatically connect action to callback slot
-      PyModuleHelper* helper = qFindChild<PyModuleHelper*>( module, "python_module_helper" );
+      PyModuleHelper* helper = module->findChild<PyModuleHelper*>( "python_module_helper" );
       if ( helper ) helper->connectAction( myResult );
     }
   }
@@ -2151,7 +2804,39 @@ void SalomePyQt::setPreferenceProperty( const int id,
       }
     }
   };
-  ProcessVoidEvent( new TEvent( id, prop, var) );
+  ProcessVoidEvent( new TEvent( id, prop, var ) );
+}
+
+/*!
+  \brief Set specific widget as a custom preferences item.
+  \param id preferences identifier
+  \param prop preferences property name
+  \param widget custom widget
+*/
+void SalomePyQt::setPreferencePropertyWg( const int id, 
+                                          const QString& prop,
+                                          UserDefinedContent* widget )
+{
+  class TEvent: public SALOME_Event
+  {
+    int      myId;
+    QString  myProp;
+    UserDefinedContent* myWidget;
+  public:
+    TEvent( const int id, const QString& prop, UserDefinedContent* widget ) 
+      : myId( id ), myProp( prop ), myWidget( widget ) {}
+    virtual void Execute() 
+    {
+      LightApp_Module* module = getActiveModule();
+      if ( module ) {
+       LightApp_Preferences* pref = module->getApp()->preferences();
+       if ( pref ) {
+         pref->setItemProperty( myProp, (qint64) new SgPyQtUserDefinedContent( myWidget ), myId );
+        }
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent( id, prop, widget ) );
 }
 
 /*!
@@ -2244,55 +2929,274 @@ void SalomePyQt::message( const QString& msg, bool addSeparator )
 }
 
 /*!
-  \brief Remove all the messages from the Log messages output window.
+  \brief Set the title to the Help panel.
+  \param title Title text (empty string removes title)
 */
-void SalomePyQt::clearMessages()
+void SalomePyQt::infoSetTitle( const QString& title )
 {
   class TEvent: public SALOME_Event
   {
+    QString myTitle;
   public:
-    TEvent() {}
+    TEvent( const QString& title ) 
+      : myTitle( title ) {}
     virtual void Execute()
     {
       if ( LightApp_Application* anApp = getApplication() ) {
-        LogWindow* lw = anApp->logWindow();
-        if ( lw )
-          lw->clear();
+        QtxInfoPanel* ip = anApp->infoPanel();
+        if ( ip )
+          ip->setTitle( myTitle );
       }
     }
   };
-  ProcessVoidEvent( new TEvent() );
+  ProcessVoidEvent( new TEvent( title ) );
 }
 
 /*!
-  \brief Gets window with specified identifier 
-  \internal
-  \param id window identifier 
-  \return pointer on the window
+  \fn int SalomePyQt::infoAddLabel( const QString& text, const int groupId )
+  \brief Insert left-aligned text label into the Help panel
+  \param text Label text
+  \param groupId Parent group's identifier (defaults to -1 for top-level group)
+  \return Label's identifier
 */
-static SUIT_ViewWindow* getWnd( const int id )
+
+class TInfoAddLabel2paramEvent: public SALOME_Event
+{
+public:
+  typedef int TResult;
+  TResult myResult;
+  QString myText;
+  int     myGroupId;
+  TInfoAddLabel2paramEvent( const QString& text, const int groupId )
+    : myText( text ), myGroupId( groupId ) {}
+  virtual void Execute()
+  {
+    if ( LightApp_Application* anApp = getApplication() ) {
+      QtxInfoPanel* ip = anApp->infoPanel();
+      if ( ip )
+        myResult = ip->addLabel( myText, myGroupId );
+    }
+  }
+};
+int SalomePyQt::infoAddLabel( const QString& text, const int groupId )
 {
-  SUIT_ViewWindow* resWnd = 0;
+  return ProcessEvent( new TInfoAddLabel2paramEvent( text, groupId ) );
+}
 
-  LightApp_Application* app = getApplication();
-  if ( app )
+/*!
+  \fn int SalomePyQt::infoAddLabel( const QString& text, Qt::Alignment alignment, const int groupId )
+  \brief Insert text label into the Help panel
+  \param text Label text
+  \param alignment Alignment flag for text label
+  \param groupId Parent group's identifier (defaults to -1 for top-level group)
+  \return Label's identifier
+*/
+
+class TInfoAddLabel3paramEvent: public SALOME_Event
+{
+public:
+  typedef int TResult;
+  TResult myResult;
+  QString myText;
+  Qt::Alignment myAlignment;
+  int     myGroupId;
+  TInfoAddLabel3paramEvent( const QString& text, Qt::Alignment alignment, const int groupId )
+    : myText( text ), myAlignment( alignment ), myGroupId( groupId ) {}
+  virtual void Execute()
+  {
+    if ( LightApp_Application* anApp = getApplication() ) {
+      QtxInfoPanel* ip = anApp->infoPanel();
+      if ( ip )
+        myResult = ip->addLabel( myText, myAlignment, myGroupId );
+    }
+  }
+};
+int SalomePyQt::infoAddLabel( const QString& text, Qt::Alignment alignment, const int groupId )
+{
+  return ProcessEvent( new TInfoAddLabel3paramEvent( text, alignment, groupId ) );
+}
+
+/*!
+  \fn int SalomePyQt::infoAddAction( QAction* action, const int groupId )
+  \brief Insert action button into the Help panel
+  \param action Action being added
+  \param groupId Parent group's identifier (defaults to -1 for top-level group)
+  \return Action's identifier
+*/
+
+class TInfoAddActionEvent: public SALOME_Event
+{
+public:
+  typedef int TResult;
+  TResult myResult;
+  QAction* myAction;
+  int     myGroupId;
+  TInfoAddActionEvent( QAction* action, const int groupId )
+    : myAction( action ), myGroupId( groupId ) {}
+  virtual void Execute()
+  {
+    if ( LightApp_Application* anApp = getApplication() ) {
+      QtxInfoPanel* ip = anApp->infoPanel();
+      if ( ip )
+        myResult = ip->addAction( myAction, myGroupId );
+    }
+  }
+};
+int SalomePyQt::infoAddAction( QAction* action, const int groupId )
+{
+  return ProcessEvent( new TInfoAddActionEvent( action, groupId ) );
+}
+
+/*!
+  \fn int SalomePyQt::infoAddGroup( const QString& text, const int groupId )
+  \brief Create a (sub-)group in the Help panel
+  \param text Group title
+  \param groupId Parent group's identifier (defaults to -1 for top-level group)
+  \return Group's identifier
+*/
+
+class TInfoAddGroupEvent: public SALOME_Event
+{
+public:
+  typedef int TResult;
+  TResult myResult;
+  QString myText;
+  int     myGroupId;
+  TInfoAddGroupEvent( const QString& text, const int groupId )
+    : myText( text ), myGroupId( groupId ) {}
+  virtual void Execute()
+  {
+    if ( LightApp_Application* anApp = getApplication() ) {
+      QtxInfoPanel* ip = anApp->infoPanel();
+      if ( ip )
+        myResult = ip->addGroup( myText, myGroupId );
+    }
+  }
+};
+int SalomePyQt::infoAddGroup( const QString& text, const int groupId )
+{
+  return ProcessEvent( new TInfoAddGroupEvent( text, groupId ) );
+}
+
+/*!
+  \brief Remove item from the Help panel
+  \param id Item's (label's, action's, group's, ...) identifier
+*/
+void SalomePyQt::infoRemove( const int id )
+{
+  class TEvent: public SALOME_Event
   {
-    ViewManagerList vmlist = app->viewManagers();
-    foreach( SUIT_ViewManager* vm, vmlist )
+    int myId;
+  public:
+    TEvent( const int id ) 
+      : myId( id ) {}
+    virtual void Execute()
     {
-      QVector<SUIT_ViewWindow*> vwlist = vm->getViews();
-      foreach ( SUIT_ViewWindow* vw, vwlist )
-      {
-        if ( id == vw->getId() )
-        {
-          resWnd = vw;
-          break;
-        }
+      if ( LightApp_Application* anApp = getApplication() ) {
+        QtxInfoPanel* ip = anApp->infoPanel();
+        if ( ip )
+          ip->remove( myId );
       }
     }
-  }
+  };
+  ProcessVoidEvent( new TEvent( id ) );
+}
+
+/*!
+  \brief Clear Help panel's contents
+  \param groupId Group's identifier (default is -1, to clear whole panel)
+*/
+void SalomePyQt::infoClear( const int groupId )
+{
+  class TEvent: public SALOME_Event
+  {
+    int myGroupId;
+  public:
+    TEvent( const int groupId ) 
+      : myGroupId( groupId ) {}
+    virtual void Execute()
+    {
+      if ( LightApp_Application* anApp = getApplication() ) {
+        QtxInfoPanel* ip = anApp->infoPanel();
+        if ( ip )
+          ip->clear( myGroupId );
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent( groupId ) );
+}
+
+/*!
+  \brief Set item's visibility in the Help panel
+  \param id Item's (label's, action's, group's, ...) identifier
+  \param visible Visibility flag
+*/
+void SalomePyQt::infoSetVisible( const int id, bool visible )
+{
+  class TEvent: public SALOME_Event
+  {
+    int myId;
+    bool myVisible;
+  public:
+    TEvent( const int id, bool visible ) 
+      : myId( id ), myVisible( visible ) {}
+    virtual void Execute()
+    {
+      if ( LightApp_Application* anApp = getApplication() ) {
+        QtxInfoPanel* ip = anApp->infoPanel();
+        if ( ip )
+          ip->setVisible( myId, myVisible );
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent( id, visible ) );
+}
+
+/*!
+  \brief Enable/disable item in the Help panel
+  \param id Item's (label's, action's, group's, ...) identifier
+  \param enabled Enabled state
+*/
+void SalomePyQt::infoSetEnabled( const int id, bool enabled )
+{
+  class TEvent: public SALOME_Event
+  {
+    int myId;
+    bool myEnabled;
+  public:
+    TEvent( const int id, bool enabled ) 
+      : myId( id ), myEnabled( enabled ) {}
+    virtual void Execute()
+    {
+      if ( LightApp_Application* anApp = getApplication() ) {
+        QtxInfoPanel* ip = anApp->infoPanel();
+        if ( ip )
+          ip->setEnabled( myId, myEnabled );
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent( id, enabled ) );
+}
 
-  return resWnd;
+/*!
+  \brief Remove all the messages from the Log messages output window.
+*/
+void SalomePyQt::clearMessages()
+{
+  class TEvent: public SALOME_Event
+  {
+  public:
+    TEvent() {}
+    virtual void Execute()
+    {
+      if ( LightApp_Application* anApp = getApplication() ) {
+        LogWindow* lw = anApp->logWindow();
+        if ( lw )
+          lw->clear();
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent() );
 }
 
 /*!
@@ -2316,45 +3220,41 @@ public:
   QString myFileName;
   int myWndId;
   TDumpViewEvent( const QString& filename, const int id ) 
-    : myResult ( false ), myFileName( filename ), myWndId(id) {}
+    : myResult ( false ), myFileName( filename ), myWndId( id ) {}
   virtual void Execute() 
   {
-       SUIT_ViewWindow* wnd = NULL;
-       if(myWndId == 0)
-       {
+    SUIT_ViewWindow* wnd = 0;
+    if ( !myWndId ) {
       if ( LightApp_Application* anApp = getApplication() ) {
-           SUIT_ViewManager* vm = anApp->activeViewManager();
-           if ( vm )
-             wnd = vm->getActiveView();
-         }
+        SUIT_ViewManager* vm = anApp->activeViewManager();
+        if ( vm )
+          wnd = vm->getActiveView();
+      }
       myWndId = wnd->getId();
-       }
-       else
-       {
-         wnd = dynamic_cast<SUIT_ViewWindow*>(getWnd( myWndId ));
-       }
+    }
+    else {
+      wnd = dynamic_cast<SUIT_ViewWindow*>( getWnd( myWndId ) );
+    }
     if ( wnd ) {
       QString fmt = SUIT_Tools::extension( myFileName ).toUpper();
-      Plot2d_ViewWindow* wnd2D = dynamic_cast<Plot2d_ViewWindow*>(wnd);
-      if(fmt == "PS" || fmt == "EPS" || fmt == "PDF") {
-       if(wnd2D) {
-         myResult = wnd2D->getViewFrame()->print(myFileName, fmt);
-       } else {
-         myResult = false;
-       }
-      } else {
-       if(wnd2D) {
-         qApp->postEvent( wnd2D->getViewFrame(), new QPaintEvent( QRect( 0, 0, wnd2D->getViewFrame()->width(), wnd2D->getViewFrame()->height() ) ) );
-         qApp->postEvent( wnd2D, new QPaintEvent( QRect( 0, 0, wnd2D->width(), wnd2D->height() ) ) );
-         qApp->processEvents();
-       }
-       QImage im = wnd->dumpView();
-       if ( !im.isNull() && !myFileName.isEmpty() ) {
-         if ( fmt.isEmpty() ) fmt = QString( "BMP" ); // default format
-         if ( fmt == "JPG" )  fmt = "JPEG";
-         myResult = im.save( myFileName, fmt.toLatin1() );
+#ifndef DISABLE_PLOT2DVIEWER
+      Plot2d_ViewWindow* wnd2D = dynamic_cast<Plot2d_ViewWindow*>( wnd );
+      if ( wnd2D ) {
+        qApp->postEvent( wnd2D->getViewFrame(), new QPaintEvent( QRect( 0, 0, wnd2D->getViewFrame()->width(), wnd2D->getViewFrame()->height() ) ) );
+        qApp->postEvent( wnd2D, new QPaintEvent( QRect( 0, 0, wnd2D->width(), wnd2D->height() ) ) );
+        qApp->processEvents();
+        if ( fmt == "PS" || fmt == "EPS" || fmt == "PDF" ) {
+         myResult = wnd2D->getViewFrame()->print( myFileName, fmt );
+          return;
         }
       }
+#endif // DISABLE_PLOT2DVIEWER
+      QImage im = wnd->dumpView();
+      if ( !im.isNull() && !myFileName.isEmpty() ) {
+        if ( fmt.isEmpty() ) fmt = QString( "BMP" ); // default format
+        if ( fmt == "JPG" )  fmt = "JPEG";
+        myResult = im.save( myFileName, fmt.toLatin1() );
+      }
     }
   }
 };
@@ -2363,7 +3263,6 @@ bool SalomePyQt::dumpView( const QString& filename, const int id )
   return ProcessEvent( new TDumpViewEvent( filename, id ) );
 }
 
-
 /*!
   \fn QList<int> SalomePyQt::getViews();
   \brief Get list of integer identifiers of all the currently opened views
@@ -2380,11 +3279,9 @@ public:
   {
     myResult.clear();
     LightApp_Application* app  = getApplication();
-    if ( app )
-    {
+    if ( app ) {
       STD_TabDesktop* tabDesk = dynamic_cast<STD_TabDesktop*>( app->desktop() );
-      if ( tabDesk )
-      {
+      if ( tabDesk ) {
         QList<SUIT_ViewWindow*> wndlist = tabDesk->windows();
         SUIT_ViewWindow* wnd;
         foreach ( wnd, wndlist )
@@ -2414,11 +3311,9 @@ public:
   virtual void Execute() 
   {
     LightApp_Application* app = getApplication();
-    if ( app )
-    {
+    if ( app ) {
       SUIT_ViewManager* viewMgr = app->activeViewManager();
-      if ( viewMgr )
-      {
+      if ( viewMgr ) {
         SUIT_ViewWindow* wnd = viewMgr->getActiveView();
         if ( wnd )
           myResult = wnd->getId();
@@ -2449,8 +3344,7 @@ public:
   virtual void Execute() 
   {
     SUIT_ViewWindow* wnd = getWnd( myWndId );
-    if ( wnd )
-    {
+    if ( wnd ) {
       SUIT_ViewManager* viewMgr = wnd->getViewManager();
       if ( viewMgr )
         myResult = viewMgr->getType();
@@ -2484,8 +3378,7 @@ public:
   virtual void Execute() 
   {
     SUIT_ViewWindow* wnd = getWnd( myWndId );
-    if ( wnd )
-    {
+    if ( wnd ) {
       wnd->setWindowTitle( myTitle );
       myResult = true;
     }
@@ -2496,6 +3389,177 @@ bool SalomePyQt::setViewTitle( const int id, const QString& title )
   return ProcessEvent( new TSetViewTitle( id, title ) );
 }
 
+/*!
+  \fn bool SalomePyQt::setViewSize( const int w, const int h, const int id );
+  \brief Set view size
+  \param w window width
+  \param h window height
+  \param id window identifier
+  \return \c true if operation is completed successfully and \c false otherwise 
+*/
+
+class TSetViewSize: public SALOME_Event
+{
+public:
+  typedef bool TResult;
+  TResult myResult;
+  int myWndWidth;
+  int myWndHeight;
+  int myWndId;
+  TSetViewSize( const int w, const int h, const int id )
+    : myResult( false ),
+      myWndWidth( w ),
+      myWndHeight( h ),
+      myWndId( id ) {}
+  virtual void Execute() 
+  {
+    SUIT_ViewWindow* wnd = 0;
+    if ( !myWndId ) {
+      if ( LightApp_Application* anApp = getApplication() ) {
+        SUIT_ViewManager* vm = anApp->activeViewManager();
+        if ( vm )
+          wnd = vm->getActiveView();
+      }
+    }
+    else {
+      wnd = dynamic_cast<SUIT_ViewWindow*>( getWnd( myWndId ) );
+    }
+    if ( wnd ) {
+      SUIT_ViewManager* viewMgr = wnd->getViewManager();
+      if ( viewMgr ) {
+        QString type = viewMgr->getType();
+        if ( type == "OCCViewer") {
+#ifndef DISABLE_OCCVIEWER
+          // specific processing for OCC viewer:
+          // OCC view can embed up to 4 sub-views, split according to the specified layout;
+          // - if there is only one sub-view active; it will be resized;
+          // - if there are several sub-views, each of them will be resized.
+          OCCViewer_ViewWindow* occView = qobject_cast<OCCViewer_ViewWindow*>( wnd );
+          for ( int i = OCCViewer_ViewFrame::BOTTOM_RIGHT; i <= OCCViewer_ViewFrame::TOP_RIGHT; i++ ) {
+            if ( occView && occView->getView( i ) ) {
+              occView->getView( i )->centralWidget()->resize( myWndWidth, myWndHeight );
+              myResult = true;
+            }
+          }
+#endif // DISABLE_OCCVIEWER
+        }
+        else if ( type == "ParaView") {
+#ifndef DISABLE_PVVIEWER
+          // specific processing for ParaView viewer:
+          // hierarchy of ParaView viewer is much complex than for usual view;
+          // we look for sub-widget named "Viewport"
+          QList<QWidget*> lst = wnd->findChildren<QWidget*>( "Viewport" );
+          if ( !lst.isEmpty() ) {
+            lst[0]->resize( myWndWidth, myWndHeight );
+            myResult = true;
+          }
+#endif // DISABLE_PVVIEWER
+        }
+        else if ( type == "ParaView3D") {
+#ifndef DISABLE_PV3DVIEWER
+          // specific processing for ParaView3D viewer:
+          // hierarchy of ParaView3D viewer is much more complex than for usual view;
+          // we look for sub-widget named "Viewport"
+          QList<QWidget*> lst = wnd->findChildren<QWidget*>( "Viewport" );
+          if ( !lst.isEmpty() ) {
+            lst[0]->resize( myWndWidth, myWndHeight );
+            myResult = true;
+          }
+#endif // DISABLE_PV3DVIEWER
+        }
+        else {
+          if ( wnd->centralWidget() ) {
+            wnd->centralWidget()->resize( myWndWidth, myWndHeight );
+            myResult = true;
+          }
+        }
+      }
+    }
+  }
+};
+bool SalomePyQt::setViewSize( const int w, const int h, const int id )
+{
+  return ProcessEvent( new TSetViewSize( w, h, id ) );
+}
+
+/*!
+  \fn bool SalomePyQt::setViewRotationPoint( const double x, const double y, const double z, const int id );
+  \brief Set view rotation point
+  \param x coordinate X view rotation point
+  \param y coordinate Y view rotation point
+  \param z coordinate Z view rotation point
+  \param id window identifier
+  \return \c true if operation is completed successfully and \c false otherwise 
+*/
+
+class TSetViewRotationPoint: public SALOME_Event
+{
+public:
+  typedef bool TResult;
+  TResult myResult;
+  double myX;
+  double myY;
+  double myZ;
+  int myWndId;
+  TSetViewRotationPoint( const double x, const double y, const double z, const int id )
+    : myResult( false ),
+      myX( x ),
+      myY( y ),
+      myZ( z ),
+      myWndId( id ) {}
+  virtual void Execute() 
+  {
+    SUIT_ViewWindow* wnd = 0;
+    if ( !myWndId ) {
+      if ( LightApp_Application* anApp = getApplication() ) {
+        SUIT_ViewManager* vm = anApp->activeViewManager();
+        if ( vm )
+          wnd = vm->getActiveView();
+      }
+    }
+    else {
+      wnd = dynamic_cast<SUIT_ViewWindow*>( getWnd( myWndId ) );
+    }
+    if ( wnd ) {
+      SUIT_ViewManager* viewMgr = wnd->getViewManager();
+      if ( viewMgr ) {
+        QString type = viewMgr->getType();
+        if ( type == "OCCViewer") {
+#ifndef DISABLE_OCCVIEWER
+          // specific processing for OCC viewer:
+          // OCC view can embed up to 4 sub-views, split according to the specified layout;
+          // - if there is only one sub-view active; its rotation point will be changed;
+          // - if there are several sub-views, rotaion points of each of them will be changed.
+          OCCViewer_ViewWindow* occView = qobject_cast<OCCViewer_ViewWindow*>( wnd );
+          if ( occView ) {
+            for ( int i = OCCViewer_ViewFrame::BOTTOM_RIGHT; i <= OCCViewer_ViewFrame::TOP_RIGHT; i++ ) {
+              if ( occView && occView->getView( i ) ) {
+                occView->getView( i )->activateSetRotationSelected( myX, myY, myZ );
+                myResult = true;
+              }
+            }
+          }
+#endif // DISABLE_OCCVIEWER
+        }
+        else if ( type == "VTKViewer") {
+#ifndef DISABLE_VTKVIEWER
+          SVTK_ViewWindow* vtkView = qobject_cast<SVTK_ViewWindow*>( wnd );
+          if ( vtkView )
+          {
+            double aCenter[3] = { myX, myY, myZ };
+            vtkView->activateSetRotationSelected( (void*)aCenter );
+            myResult = true;
+          }
+#endif // DISABLE_VTKVIEWER
+        }
+      }
+    }
+  }
+};
+bool SalomePyQt::setViewRotationPoint( const double x, const double y, const double z, const int id )
+{
+  return ProcessEvent( new TSetViewRotationPoint( x, y, z, id ) );
+}
 
 /*!
   \fn QString SalomePyQt::getViewTitle( const int id );
@@ -2544,19 +3608,19 @@ public:
   {
     myResult.clear();
     LightApp_Application* app  = getApplication();
-    if ( app )
-    {
+    if ( app ) {
       ViewManagerList vmList;
       app->viewManagers( myType, vmList );
       SUIT_ViewManager* viewMgr;
-      foreach ( viewMgr, vmList )
-      {
+      foreach ( viewMgr, vmList ) {
         QVector<SUIT_ViewWindow*> vec = viewMgr->getViews();
-        for ( int i = 0, n = vec.size(); i < n; i++ )
-        {
+        for ( int i = 0, n = vec.size(); i < n; i++ ) {
           SUIT_ViewWindow* wnd = vec[ i ];
           if ( wnd )
-            myResult.append( wnd->getId() );
+            {
+              MESSAGE("SUIT_ViewWindow*: "<< wnd << " id: " << wnd->getId());
+              myResult.append( wnd->getId() );
+            }
         }
       }
     }
@@ -2586,8 +3650,9 @@ public:
   virtual void Execute() 
   {
     SUIT_ViewWindow* wnd = getWnd( myWndId );
-    if ( wnd )
-    {
+    MESSAGE("window id:" << myWndId << " SUIT_ViewWindow*: " << wnd);
+    if ( wnd ) {
+      Activator activator;
       wnd->setFocus();
       myResult = true;
     }
@@ -2598,6 +3663,67 @@ bool SalomePyQt::activateView( const int id )
   return ProcessEvent( new TActivateView( id ) );
 }
 
+/*!
+  \fn bool SalomePyQt::activateManagerAndView( const int id );
+  \brief Activate view manager and view: useful for a view embedded in a module main Window
+  \param id window identifier
+  \return \c true if operation is completed successfully and \c false otherwise
+ */
+
+class TActivateViewManagerAndView: public SALOME_Event
+{
+public:
+  typedef bool TResult;
+  TResult myResult;
+  int myWndId;
+  TActivateViewManagerAndView( const int id )
+    : myResult( false ),
+      myWndId( id ) {}
+  virtual void Execute()
+  {
+    SUIT_ViewWindow* wnd = getWnd( myWndId );
+    MESSAGE("window id:" << myWndId << " SUIT_ViewWindow*: " << wnd);
+    if ( wnd )
+      {
+        LightApp_Application* app  = getApplication();
+        app->desktop()->windowActivated(wnd); // equivalent to app->setActiveViewManager(wnd->getViewManager())
+        wnd->setFocus();
+        myResult = true;
+      }
+  }
+};
+bool SalomePyQt::activateViewManagerAndView( const int id )
+{
+  return ProcessEvent( new TActivateViewManagerAndView( id ) );
+}
+
+/*!
+ *
+ */
+
+class TGetViewWidget: public SALOME_Event
+{
+public:
+  typedef QWidget* TResult;
+  TResult myResult;
+  int myWndId;
+  TGetViewWidget( const int id )
+    : myResult( 0 ),
+      myWndId( id ) {}
+  virtual void Execute()
+  {
+    SUIT_ViewWindow* wnd = getWnd( myWndId );
+    if ( wnd ) {
+        myResult = (QWidget*)wnd;
+    }
+  }
+};
+QWidget* SalomePyQt::getViewWidget( const int id)
+{
+  return ProcessEvent( new TGetViewWidget( id ) );
+}
+
+
 /*!
   \fn int SalomePyQt::createView( const QString& type, bool visible = true, const int width = 0, const int height = 0 );
   \brief Create new view and activate it
@@ -2617,44 +3743,46 @@ public:
   bool myVisible;
   int myWidth;
   int myHeight;
-  TCreateView( const QString& theType, bool visible, const int width, const int height )
+  bool myDetached;
+  TCreateView( const QString& theType, bool visible, const int width, const int height, bool detached )
     : myResult( -1 ),
       myType( theType ),
       myVisible(visible),
       myWidth(width),
-      myHeight(height) {}
+      myHeight(height),
+      myDetached(detached) {}
   virtual void Execute() 
   {
     LightApp_Application* app  = getApplication();
-    if ( app )
-      {
-        SUIT_ViewManager* viewMgr = app->createViewManager( myType );
-        if ( viewMgr )
-          {
-            SUIT_ViewWindow* wnd = viewMgr->getActiveView();
-            if ( wnd ) {
-              wnd->setShown(myVisible);
-              if(!myVisible && myWidth == 0 && myHeight == 0) {
-                myWidth = 1024;
-                myHeight = 768;
-              }
-              if(myWidth > 0 && myHeight > 0) {
-                Plot2d_ViewWindow* wnd2D = dynamic_cast<Plot2d_ViewWindow*>(wnd);
-                if(wnd2D) {
-                  wnd2D->getViewFrame()->setGeometry(0,0,myWidth,myHeight);
-                } else {
-                  wnd->setGeometry(0,0,myWidth,myHeight);
-                }
-              }
-              myResult = wnd->getId();
-            }
+    if ( app ) {
+      SUIT_ViewManager* viewMgr = app->createViewManager( myType, myDetached );
+      if ( viewMgr ) {
+        QWidget* wnd = viewMgr->getActiveView();
+        myResult = viewMgr->getActiveView()->getId();
+        if ( wnd ) {
+          if ( !myVisible )
+            wnd->setVisible(false);
+          if ( !myVisible && myWidth == 0 && myHeight == 0 ) {
+            myWidth = 1024;
+            myHeight = 768;
+          }
+          if (myWidth > 0 && myHeight > 0) {
+#ifndef DISABLE_PLOT2DVIEWER
+            Plot2d_ViewWindow* wnd2D = dynamic_cast<Plot2d_ViewWindow*>( wnd );
+            if ( wnd2D ) wnd = wnd2D->getViewFrame();
+#endif // DISABLE_PLOT2DVIEWER
+            wnd->setGeometry( 0, 0, myWidth, myHeight );
           }
+        }
       }
+    }
   }
 };
-int SalomePyQt::createView( const QString& type, bool visible, const int width, const int height )
+int SalomePyQt::createView( const QString& type, bool visible, const int width, const int height, bool detached )
 {
-  return ProcessEvent( new TCreateView( type, visible, width, height ) );
+  int ret = ProcessEvent( new TCreateView( type, visible, width, height, detached ) );
+  QCoreApplication::processEvents();
+  return ret;
 }
 
 /*!
@@ -2679,11 +3807,9 @@ public:
   virtual void Execute() 
   {
     LightApp_Application* app  = getApplication();
-    if ( app )
-    {
+    if ( app ) {
       SUIT_ViewManager* viewMgr = app->createViewManager( myType, myWidget );
-      if ( viewMgr )
-      {
+      if ( viewMgr ) {
         SUIT_ViewWindow* wnd = viewMgr->getActiveView();
         if ( wnd )
           myResult = wnd->getId();
@@ -2693,7 +3819,9 @@ public:
 };
 int SalomePyQt::createView( const QString& type, QWidget* w )
 {
-  return ProcessEvent( new TCreateViewWg( type, w ) );
+  int ret = ProcessEvent( new TCreateViewWg( type, w ) );
+  QCoreApplication::processEvents();
+  return ret;
 }
 
 /*!
@@ -2715,11 +3843,9 @@ public:
   virtual void Execute() 
   {
     SUIT_ViewWindow* wnd = getWnd( myWndId );
-    if ( wnd )
-    {
+    if ( wnd ) {
       SUIT_ViewManager* viewMgr = wnd->getViewManager();
-      if ( viewMgr )
-      {
+      if ( viewMgr ) {
         wnd->close();
         myResult = true;
       }
@@ -2750,30 +3876,28 @@ public:
   virtual void Execute() 
   {
     SUIT_ViewWindow* wnd = getWnd( myWndId );
-    if ( wnd )
-    {
+    if ( wnd ) {
       SUIT_ViewManager* viewMgr = wnd->getViewManager();
-      if ( viewMgr )
-      {
-        if ( wnd->inherits( "OCCViewer_ViewWindow" ) )
-        {
+      if ( viewMgr ) {
+#ifndef DISABLE_OCCVIEWER
+        if ( wnd->inherits( "OCCViewer_ViewWindow" ) ) {
           OCCViewer_ViewWindow* occView = (OCCViewer_ViewWindow*)( wnd );
           occView->onCloneView();
-
           wnd = viewMgr->getActiveView();
           if ( wnd )
             myResult = wnd->getId();
         }
-        else if ( wnd->inherits( "Plot2d_ViewWindow" ) ) 
-        {
+#endif // DISABLE_OCCVIEWER
+#ifndef DISABLE_PLOT2DVIEWER
+        if ( wnd->inherits( "Plot2d_ViewWindow" ) ) {
           Plot2d_ViewManager* viewMgr2d = dynamic_cast<Plot2d_ViewManager*>( viewMgr );
           Plot2d_ViewWindow* srcWnd2d = dynamic_cast<Plot2d_ViewWindow*>( wnd );
-          if ( viewMgr2d && srcWnd2d )
-          {
+          if ( viewMgr2d && srcWnd2d ) {
             Plot2d_ViewWindow* resWnd = viewMgr2d->cloneView( srcWnd2d );
             myResult = resWnd->getId();
           }
         }
+#endif // DISABLE_OCCVIEWER
       }
     }
   }
@@ -2910,14 +4034,11 @@ public:
   virtual void Execute() 
   {
     LightApp_Application* app  = getApplication();
-    if ( app )
-    {
+    if ( app ) {
       STD_TabDesktop* tabDesk = dynamic_cast<STD_TabDesktop*>( app->desktop() );
-      if ( tabDesk )
-      {
+      if ( tabDesk ) {
         QtxWorkstack* wStack = tabDesk->workstack();
-        if ( wStack )
-        {
+        if ( wStack ) {
           wStack->stack();
           myResult = true;
         }
@@ -2957,21 +4078,17 @@ public:
   virtual void Execute() 
   {
     SUIT_ViewWindow* wnd = getWnd( myWndId );
-    if ( wnd )
-    {
+    if ( wnd ) {
       // activate view
       // wnd->setFocus(); ???
 
       // split workstack
-      if ( getApplication() )
-      {
+      if ( getApplication() ) {
         STD_TabDesktop* desk = 
           dynamic_cast<STD_TabDesktop*>( getApplication()->desktop() );
-        if ( desk )
-        {
+        if ( desk ) {
           QtxWorkstack* wStack = desk->workstack();
-          if ( wStack )
-          {
+          if ( wStack ) {
             Qt::Orientation qtOri = 
               ( myOri == Horizontal ) ? Qt::Horizontal : Qt::Vertical;
 
@@ -3024,8 +4141,7 @@ public:
   {
     SUIT_ViewWindow* wnd = getWnd( myWndId );
     SUIT_ViewWindow* wnd_to = getWnd( myWndToId );
-    if ( wnd && wnd_to )
-    {
+    if ( wnd && wnd_to ) {
       QtxWorkstack* wStack = dynamic_cast<STD_TabDesktop*>( 
         getApplication()->desktop() )->workstack();
       if ( wStack )
@@ -3058,16 +4174,13 @@ public:
   {
     myResult.clear();
     SUIT_ViewWindow* wnd = getWnd( myWndId );
-    if ( wnd )
-    {
+    if ( wnd ) {
       QtxWorkstack* wStack = dynamic_cast<STD_TabDesktop*>( 
         getApplication()->desktop() )->workstack();
-      if ( wStack )
-      {
+      if ( wStack ) {
         QWidgetList wgList = wStack->windowList( wnd );
         QWidget* wg;
-        foreach ( wg, wgList )
-        {
+        foreach ( wg, wgList ) {
           SUIT_ViewWindow* tmpWnd = dynamic_cast<SUIT_ViewWindow*>( wg );
           if ( tmpWnd && tmpWnd != wnd )
             myResult.append( tmpWnd->getId() );
@@ -3082,6 +4195,36 @@ QList<int> SalomePyQt::neighbourViews( const int id )
 }
 
 
+/*!
+  \fn void SalomePyQt::createRoot();
+  \brief Initialize root data object.
+
+  Does nothing if root is already initialized.
+*/
+
+void SalomePyQt::createRoot()
+{
+  class TEvent: public SALOME_Event
+  {
+  public:
+    TEvent() {}
+    virtual void Execute() 
+    {
+      SALOME_PYQT_ModuleLight* module = dynamic_cast<SALOME_PYQT_ModuleLight*>( getActiveModule() );
+      if ( module ) {
+        SALOME_PYQT_DataModelLight* dm =
+          dynamic_cast<SALOME_PYQT_DataModelLight*>( module->dataModel() );
+        if ( dm )
+          dm->getRoot();
+      }
+      else {
+        if ( verbose() ) printf( "SalomePyQt.createRoot() function is not supported for the current module.\n" );
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent() );
+}
+
 /*!
   \fn QString SalomePyQt::createObject( const QString& parent );
   \brief Create empty data object
@@ -3137,10 +4280,10 @@ public:
                      const QString& icon,
                      const QString& tooltip,
                      const QString& parent )
-    : myName( name ),
+    : myParent( parent ),
+      myName( name ),
       myIcon( icon ),
-      myToolTip( tooltip ),
-      myParent( parent ) {}
+      myToolTip( tooltip ) {}
   virtual void Execute()
   {
     SALOME_PYQT_ModuleLight* module = dynamic_cast<SALOME_PYQT_ModuleLight*>( getActiveModule() );
@@ -3540,6 +4683,8 @@ QStringList SalomePyQt::getChildren( const QString& entry, const bool recursive
   return ProcessEvent( new TGetChildrenEvent( entry, recursive ) ); 
 }
 
+#ifndef DISABLE_PLOT2DVIEWER
+// Next set of methods relates to the Plot2d viewer functionality
 
 /*!
   \fn void SalomePyQt::displayCurve( const int id, Plot2d_Curve* theCurve )
@@ -3553,18 +4698,16 @@ class TDisplayCurve: public SALOME_Event
 public:
   int myWndId;
   Plot2d_Curve* myCurve;
-  TDisplayCurve(const int id, Plot2d_Curve* theCurve) : myWndId(id), myCurve(theCurve) {}
+  TDisplayCurve( const int id, Plot2d_Curve* theCurve ) : myWndId( id ), myCurve( theCurve ) {}
   virtual void Execute() {
-       Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>(getWnd( myWndId ));
-       if ( wnd )
-       {
-         wnd->getViewFrame()->displayCurve(myCurve);
-       }
+    Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( getWnd( myWndId ) );
+    if ( wnd )
+      wnd->getViewFrame()->displayCurve( myCurve );
   }
 };
-void SalomePyQt::displayCurve(const int id, Plot2d_Curve* theCurve)
+void SalomePyQt::displayCurve( const int id, Plot2d_Curve* theCurve )
 {
-       ProcessVoidEvent( new TDisplayCurve(id, theCurve) ); 
+  ProcessVoidEvent( new TDisplayCurve( id, theCurve ) ); 
 }
 
 /*!
@@ -3579,18 +4722,15 @@ class TEraseCurve: public SALOME_Event
 public:
   int myWndId;
   Plot2d_Curve* myCurve;
-  TEraseCurve(const int id, Plot2d_Curve* theCurve) : myWndId(id), myCurve(theCurve) {}
+  TEraseCurve( const int id, Plot2d_Curve* theCurve ) : myWndId( id ), myCurve( theCurve ) {}
   virtual void Execute() {
-       Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>(getWnd( myWndId ));
-       if ( wnd )
-       {
-         wnd->getViewFrame()->eraseCurve(myCurve);
-       }
+    Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( getWnd( myWndId ) );
+    wnd->getViewFrame()->eraseCurve( myCurve );
   }
 };
-void SalomePyQt::eraseCurve(const int id, Plot2d_Curve* theCurve)
+void SalomePyQt::eraseCurve( const int id, Plot2d_Curve* theCurve )
 {
-       ProcessVoidEvent( new TEraseCurve(id, theCurve) ); 
+  ProcessVoidEvent( new TEraseCurve( id, theCurve ) ); 
 }
 
 /*!
@@ -3603,37 +4743,32 @@ class TDeleteCurve: public SALOME_Event
 {
 public:
   Plot2d_Curve* myCurve;
-  TDeleteCurve(Plot2d_Curve* theCurve) : myCurve(theCurve) {}
+  TDeleteCurve( Plot2d_Curve* theCurve ) : myCurve( theCurve ) {}
   virtual void Execute() {
     LightApp_Application* app  = getApplication();
-    if ( app )
-    {
+    if ( app ) {
       STD_TabDesktop* tabDesk = dynamic_cast<STD_TabDesktop*>( app->desktop() );
-      if ( tabDesk )
-      {
+      if ( tabDesk ) {
         QList<SUIT_ViewWindow*> wndlist = tabDesk->windows();
         SUIT_ViewWindow* wnd;
-        foreach ( wnd, wndlist )
-        {
-          Plot2d_ViewWindow* aP2d = dynamic_cast<Plot2d_ViewWindow*>(wnd);
-          if(aP2d)
-          {
-               aP2d->getViewFrame()->eraseObject(myCurve);
-          }
+        foreach ( wnd, wndlist ) {
+          Plot2d_ViewWindow* aP2d = dynamic_cast<Plot2d_ViewWindow*>( wnd );
+          if ( aP2d )
+            aP2d->getViewFrame()->eraseObject( myCurve );
         }
       }
     }
   }
 };
-void SalomePyQt::eraseCurve(Plot2d_Curve * theCurve)
+void SalomePyQt::eraseCurve( Plot2d_Curve* theCurve )
 {
-       ProcessVoidEvent( new TDeleteCurve(theCurve) );
+  ProcessVoidEvent( new TDeleteCurve( theCurve ) );
 }
 
 /*!
   \brief updateCurves (repaint) curves in view window.
 */
-void SalomePyQt::updateCurves(const int id)
+void SalomePyQt::updateCurves( const int id )
 {
   class TEvent: public SALOME_Event
   {
@@ -3642,14 +4777,12 @@ void SalomePyQt::updateCurves(const int id)
     TEvent( const int id ) : myWndId( id ) {}
     virtual void Execute()
     {
-      Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>(getWnd( myWndId ));
+      Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( getWnd( myWndId ) );
       if ( wnd )
-      {
        wnd->getViewFrame()->DisplayAll();
-      }
     }
   };
-  ProcessVoidEvent( new TEvent(id) );
+  ProcessVoidEvent( new TEvent( id ) );
 }
 
 /*!
@@ -3668,19 +4801,17 @@ public:
   int myWndId;
   ObjectType myType;
   TGetPlot2dTitle(const int id, ObjectType type) :
-         myWndId(id),
-         myType(type) {}
+    myWndId( id ),
+    myType( type ) {}
   virtual void Execute() {
-       Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>(getWnd( myWndId ));
-       if ( wnd )
-       {
-         myResult = wnd->getViewFrame()->getTitle((Plot2d_ViewFrame::ObjectType)myType);
-       }
+    Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( getWnd( myWndId ) );
+    if ( wnd )
+      myResult = wnd->getViewFrame()->getTitle( (Plot2d_ViewFrame::ObjectType)myType );
   }
 };
-QString SalomePyQt::getPlot2dTitle(const int id, ObjectType type)
+QString SalomePyQt::getPlot2dTitle( const int id, ObjectType type )
 {
-       return ProcessEvent( new TGetPlot2dTitle(id, type) ); 
+  return ProcessEvent( new TGetPlot2dTitle( id, type ) ); 
 }
 
 
@@ -3701,22 +4832,19 @@ public:
   QString myTitle;
   ObjectType myType;
   bool myShow;
-  TSetPlot2dTitle(const int id, const QString& title, ObjectType type, bool show) :
-         myWndId(id),
-         myTitle(title),
-         myType(type),
-         myShow(show) {}
+  TSetPlot2dTitle( const int id, const QString& title, ObjectType type, bool show ) :
+    myWndId( id ),
+    myTitle( title ),
+    myType( type ),
+    myShow( show ) {}
   virtual void Execute() {
-       Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>(getWnd( myWndId ));
-       if ( wnd )
-       {
-         wnd->getViewFrame()->setTitle(myShow, myTitle, (Plot2d_ViewFrame::ObjectType)myType, false);
-       }
+    Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( getWnd( myWndId ) );
+    wnd->getViewFrame()->setTitle( myShow, myTitle, (Plot2d_ViewFrame::ObjectType)myType, false );
   }
 };
-void SalomePyQt::setPlot2dTitle(const int id, const QString& title, ObjectType type, bool show)
+void SalomePyQt::setPlot2dTitle( const int id, const QString& title, ObjectType type, bool show )
 {
-       ProcessVoidEvent( new TSetPlot2dTitle(id, title, type, show) ); 
+  ProcessVoidEvent( new TSetPlot2dTitle( id, title, type, show ) ); 
 }
 
 /*!
@@ -3737,15 +4865,14 @@ public:
   virtual void Execute() 
   {
     myResult.clear();
-    Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>(getWnd( myWndId ));
-    if ( wnd )
-    {
+    Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( getWnd( myWndId ) );
+    if ( wnd ) {
       double XMin, XMax, YMin, YMax, Y2Min, Y2Max;
-      wnd->getViewFrame()->getFitRangeByCurves(XMin, XMax, YMin, YMax, Y2Min, Y2Max);
-      myResult.append(XMin);
-      myResult.append(XMax);
-      myResult.append(YMin);
-      myResult.append(YMax);
+      wnd->getViewFrame()->getFitRangeByCurves( XMin, XMax, YMin, YMax, Y2Min, Y2Max );
+      myResult.append( XMin );
+      myResult.append( XMax );
+      myResult.append( YMin );
+      myResult.append( YMax );
     }
   }
 };
@@ -3772,15 +4899,14 @@ public:
   virtual void Execute() 
   {
     myResult.clear();
-    Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>(getWnd( myWndId ));
-    if ( wnd )
-    {
+    Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( getWnd( myWndId ) );
+    if ( wnd ) {
       double XMin, XMax, YMin, YMax, Y2Min, Y2Max;
-      wnd->getViewFrame()->getFitRanges(XMin, XMax, YMin, YMax, Y2Min, Y2Max);
-      myResult.append(XMin);
-      myResult.append(XMax);
-      myResult.append(YMin);
-      myResult.append(YMax);
+      wnd->getViewFrame()->getFitRanges( XMin, XMax, YMin, YMax, Y2Min, Y2Max );
+      myResult.append( XMin );
+      myResult.append( XMax );
+      myResult.append( YMin );
+      myResult.append( YMax );
     }
   }
 };
@@ -3807,67 +4933,90 @@ public:
   double myXMax;
   double myYMin;
   double myYMax;
-  TPlot2dFitRange(const int id, const double XMin, const double XMax, const double YMin, const double YMax) :
-         myWndId(id),
-         myXMin(XMin),
-         myXMax(XMax),
-         myYMin(YMin),
-         myYMax(YMax) {}
+  TPlot2dFitRange( const int id, const double XMin, const double XMax, const double YMin, const double YMax ) :
+    myWndId( id ),
+    myXMin( XMin ),
+    myXMax( XMax ),
+    myYMin( YMin ),
+    myYMax( YMax ) {}
   virtual void Execute() {
-       Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>(getWnd( myWndId ));
-       if ( wnd )
-       {
-         wnd->getViewFrame()->fitData(0, myXMin, myXMax, myYMin, myYMax);
-       }
+    Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( getWnd( myWndId ) );
+    if ( wnd )
+      wnd->getViewFrame()->fitData( 0, myXMin, myXMax, myYMin, myYMax );
   }
 };
-void SalomePyQt::setPlot2dFitRange(const int id, const double XMin, const double XMax, const double YMin, const double YMax)
+void SalomePyQt::setPlot2dFitRange( const int id, const double XMin, const double XMax, const double YMin, const double YMax )
 {
-       ProcessVoidEvent( new TPlot2dFitRange(id, XMin, XMax, YMin, YMax) ); 
+  ProcessVoidEvent( new TPlot2dFitRange( id, XMin, XMax, YMin, YMax ) ); 
 }
 
+// End of methods related to the Plot2d viewer functionality
+#endif // DISABLE_PLOT2DVIEWER
+
+/*!
+  \brief Process Qt event loop
+*/
+void SalomePyQt::processEvents()
+{
+  QCoreApplication::processEvents();
+}
 
-void SalomePyQt::setVisibilityState( const QString& theEntry, VisibilityState theState)
+/*!
+  \brief Set visibility state for given object
+  \param theEntry study ID of the object
+  \param theState visibility state
+*/
+void SalomePyQt::setVisibilityState( const QString& theEntry, VisibilityState theState )
 {
   class TEvent: public SALOME_Event
   {
     QString myEntry;
     int myState;
   public:
-    TEvent( const QString& theEntry, int theState):
-      myEntry(theEntry), myState(theState) {}
+    TEvent( const QString& theEntry, int theState ):
+      myEntry( theEntry ), myState( theState ) {}
     virtual void Execute() 
     {
       LightApp_Study* aStudy = getActiveStudy();
       if ( !aStudy )
         return;
-      aStudy->setVisibilityState(myEntry, (Qtx::VisibilityState)myState);
+      aStudy->setVisibilityState( myEntry, (Qtx::VisibilityState)myState );
     }
   };
-  ProcessVoidEvent( new TEvent(theEntry, theState ) );
+  ProcessVoidEvent( new TEvent( theEntry, theState ) );
 }
 
+/*!
+  \fn VisibilityState SalomePyQt::getVisibilityState( const QString& theEntry )
+  \brief Get visibility state for given object
+  \param theEntry study ID of the object
+  \return visibility state
+*/
+
 class TGetVisibilityStateEvent: public SALOME_Event 
 {
 public:
   typedef int TResult;
   TResult myResult;
   QString myEntry;
-  TGetVisibilityStateEvent(const QString& theEntry) : myResult( 0 ), myEntry(theEntry) {}
+  TGetVisibilityStateEvent( const QString& theEntry ) : myResult( 0 ), myEntry( theEntry ) {}
   virtual void Execute()
   {
     LightApp_Study* aStudy = getActiveStudy();
     if ( aStudy )
-      myResult = aStudy->visibilityState(myEntry);
+      myResult = aStudy->visibilityState( myEntry );
   }
 };
-
 VisibilityState SalomePyQt::getVisibilityState( const QString& theEntry )
 {
-  return (VisibilityState) ProcessEvent( new TGetVisibilityStateEvent(theEntry) );
+  return (VisibilityState) ProcessEvent( new TGetVisibilityStateEvent( theEntry ) );
 }
 
-
+/*!
+  \brief Set position of given object in the tree
+  \param theEntry study ID of the object
+  \param thePos position
+*/
 void SalomePyQt::setObjectPosition( const QString& theEntry, int thePos )
 {
   class TEvent: public SALOME_Event
@@ -3875,19 +5024,24 @@ void SalomePyQt::setObjectPosition( const QString& theEntry, int thePos )
     QString myEntry;
     int myPos;
   public:
-    TEvent( const QString& theEntry, int thePos):
-      myEntry(theEntry), myPos(thePos) {}
+    TEvent( const QString& theEntry, int thePos ):
+      myEntry( theEntry ), myPos( thePos ) {}
     virtual void Execute() 
     {
       SALOME_PYQT_ModuleLight* module = dynamic_cast<SALOME_PYQT_ModuleLight*>( getActiveModule() );
       if ( module )
-        module->setObjectPosition(myEntry, myPos );
+        module->setObjectPosition( myEntry, myPos );
     }
   };
-  ProcessVoidEvent( new TEvent(theEntry, thePos ) );
+  ProcessVoidEvent( new TEvent( theEntry, thePos ) );
 }
 
-
+/*!
+  \fn int SalomePyQt::getObjectPosition( const QString& theEntry )
+  \brief Get position of given object in the tree
+  \param theEntry study ID of the object
+  \return position
+*/
 
 class TGetObjectPositionEvent: public SALOME_Event 
 {
@@ -3895,21 +5049,24 @@ public:
   typedef int TResult;
   TResult myResult;
   QString myEntry;
-  TGetObjectPositionEvent(const QString& theEntry) : myResult( 0 ), myEntry(theEntry) {}
+  TGetObjectPositionEvent( const QString& theEntry ) : myResult( 0 ), myEntry( theEntry ) {}
   virtual void Execute()
   {
     SALOME_PYQT_ModuleLight* module = dynamic_cast<SALOME_PYQT_ModuleLight*>( getActiveModule() );
     if ( module )
-      myResult = module->getObjectPosition(myEntry);
+      myResult = module->getObjectPosition( myEntry );
   }
 };
-
 int SalomePyQt::getObjectPosition( const QString& theEntry )
 {
-  return ProcessEvent( new TGetObjectPositionEvent(theEntry) );
+  return ProcessEvent( new TGetObjectPositionEvent( theEntry ) );
 }
 
-void SalomePyQt::startPyLog(const QString& theFileName)
+/*!
+  \brief Start recordind a log of Python commands from embedded console
+  \param theFileName output lof file name
+*/
+void SalomePyQt::startPyLog( const QString& theFileName )
 {
   class TEvent: public SALOME_Event
   {
@@ -3928,6 +5085,9 @@ void SalomePyQt::startPyLog(const QString& theFileName)
   ProcessVoidEvent( new TEvent( theFileName ) );
 }
 
+/*!
+  \brief Stop recordind a log of Python commands from embedded console
+*/
 void SalomePyQt::stopPyLog()
 {
   class TEvent: public SALOME_Event
@@ -3944,3 +5104,43 @@ void SalomePyQt::stopPyLog()
   };
   ProcessVoidEvent( new TEvent() );
 }
+
+/*!
+  \brief Log GUI event.
+  \param eventDescription GUI event description.
+*/
+void SalomePyQt::logUserEvent( const QString& eventDescription )
+{
+  class TEvent: public SALOME_Event
+  {
+    QString myEventDescription;
+  public:
+    TEvent( const QString& theDescription ) : myEventDescription( theDescription ) {}
+    virtual void Execute() 
+    {
+      LightApp_Application::logUserEvent( myEventDescription );
+    }
+  };
+  ProcessVoidEvent( new TEvent( eventDescription ) );
+}
+
+/*!
+  \brief Log given action.
+  \param action GUI action being logged.
+  \param moduleName optional name of module, owning an action
+*/
+void SalomePyQt::logAction( QAction* action, const QString& moduleName )
+{
+  class TEvent: public SALOME_Event
+  {
+    QAction* myAction;
+    QString myModuleName;
+  public:
+    TEvent( QAction* theAction, const QString& theModuleName ) : myAction( theAction ), myModuleName( theModuleName ) {}
+    virtual void Execute() 
+    {
+      LightApp_Application::logAction( myAction, myModuleName );
+    }
+  };
+  ProcessVoidEvent( new TEvent( action, moduleName ) );
+}