Salome HOME
updated copyright message
[modules/gui.git] / src / CAM / CAM_Application.cxx
index 46d47ef2b9c25222a3a8ee115a0fc18f90420287..873951c8a0c430a97bc6ff52fdd210c50c6a348d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -46,6 +46,8 @@
 #include <cstdio>
 #include <iostream>
 
+#include <utilities.h>
+
 namespace
 {
 class BusyLocker
@@ -415,13 +417,17 @@ bool CAM_Application::activateModule( const QString& modName )
   // See issues 0021307, 0021373
   BusyLocker lock( myBlocked );
 
+  QString name = modName;
+  if ( !name.isEmpty() && !moduleTitle( modName ).isEmpty() )
+    name = moduleTitle( modName );
+
   bool res = false;
-  if ( !modName.isEmpty() )
+  if ( !name.isEmpty() )
   {
     setProperty("activateModule", true);
-    CAM_Module* mod = module( modName );
+    CAM_Module* mod = module( name );
     if ( !mod )
-      mod = loadModule( modName );
+      mod = loadModule( name );
     addModule( mod );
 
     if ( mod )
@@ -454,12 +460,14 @@ bool CAM_Application::activateModule( CAM_Module* mod )
   {
     if ( !myModule->deactivateModule( activeStudy() ) )
     {
-      // ....      
-    }    
+      // ???
+    }
+    moduleDeactivated( myModule );
   }     
   myModule = mod;
 
-  if ( myModule ){
+  if ( myModule )
+  {
     // Connect the module to the active study
     myModule->connectToStudy( dynamic_cast<CAM_Study*>( activeStudy() ) );
     if ( !myModule->activateModule( activeStudy() ) )
@@ -607,6 +615,18 @@ void CAM_Application::moduleAdded( CAM_Module* /*mod*/ )
 {
 }
 
+/*!
+  \brief Callback function, called when the module is just deactivated.
+  
+  This virtual method can be re-implemented in the successors. Base implementation
+  does nothing.
+
+  \param mod module just deactivated
+*/
+void CAM_Application::moduleDeactivated( CAM_Module* /*mod*/ )
+{
+}
+
 /*!
   \brief Get module name by its title (user name).
   \param title module title (user name)
@@ -739,6 +759,7 @@ void CAM_Application::readModuleList()
   if ( !myInfoList.isEmpty() )
     return;
 
+  // we cannot use own resourceMgr() as this method can be called from constructor
   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
 
   QStringList modList;
@@ -783,88 +804,111 @@ void CAM_Application::readModuleList()
     modList = mods.split( ",", QString::SkipEmptyParts );
   }
 
-  for ( QStringList::const_iterator it = modList.begin(); it != modList.end(); ++it )
-  {
-    QString modName = (*it).trimmed();
-
-    if ( modName.isEmpty() )
-      continue;  // empty module name
-
-    if ( !moduleTitle( modName ).isEmpty() )
-      continue;  // already added
-
-    if ( modName == "KERNEL" || modName == "GUI" )
-      continue; // omit KERNEL and GUI modules
-
-    bool hasGui = resMgr->booleanValue( *it, "gui", true );
+  // extra modules loaded manually on previous session
+  // ...
 
-    QString modTitle, modIcon, modLibrary, modDescription;
+  foreach ( QString modName, modList )
+    appendModuleInfo( modName.trimmed() );
 
-    if ( hasGui )
-    {
-      // if module has GUI, check that it is present
-      modTitle = resMgr->stringValue( *it, "name", QString() );
-      if ( modTitle.isEmpty() )
+  if ( myInfoList.isEmpty() ) {
+    if ( desktop() && desktop()->isVisible() )
+      SUIT_MessageBox::warning( desktop(), tr( "Warning" ), tr( "Modules list is empty" ) );
+    else
       {
         printf( "****************************************************************\n" );
-        printf( "     Warning: module %s is improperly configured!\n", qPrintable(*it) );
-        printf( "     Module %s will not be available in GUI mode!\n", qPrintable(*it) );
+        printf( "*    Warning: modules list is empty.\n" );
         printf( "****************************************************************\n" );
-        continue;
       }
+  }
+}
 
-      modIcon = resMgr->stringValue( *it, "icon", QString() );
+bool CAM_Application::appendModuleInfo( const QString& modName )
+{
+  MESSAGE("Start to append module info for a given module name: ");
+  SCRUTE(modName.toStdString());
 
-      modDescription = resMgr->stringValue( *it, "description", QString() );
+  if ( modName.isEmpty() )
+    return false;  // empty module name
 
-      modLibrary = resMgr->stringValue( *it, "library", QString() ).trimmed();
-      if ( !modLibrary.isEmpty() )
-      {
-        modLibrary = SUIT_Tools::file( modLibrary.trimmed() );
-#if defined(WIN32)
-        QString libExt = QString( "dll" );
-#elif defined(__APPLE__)
-        QString libExt = QString( "dylib" );
-#else
-        QString libExt = QString( "so" );
-#endif
-        if ( SUIT_Tools::extension( modLibrary ).toLower() == libExt )
-          modLibrary.truncate( modLibrary.length() - libExt.length() - 1 );
-#ifndef WIN32
-        QString prefix = QString( "lib" );
-        if ( modLibrary.startsWith( prefix ) )
-          modLibrary.remove( 0, prefix.length() );
-#endif
-      }
-      else
-        modLibrary = modName;
-    }
+  if ( !moduleTitle( modName ).isEmpty() )
+    return false;  // already added
 
-    QString version = resMgr->stringValue( *it, "version", QString() );
+  if ( modName == "KERNEL" || modName == "GUI" )
+    return false; // skip KERNEL and GUI modules
 
-    QString modDisplayer = resMgr->stringValue( *it, "displayer", QString() );
+  // we cannot use own resourceMgr() as this method can be called from constructor
+  SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
 
-    ModuleInfo inf;
-    inf.name = modName;
-    inf.title = modTitle;
-    inf.status = hasGui ? stUnknown : stNoGui;
-    if ( hasGui ) inf.library = modLibrary;
-    inf.icon = modIcon;
-    inf.description = modDescription;
-    inf.displayer = modDisplayer;
-    inf.version = version;
-    myInfoList.append( inf );
+  ModuleInfo inf;
+
+  // module internal name
+  inf.name = modName;
+  // module version
+  inf.version = resMgr->stringValue( modName, "version", QString() ).trimmed();
+  // displayer, if module does not have GUI, displayer may be delegated to other module
+  inf.displayer = resMgr->stringValue( modName, "displayer", QString() ).trimmed();
+
+  // "gui" option explicitly says that module has GUI
+  // Now trying to get the "gui" option value, we always get a default one,
+  // then we can't rely on it.
+  bool hasGui = resMgr->booleanValue(modName, "gui", false);
+
+  // Additional check if the module actually has a title and icon.
+  // Module with GUI must explicitly specify title (GUI name).
+  inf.title = resMgr->stringValue(modName, "name", QString()).trimmed();
+  const bool hasTitle = !inf.title.isEmpty();
+  SCRUTE(hasGui);
+  SCRUTE(hasTitle);
+  if (hasGui && !hasTitle)
+  {
+    MESSAGE("Invalid config! The module has gui option, but doesn't have a title.");
+    return false;
   }
 
-  if ( myInfoList.isEmpty() ) {
-    if ( desktop() && desktop()->isVisible() )
-      SUIT_MessageBox::warning( desktop(), tr( "Warning" ), tr( "Modules list is empty" ) );
-    else
-      {
-        printf( "****************************************************************\n" );
-        printf( "*    Warning: modules list is empty.\n" );
-        printf( "****************************************************************\n" );
-      }
+  // While we can't rely on gui option, use a title to make a decision about gui.
+  hasGui = hasTitle;
+
+  // status; if module has GUI, availability will be checked on activation
+  inf.status = hasGui ? stUnknown : stNoGui;
+
+  if ( hasGui )
+  {
+    // icon
+    inf.icon = resMgr->stringValue( modName, "icon", QString() ).trimmed();
+    // description, for Info panel
+    inf.description = resMgr->stringValue( modName, "description", QString() );
+    // library; if not specified, we use internal module name
+    inf.library = SUIT_Tools::libraryName( resMgr->stringValue( modName, "library", QString() ).trimmed() );
+    if ( inf.library.isEmpty() )
+      inf.library = modName;
+  }
+
+  // At this point we should have only valid inf object.
+  myInfoList.append(inf);
+
+  SCRUTE(inf.name.toStdString());
+  SCRUTE(inf.version.toStdString());
+  SCRUTE(inf.displayer.toStdString());
+  SCRUTE(inf.status);
+  SCRUTE(inf.title.toStdString());
+  SCRUTE(inf.icon.toStdString());
+  SCRUTE(inf.description.toStdString());
+  SCRUTE(inf.library.toStdString());
+
+  return true;
+}
+
+void CAM_Application::removeModuleInfo( const QString& modName )
+{
+  QMutableListIterator<ModuleInfo> it( myInfoList );
+  while ( it.hasNext() )
+  {
+    ModuleInfo info = it.next();
+    if ( info.name == modName )
+    {
+      it.remove();
+      break;
+    }
   }
 }
 
@@ -934,4 +978,4 @@ bool CAM_Application::abortAllOperations()
     aborted = (*it)->abortAllOperations();
   }
   return aborted;
-}
+}
\ No newline at end of file