-// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2022 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
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
#endif
#include <cstdio>
+#include <iostream>
namespace
{
- etc
*/
+CAM_Application::ModuleInfoList CAM_Application::myInfoList;
+
/*!
\brief Constructor.
*/
void CAM_Application::start()
{
+ // check modules
+ for ( ModuleInfoList::iterator it = myInfoList.begin();
+ it != myInfoList.end(); ++it )
+ {
+ if ( (*it).status == stUnknown )
+ (*it).status = checkModule( (*it).title ) ? stReady : stInaccessible;
+ }
+
+ // auto-load modules
if ( myAutoLoad )
loadModules();
{
for ( ModuleInfoList::const_iterator it = myInfoList.begin();
it != myInfoList.end(); ++it )
- lst.append( (*it).title );
+ if ( (*it).status != stNoGui )
+ lst.append( (*it).title );
}
}
{
for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end(); ++it )
{
- if ( !isModuleAccessible( (*it).title ) ) {
- continue;
- }
CAM_Module* mod = loadModule( (*it).title );
if ( mod )
addModule( mod );
return 0;
}
- if ( !isModuleAccessible( modName ) ) {
- qWarning( qPrintable( tr( "Module \"%1\" cannot be loaded in this application." ).arg( modName ) ) );
- return 0;
- }
-
QString libName = moduleLibrary( modName );
if ( libName.isEmpty() )
{
GET_VERSION_FUNC getVersion = 0;
#ifdef WIN32
- HINSTANCE modLib = ::LoadLibrary( libName.toLatin1() );
+#ifdef UNICODE
+ LPTSTR str_libname = new TCHAR[libName.length() + 1];
+ str_libname[libName.toWCharArray(str_libname)] = '\0';
+#else
+ QByteArray arr = libName.toLatin1();
+ LPTSTR str_libname = arr.constData();
+#endif
+ HINSTANCE modLib = ::LoadLibrary( str_libname );
+#ifdef UNICODE
+ delete str_libname;
+#endif
if ( !modLib )
{
LPVOID lpMsgBuf;
::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
- err = QString( "Failed to load %1. %2" ).arg( libName ).arg( (LPTSTR)lpMsgBuf );
+#ifdef UNICODE
+ QString out_err = QString::fromWCharArray((LPTSTR)lpMsgBuf);
+#else
+ QString out_err = (LPTSTR)lpMsgBuf;
+#endif
+ err = QString( "Failed to load %1. %2" ).arg( libName ).arg(out_err);
::LocalFree( lpMsgBuf );
}
else
LPVOID lpMsgBuf;
::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
- err = QString( "Failed to find %1 function. %2" ).arg( GET_MODULE_NAME ).arg( (LPTSTR)lpMsgBuf );
- ::LocalFree( lpMsgBuf );
+#ifdef UNICODE
+ QString out_err = QString::fromWCharArray((LPTSTR)lpMsgBuf);
+#else
+ QString out_err = (LPTSTR)lpMsgBuf;
+#endif
+
+ err = QString( "Failed to find %1 function. %2" ).arg( GET_MODULE_NAME ).arg( out_err );
+ ::LocalFree( lpMsgBuf );
}
getVersion = (GET_VERSION_FUNC)::GetProcAddress( modLib, GET_VERSION_NAME );
}
#else
- void* modLib = dlopen( libName.toLatin1(), RTLD_LAZY );
+ void* modLib = dlopen( libName.toUtf8(), RTLD_LAZY | RTLD_GLOBAL );
if ( !modLib )
err = QString( "Can not load library %1. %2" ).arg( libName ).arg( dlerror() );
else
char* version = getVersion ? getVersion() : 0;
- if(version) {
+ if ( version ) {
for ( ModuleInfoList::iterator it = myInfoList.begin(); it != myInfoList.end(); ++it ) {
if ( (*it).title == modName ) {
if( (*it).version.isEmpty() ) {
*/
bool CAM_Application::activateModule( const QString& modName )
{
- if ( !modName.isEmpty() && !activeStudy() || myBlocked )
+ if ( (!modName.isEmpty() && !activeStudy()) || myBlocked )
return false;
// VSR 25/10/2011: prevent nested activation/deactivation
bool res = false;
if ( !modName.isEmpty() )
{
+ setProperty("activateModule", true);
CAM_Module* mod = module( modName );
- if ( !mod && !moduleLibrary( modName ).isEmpty() )
- {
+ if ( !mod )
mod = loadModule( modName );
- addModule( mod );
- }
+ addModule( mod );
if ( mod )
res = activateModule( mod );
+ setProperty("activateModule", QVariant());
}
else
res = activateModule( 0 );
{
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() ) )
return true;
}
+/*!
+ \brief Load module \a modName and activate its operation, corresponding to \a actionId.
+ This method is dedicated to run operations of some module from any other module.
+ \param modName module name
+ \param actionId is a numerical unique operation identifier
+ \return \c true in case of success and \c false otherwise
+*/
+bool CAM_Application::activateOperation( const QString& modName, int actionId )
+{
+ CAM_Module* mod = loadModule(modName, false);
+ if (mod) {
+ addModule(mod);
+ return mod->activateOperation(actionId);
+ }
+ return false;
+}
+
+/*!
+ \brief Load module \a modName and activate its operation, corresponding to \a actionId.
+ This method is dedicated to run operations of some module from any other module.
+ \param modName module name
+ \param actionId is a string unique operation identifier
+ \return \c true in case of success and \c false otherwise
+*/
+bool CAM_Application::activateOperation( const QString& modName, const QString& actionId )
+{
+ CAM_Module* mod = loadModule(modName, false);
+ if (mod) {
+ addModule(mod);
+ return mod->activateOperation(actionId);
+ }
+ return false;
+}
+
+/*!
+ \brief Load module \a modName and activate its operation,
+ corresponding to \a actionId and \a pluginName.
+ This method is dedicated to run operations of some module from any other module.
+ \param modName module name
+ \param actionId is a string unique operation identifier
+ \param pluginName is a name of a plugin where the operation is implemented
+ \return \c true in case of success and \c false otherwise
+*/
+bool CAM_Application::activateOperation( const QString& modName,
+ const QString& actionId,
+ const QString& pluginName )
+{
+ CAM_Module* mod = loadModule(modName, false);
+ if (mod) {
+ addModule(mod);
+ return mod->activateOperation(actionId, pluginName);
+ }
+ return false;
+}
+
/*!
\brief Create new study.
\return study object pointer
STD_Application::setActiveStudy( study );
}
+/*!
+ \brief Check module availability.
+
+ The method can be redefined in successors. Default implementation returns \c true.
+
+ \param title module title
+ \return \c true if module is accessible; \c false otherwise
+*/
+bool CAM_Application::checkModule( const QString& )
+{
+ return true;
+}
+
/*!
\brief Callback function, called when the module is added to the application.
{
}
+/*!
+ \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)
\return module name or null QString if module is not found
*/
-QString CAM_Application::moduleName( const QString& title ) const
+QString CAM_Application::moduleName( const QString& title )
{
QString res;
for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
\param name module name
\return module title (user name) or null QString if module is not found
*/
-QString CAM_Application::moduleTitle( const QString& name ) const
+QString CAM_Application::moduleTitle( const QString& name )
{
QString res;
for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
/*!
\brief Get module icon name.
- \param name module name
+ \param name module name or title
\return module icon or null QString if module is not found
*/
-QString CAM_Application::moduleIcon( const QString& name ) const
+QString CAM_Application::moduleIcon( const QString& name )
{
QString res;
for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isNull(); ++it )
{
- if ( (*it).name == name )
+ if ( (*it).name == name || (*it).title == name )
res = (*it).icon;
}
return res;
}
/*!
- \brief Returns \c true if module is accessible for the current application.
- Singleton module can be loaded only in one application object. In other application
- objects this module will be unavailable.
- \param title module title (user name)
- \return \c true if module is accessible (can be loaded) or \c false otherwise
- */
-bool CAM_Application::isModuleAccessible( const QString& title ) const
+ \brief Get module description.
+ \param name module name or title
+ \return module description or null QString if description is not provided in config file.
+*/
+QString CAM_Application::moduleDescription( const QString& name )
{
- bool found = false;
- bool blocked = false;
-
- QStringList somewhereLoaded;
- QList<SUIT_Application*> apps = SUIT_Session::session()->applications();
- foreach( SUIT_Application* app, apps ) {
- CAM_Application* camApp = dynamic_cast<CAM_Application*>( app );
- if ( !camApp ) continue;
- QStringList loaded;
- camApp->modules( loaded, true );
- foreach( QString lm, loaded ) {
- if ( !somewhereLoaded.contains( lm ) ) somewhereLoaded << lm;
- }
- }
-
- for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && !found; ++it )
+ QString res;
+ for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isNull(); ++it )
{
- found = (*it).title == title;
- blocked = (*it).isSingleton && somewhereLoaded.contains((*it).title);
+ if ( (*it).name == name || (*it).title == name )
+ res = tr((*it).description.toUtf8());
}
- return found && !blocked;
+ return res;
}
/*!
\brief Get module library name by its title (user name).
- \param title module title (user name)
+ \param title module name or title
\param full if \c true, return full library name, otherwise return its internal name
\return module library name or null QString if module is not found
*/
-QString CAM_Application::moduleLibrary( const QString& title, const bool full ) const
+QString CAM_Application::moduleLibrary( const QString& name, const bool full )
{
QString res;
for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
{
- if ( (*it).title == title )
- res = (*it).internal;
+ if ( (*it).name == name || (*it).title == name )
+ res = (*it).library;
}
if ( !res.isEmpty() && full )
res = SUIT_Tools::library( res );
return res;
}
+/*!
+ \brief Get displayer proxy for given module, by its title (user name).
+ \param name module name or title
+ \return name of module which provides displayer for requested module
+ */
+QString CAM_Application::moduleDisplayer( const QString& name )
+{
+ QString res;
+
+ if ( !name.isEmpty() )
+ {
+ for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
+ {
+ if ( (*it).title == name || (*it).name == name ) {
+ res = (*it).displayer;
+ if ( res.isEmpty() )
+ res = (*it).title;
+ }
+ }
+ }
+
+ return res;
+}
+
/*!
\brief Read modules information list
if ( !moduleTitle( modName ).isEmpty() )
continue; // already added
- QString modTitle = resMgr->stringValue( *it, "name", QString() );
- if ( modTitle.isEmpty() )
- {
- printf( "****************************************************************\n" );
- printf( "* Warning: %s GUI resources are not found.\n", qPrintable(*it) );
- printf( "* %s GUI will not be available.\n", qPrintable(*it) );
- printf( "****************************************************************\n" );
- continue;
- }
+ if ( modName == "KERNEL" || modName == "GUI" )
+ continue; // omit KERNEL and GUI modules
+
+ bool hasGui = resMgr->booleanValue( *it, "gui", true );
- QString modIcon = resMgr->stringValue( *it, "icon", QString() );
+ QString modTitle, modIcon, modLibrary, modDescription;
- QString modLibrary = resMgr->stringValue( *it, "library", QString() ).trimmed();
- if ( !modLibrary.isEmpty() )
+ if ( hasGui )
{
- modLibrary = SUIT_Tools::file( modLibrary.trimmed() );
-#ifdef WIN32
- QString libExt = QString( "dll" );
+ // if module has GUI, check that it is present
+ modTitle = resMgr->stringValue( *it, "name", QString() );
+ if ( modTitle.isEmpty() )
+ {
+ 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( "****************************************************************\n" );
+ continue;
+ }
+
+ modIcon = resMgr->stringValue( *it, "icon", QString() );
+
+ modDescription = resMgr->stringValue( *it, "description", QString() );
+
+ 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" );
+ QString libExt = QString( "so" );
#endif
- if ( SUIT_Tools::extension( modLibrary ).toLower() == libExt )
- modLibrary.truncate( modLibrary.length() - libExt.length() - 1 );
+ 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() );
+ QString prefix = QString( "lib" );
+ if ( modLibrary.startsWith( prefix ) )
+ modLibrary.remove( 0, prefix.length() );
#endif
+ }
+ else
+ modLibrary = modName;
}
- else
- modLibrary = modName;
- bool aIsSingleton = resMgr->booleanValue(*it, "singleton", false);
+ QString version = resMgr->stringValue( *it, "version", QString() );
- QString ver = resMgr->stringValue(*it, "version", QString());
+ QString modDisplayer = resMgr->stringValue( *it, "displayer", QString() );
ModuleInfo inf;
inf.name = modName;
inf.title = modTitle;
- inf.internal = modLibrary;
+ inf.status = hasGui ? stUnknown : stNoGui;
+ if ( hasGui ) inf.library = modLibrary;
inf.icon = modIcon;
- inf.isSingleton = aIsSingleton;
- inf.version = ver;
+ inf.description = modDescription;
+ inf.displayer = modDisplayer;
+ inf.version = version;
myInfoList.append( inf );
}
/*!
\brief Return information about version of the each module.
*/
-CAM_Application::ModuleShortInfoList CAM_Application::getVersionInfo() const {
-
+CAM_Application::ModuleShortInfoList CAM_Application::getVersionInfo()
+{
ModuleShortInfoList info;
ModuleShortInfo kernel;
for(int i = 0; i < myInfoList.size(); i++) {
ModuleShortInfo infoItem;
- infoItem.name = myInfoList.at(i).title;
+ infoItem.name = myInfoList.at(i).title.isEmpty() ? myInfoList.at(i).name : myInfoList.at(i).title;
infoItem.version = myInfoList.at(i).version;
info.append(infoItem);
}
return info;
}
+
+/*!
+ \brief Abort active operations if there are any
+
+ Iterates through all modules and asks each of them if there are pending operations that cannot be aborted.
+
+ \return \c false if some operation cannot be aborted
+*/
+bool CAM_Application::abortAllOperations()
+{
+ bool aborted = true;
+ for ( QList<CAM_Module*>::const_iterator it = myModules.begin(); it != myModules.end() && aborted; ++it )
+ {
+ aborted = (*it)->abortAllOperations();
+ }
+ return aborted;
+}