Salome HOME
bos #29467 SALOME GUI logger
[modules/gui.git] / src / SALOME_PYQT / SalomePyQt / SalomePyQt.cxx
index 47407341271a408680bec0bc5521a25804b1b161..25efe528da1fd8165f57e18b5424be241d771667 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  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 "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"
@@ -224,6 +229,25 @@ namespace
     \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();
+    }
+  };
 }
 
 /*!
@@ -436,6 +460,29 @@ void SgPyQtUserDefinedContent::retrieve( QtxResourceMgr*, QtxPreferenceMgr* )
   \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.
@@ -910,6 +957,7 @@ public:
   virtual void Execute() 
   {
     if ( LightApp_Application* anApp = getApplication() ) {
+      Activator activator;
       myResult = anApp->activateModule( myModuleName );
     }
   }
@@ -919,6 +967,28 @@ bool SalomePyQt::activateModule( const QString& modName )
   return ProcessEvent( new TActivateModuleEvent( modName ) );
 }
 
+/*!
+  \fn void SalomePyQt::registerModule( const QString& modName);
+  \brief Registers module in the study tree
+*/
+
+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 Update an Object Browser of the study.
 */
@@ -1633,7 +1703,7 @@ public:
   bool mySubst;
   TResult myDefault;
   TGetStrSettingEvent( const QString& section, const QString& name, const QString& def, const bool subst ) 
-    : mySection( section ), myName( name ), myDefault( def ), mySubst( subst ) {}
+    : mySection( section ), myName( name ), mySubst( subst ), myDefault( def ) {}
   virtual void Execute() 
   {
     if ( SUIT_Session::session() ) {
@@ -2072,13 +2142,13 @@ 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() const
   {
@@ -2088,26 +2158,33 @@ public:
         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;
   }
@@ -2224,17 +2301,17 @@ 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() const
   {
@@ -2244,31 +2321,39 @@ public:
         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;
   }
@@ -2843,6 +2928,256 @@ void SalomePyQt::message( const QString& msg, bool addSeparator )
   ProcessVoidEvent( new TEvent( msg, addSeparator ) );
 }
 
+/*!
+  \brief Set the title to the Help panel.
+  \param title Title text (empty string removes title)
+*/
+void SalomePyQt::infoSetTitle( const QString& title )
+{
+  class TEvent: public SALOME_Event
+  {
+    QString myTitle;
+  public:
+    TEvent( const QString& title ) 
+      : myTitle( title ) {}
+    virtual void Execute()
+    {
+      if ( LightApp_Application* anApp = getApplication() ) {
+        QtxInfoPanel* ip = anApp->infoPanel();
+        if ( ip )
+          ip->setTitle( myTitle );
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent( title ) );
+}
+
+/*!
+  \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
+*/
+
+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 )
+{
+  return ProcessEvent( new TInfoAddLabel2paramEvent( text, groupId ) );
+}
+
+/*!
+  \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
+  {
+    int myId;
+  public:
+    TEvent( const int id ) 
+      : myId( id ) {}
+    virtual void Execute()
+    {
+      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 ) );
+}
+
 /*!
   \brief Remove all the messages from the Log messages output window.
 */
@@ -3119,6 +3454,18 @@ public:
             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() ) {
@@ -3305,6 +3652,7 @@ public:
     SUIT_ViewWindow* wnd = getWnd( myWndId );
     MESSAGE("window id:" << myWndId << " SUIT_ViewWindow*: " << wnd);
     if ( wnd ) {
+      Activator activator;
       wnd->setFocus();
       myResult = true;
     }
@@ -3932,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() );
@@ -4756,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 ) );
+}