Salome HOME
bos #18727 [CEA 18716] Warnings at SALOME launch
[modules/gui.git] / src / CAM / CAM_Application.cxx
1 // Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "CAM_Application.h"
24
25 #include "CAM_Study.h"
26 #include "CAM_Module.h"
27
28 #include <SUIT_Tools.h>
29 #include <SUIT_Desktop.h>
30 #include <SUIT_Session.h>
31 #include <SUIT_MessageBox.h>
32 #include <SUIT_ResourceMgr.h>
33
34 #include <KERNEL_version.h>
35 #include <GUI_version.h>
36
37 #include <QApplication>
38 #include <QRegExp>
39
40 #ifdef WIN32
41 #include <windows.h>
42 #else
43 #include <dlfcn.h>
44 #endif
45
46 #include <cstdio>
47 #include <iostream>
48
49 namespace
50 {
51 class BusyLocker
52 {
53 public:
54   BusyLocker( bool& busy ) : myPrev( busy ), myBusy( busy ) { myBusy = true; }
55   ~BusyLocker() { myBusy = myPrev; }
56 private:
57   bool  myPrev;
58   bool& myBusy;
59 };
60 }
61
62 /*!
63   \brief Create new instance of CAM_Application.
64   \return new instance of CAM_Application class
65 */
66 extern "C" CAM_EXPORT SUIT_Application* createApplication()
67 {
68   return new CAM_Application();
69 }
70
71 /*!
72   \class CAM_Application
73   \brief Introduces an application class which provides modular architecture.
74   
75   This class defines multi-modular application configuration and behaviour.
76   Each module (CAM_Module) can have own data model, document windows and 
77   viewers, etc.
78
79   An application provides all necessary functionality for modules management,
80   like
81   - loading of modules
82   - modules activation/deactivation
83   - etc
84 */
85
86 CAM_Application::ModuleInfoList CAM_Application::myInfoList;
87
88 /*!
89   \brief Constructor.
90
91   Read modules list (from command line or from resource file). 
92   If \a autoLoad parameter is \c true all the modules will be loaded
93   immediately after application starting, otherwise each module will
94   be loaded by demand (with activateModule()).
95
96   \param autoLoad auto loading flag
97 */
98 CAM_Application::CAM_Application( const bool autoLoad )
99 : STD_Application(),
100   myModule( 0 ),
101   myAutoLoad( autoLoad ),
102   myBlocked( false )
103 {
104   readModuleList();
105 }
106
107 /*!
108   \brief Destructor.
109
110   Does nothing currently.
111 */
112 CAM_Application::~CAM_Application()
113 {
114   for ( QList<CAM_Module*>::const_iterator it = myModules.begin(); it != myModules.end(); ++it )
115     delete *it;
116   myModules.clear();
117 }
118
119 /*! 
120   \brief Start an application.
121
122   Load all modules, if "auto loading" flag has been set to \c true.
123
124   \sa CAM_Application()
125 */
126 void CAM_Application::start()
127 {
128   // check modules
129   for ( ModuleInfoList::iterator it = myInfoList.begin(); 
130         it != myInfoList.end(); ++it )
131   {
132     if ( (*it).status == stUnknown )
133       (*it).status = checkModule( (*it).title ) ? stReady : stInaccessible;
134   }
135   
136   // auto-load modules
137   if ( myAutoLoad )
138     loadModules();
139
140   STD_Application::start();
141 }
142
143 /*!
144   \brief Get active module.
145   \return active module or 0 if there are no any
146 */
147 CAM_Module* CAM_Application::activeModule() const
148 {
149   return myModule;
150 }
151
152 /*!
153   \brief Get the module with specified name.
154   \return module or 0 if not found
155 */
156 CAM_Module* CAM_Application::module(  const QString& modName ) const
157 {
158   CAM_Module* mod = 0;
159   for ( QList<CAM_Module*>::const_iterator it = myModules.begin(); 
160         it != myModules.end() && !mod; ++it )
161     if ( (*it)->moduleName() == modName )
162       mod = *it;
163   return mod;
164 }
165
166 /*!
167   \brief Get all loaded modules.
168   \return list of modules
169 */
170 CAM_Application::ModuleList CAM_Application::modules() const
171 {
172   return myModules;
173 }
174
175 /*!
176   \brief Get all loaded modules.
177   \param returning list of modules
178 */
179 void CAM_Application::modules( CAM_Application::ModuleList& out ) const
180 {
181   out.clear();
182
183   for ( QList<CAM_Module*>::const_iterator it = myModules.begin(); 
184         it != myModules.end(); ++it )
185     out.append( *it );
186 }
187
188 /*!
189   \brief Get names of all modules.
190
191   Get loaded modules names if \a loaded is \c true, 
192   otherwise get all avaiable modules names.
193   
194   \param lst output list of modules names
195   \param loaded boolean flag, defines what modules names to return
196 */
197 void CAM_Application::modules( QStringList& lst, const bool loaded ) const
198 {
199   lst.clear();
200
201   if ( loaded )
202   {
203     for ( QList<CAM_Module*>::const_iterator it = myModules.begin(); 
204           it != myModules.end(); ++it )
205       lst.append( (*it)->moduleName() );
206   }
207   else
208   {
209     for ( ModuleInfoList::const_iterator it = myInfoList.begin(); 
210           it != myInfoList.end(); ++it )
211       lst.append( (*it).title );
212   }
213 }
214
215 /*!
216   \brief Add module \a mod to the modules list.
217
218   Performes module initialization. Does nothing if the module
219   is already added. 
220   
221   \param mod module being added
222   \sa CAM_Module::initialize()
223 */
224 void CAM_Application::addModule( CAM_Module* mod )
225 {
226   if ( !mod || myModules.contains( mod ) )
227     return;
228
229   mod->initialize( this );
230
231   QMap<CAM_Module*, int> map;
232
233   ModuleList newList;
234   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); 
235         it != myInfoList.end(); ++it )
236   {
237     if ( (*it).title == mod->moduleName() )
238       newList.append( mod );
239     else
240     {
241       CAM_Module* curMod = module( (*it).title );
242       if ( curMod )
243         newList.append( curMod );
244     }
245   }
246
247   for ( QList<CAM_Module*>::const_iterator it = myModules.begin();
248         it != myModules.end(); ++it )
249   {
250     if ( !newList.contains( *it ) )
251       newList.append( *it );
252   }
253
254   if ( !newList.contains( mod ) )
255       newList.append( mod );
256
257   myModules = newList;
258
259   moduleAdded( mod );
260 }
261
262 /*!
263   \brief Load modules from the modules information list.
264   
265   If some module can not be loaded, an error message is shown.
266 */
267 void CAM_Application::loadModules()
268 {
269   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end(); ++it )
270   {
271     CAM_Module* mod = loadModule( (*it).title );
272     if ( mod )
273       addModule( mod );
274     else {
275       QString wrn = tr( "Can not load module %1" ).arg( (*it).title );
276       if ( desktop() && desktop()->isVisible() )
277         SUIT_MessageBox::critical( desktop(), tr( "Loading modules" ), wrn );
278       else
279         qWarning( qPrintable( wrn ) ); 
280     }
281   }
282 }
283
284 /*!
285   \brief Load module \a modName.
286
287   The function prints warning message if:
288   - modules information list is empty
289   - modules information list does not include specified module info
290   - module library can not be loaded by some reason
291
292   \param modName module name
293   \return module object pointer or 0 if module could not be loaded
294 */
295 CAM_Module* CAM_Application::loadModule( const QString& modName, const bool showMsg )
296 {
297   if ( myInfoList.isEmpty() )
298   {
299     qWarning( qPrintable( tr( "Modules configuration is not defined." ) ) );
300     return 0;
301   }
302
303   QString libName = moduleLibrary( modName );
304   if ( libName.isEmpty() )
305   {
306     qWarning( qPrintable( tr( "Information about module \"%1\" doesn't exist." ).arg( modName ) ) );
307     return 0;
308   }
309
310   QString err;
311   GET_MODULE_FUNC crtInst = 0;
312   GET_VERSION_FUNC getVersion = 0;
313
314 #ifdef WIN32
315 #ifdef UNICODE
316   LPTSTR str_libname = new TCHAR[libName.length() + 1];
317   str_libname[libName.toWCharArray(str_libname)] = '\0';
318 #else
319   QByteArray arr = libName.toLatin1();
320   LPTSTR str_libname = arr.constData();
321 #endif
322   HINSTANCE modLib = ::LoadLibrary( str_libname );
323 #ifdef UNICODE
324   delete str_libname;
325 #endif
326   if ( !modLib )
327   {
328     LPVOID lpMsgBuf;
329     ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
330                      FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
331 #ifdef UNICODE
332         QString out_err = QString::fromWCharArray((LPTSTR)lpMsgBuf);
333 #else 
334         QString out_err = (LPTSTR)lpMsgBuf;
335 #endif
336     err = QString( "Failed to load  %1. %2" ).arg( libName ).arg(out_err);
337     ::LocalFree( lpMsgBuf );
338   }
339   else
340   {
341     crtInst = (GET_MODULE_FUNC)::GetProcAddress( modLib, GET_MODULE_NAME );
342     if ( !crtInst )
343     {
344       LPVOID lpMsgBuf;
345       ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
346                        FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
347 #ifdef UNICODE
348           QString out_err = QString::fromWCharArray((LPTSTR)lpMsgBuf);
349 #else 
350           QString out_err = (LPTSTR)lpMsgBuf;
351 #endif
352
353           err = QString( "Failed to find  %1 function. %2" ).arg( GET_MODULE_NAME ).arg( out_err );
354           ::LocalFree( lpMsgBuf );
355     }
356
357     getVersion = (GET_VERSION_FUNC)::GetProcAddress( modLib, GET_VERSION_NAME );
358   }
359 #else
360   void* modLib = dlopen( libName.toUtf8(), RTLD_LAZY | RTLD_GLOBAL );
361   if ( !modLib )
362     err = QString( "Can not load library %1. %2" ).arg( libName ).arg( dlerror() );
363   else
364   {
365     crtInst = (GET_MODULE_FUNC)dlsym( modLib, GET_MODULE_NAME );
366     if ( !crtInst )
367       err = QString( "Failed to find function %1. %2" ).arg( GET_MODULE_NAME ).arg( dlerror() );
368
369     getVersion = (GET_VERSION_FUNC)dlsym( modLib, GET_VERSION_NAME );
370   }
371 #endif
372
373   CAM_Module* module = crtInst ? crtInst() : 0;
374   if ( module )
375   {
376     module->setModuleName( modName );
377     module->setName( moduleName( modName ) );
378   }
379
380   if ( !err.isEmpty() && showMsg ) {
381     if ( desktop() && desktop()->isVisible() )
382       SUIT_MessageBox::warning( desktop(), tr( "Error" ), err );
383     else
384       qWarning( qPrintable( err ) ); 
385   }
386
387   char* version = getVersion ? getVersion() : 0;
388
389   if ( version ) {    
390     for ( ModuleInfoList::iterator it = myInfoList.begin(); it != myInfoList.end(); ++it ) {
391       if ( (*it).title == modName ) {
392         if( (*it).version.isEmpty() ) {
393           (*it).version = QString(version);
394         }
395         break;
396       }
397     }
398   }
399   
400   return module;
401 }
402
403 /*!
404   \brief Activate module \a modName.
405   \param modName module name
406   \return \c true, if module is loaded and activated successfully and \c false otherwise
407 */
408 bool CAM_Application::activateModule( const QString& modName )
409 {
410   if ( (!modName.isEmpty() && !activeStudy()) || myBlocked )
411     return false;
412
413   // VSR 25/10/2011: prevent nested activation/deactivation
414   // See issues 0021307, 0021373
415   BusyLocker lock( myBlocked );
416
417   bool res = false;
418   if ( !modName.isEmpty() )
419   {
420     CAM_Module* mod = module( modName );
421     if ( !mod )
422       mod = loadModule( modName );
423     addModule( mod );
424
425     if ( mod )
426       res = activateModule( mod );
427   }
428   else
429     res = activateModule( 0 );
430
431   return res;
432 }
433
434 /*!
435   \brief Activate module \a mod.
436
437   Shows error message if module could not be activated in the current study.
438
439   \param mod module object pointer
440   \return \c true, if module is loaded and activated successfully and \c false otherwise
441 */
442 bool CAM_Application::activateModule( CAM_Module* mod )
443 {
444   if ( mod && !activeStudy() )
445     return false;
446
447   if ( myModule == mod )
448     return true;
449
450   if ( myModule )
451   {
452     if ( !myModule->deactivateModule( activeStudy() ) )
453     {
454       // ....      
455     }    
456   }     
457   myModule = mod;
458
459   if ( myModule ){
460     // Connect the module to the active study
461     myModule->connectToStudy( dynamic_cast<CAM_Study*>( activeStudy() ) );
462     if ( !myModule->activateModule( activeStudy() ) )
463     {
464       myModule->setMenuShown( false );
465       myModule->setToolShown( false );
466       QString wrn = tr( "ERROR_ACTIVATE_MODULE_MSG" ).arg( myModule->moduleName() );
467       if ( desktop() && desktop()->isVisible() )
468         SUIT_MessageBox::critical( desktop(), tr( "ERROR_TLT" ), wrn );
469       else
470         qWarning( qPrintable( wrn ) ); 
471       myModule = 0;
472       return false;
473     }
474   }
475
476   updateCommandsStatus();
477
478   return true;
479 }
480
481 /*!
482   \brief Load module \a modName and activate its operation, corresponding to \a actionId.
483   This method is dedicated to run operations of some module from any other module.
484   \param modName module name
485   \param actionId is a numerical unique operation identifier
486   \return \c true in case of success and \c false otherwise
487 */
488 bool CAM_Application::activateOperation( const QString& modName, int actionId )
489 {
490   CAM_Module* mod = loadModule(modName, false);
491   if (mod) {
492     addModule(mod);
493     return mod->activateOperation(actionId);
494   }
495   return false;
496 }
497
498 /*!
499   \brief Load module \a modName and activate its operation, corresponding to \a actionId.
500   This method is dedicated to run operations of some module from any other module.
501   \param modName module name
502   \param actionId is a string unique operation identifier
503   \return \c true in case of success and \c false otherwise
504 */
505 bool CAM_Application::activateOperation( const QString& modName, const QString& actionId )
506 {
507   CAM_Module* mod = loadModule(modName, false);
508   if (mod) {
509     addModule(mod);
510     return mod->activateOperation(actionId);
511   }
512   return false;
513 }
514
515 /*!
516   \brief Load module \a modName and activate its operation,
517          corresponding to \a actionId and \a pluginName.
518   This method is dedicated to run operations of some module from any other module.
519   \param modName module name
520   \param actionId is a string unique operation identifier
521   \param pluginName is a name of a plugin where the operation is implemented
522   \return \c true in case of success and \c false otherwise
523 */
524 bool CAM_Application::activateOperation( const QString& modName,
525                                          const QString& actionId,
526                                          const QString& pluginName )
527 {
528   CAM_Module* mod = loadModule(modName, false);
529   if (mod) {
530     addModule(mod);
531     return mod->activateOperation(actionId, pluginName);
532   }
533   return false;
534 }
535
536 /*!
537   \brief Create new study.
538   \return study object pointer
539 */
540 SUIT_Study* CAM_Application::createNewStudy() 
541
542   return new CAM_Study( this );
543 }
544
545 /*!
546   \brief Update menu commands status.
547 */
548 void CAM_Application::updateCommandsStatus()
549 {
550   STD_Application::updateCommandsStatus();
551
552   if ( activeModule() )
553     activeModule()->updateCommandsStatus();
554 }
555
556 /*!
557   \brief Prepare application to study closing.
558
559   Closes all modules in study \a theDoc.
560   
561   \param theDoc study
562 */
563 void CAM_Application::beforeCloseDoc( SUIT_Study* theDoc )
564 {
565   for ( QList<CAM_Module*>::iterator it = myModules.begin(); it != myModules.end(); ++it )
566     (*it)->studyClosed( theDoc );
567 }
568
569 void CAM_Application::afterCloseDoc()
570 {
571 }
572
573 /*!
574   \brief Set active study.
575   \param study study to be made active
576 */
577 void CAM_Application::setActiveStudy( SUIT_Study* study )
578 {
579   STD_Application::setActiveStudy( study );
580 }
581
582 /*!
583   \brief Check module availability.
584
585   The method can be redefined in successors. Default implementation returns \c true.
586
587   \param title module title
588   \return \c true if module is accessible; \c false otherwise
589 */
590 bool CAM_Application::checkModule( const QString& )
591 {
592   return true;
593 }
594
595 /*!
596   \brief Callback function, called when the module is added to the application.
597   
598   This virtual method can be re-implemented in the successors. Base implementation
599   does nothing.
600
601   \param mod module being added
602 */
603 void CAM_Application::moduleAdded( CAM_Module* /*mod*/ )
604 {
605 }
606
607 /*!
608   \brief Get module name by its title (user name).
609   \param title module title (user name)
610   \return module name or null QString if module is not found
611 */
612 QString CAM_Application::moduleName( const QString& title )
613 {
614   QString res;
615   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
616   {
617     if ( (*it).title == title )
618       res = (*it).name;
619   }
620   return res;
621 }
622
623 /*!
624   \brief Get module title (user name) by its name.
625   \param name module name
626   \return module title (user name) or null QString if module is not found
627 */
628 QString CAM_Application::moduleTitle( const QString& name )
629 {
630   QString res;
631   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
632   {
633     if ( (*it).name == name )
634       res = (*it).title;
635   }
636   return res;
637 }
638
639 /*!
640   \brief Get module icon name.
641   \param name module name
642   \return module icon or null QString if module is not found
643 */
644 QString CAM_Application::moduleIcon( const QString& name )
645 {
646   QString res;
647   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isNull(); ++it )
648   {
649     if ( (*it).name == name )
650       res = (*it).icon;
651   }
652   return res;
653 }
654
655 /*!
656   \brief Get module library name by its title (user name).
657   \param title module title (user name)
658   \param full if \c true, return full library name, otherwise return its internal name
659   \return module library name or null QString if module is not found
660  */
661 QString CAM_Application::moduleLibrary( const QString& title, const bool full )
662 {
663   QString res;
664   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
665   {
666     if ( (*it).title == title )
667       res = (*it).library;
668   }
669   if ( !res.isEmpty() && full )
670     res = SUIT_Tools::library( res );
671   return res;
672 }
673
674 /*!
675   \brief Read modules information list
676
677   This function first tries to get the modules names list by parsing
678   the application command line arguments, looking for the
679   "--modules ( <mod_name>[:<mod_name>...] )" option.
680   List of modules is separated by colon symbol (":").
681   
682   If "--modules" command line option is not used, the list of modules
683   is retrieved from the application resource file: parameter "modules" of
684   the section "launch".
685
686   Then the information about each module (module title (user name), 
687   library name) is retrieved from the corresponding section of resource
688   file with help of resources manager.
689
690   Shows the warning message, if module information list is empty.
691
692   \sa SUIT_ResourceMgr
693 */
694 void CAM_Application::readModuleList()
695 {
696   if ( !myInfoList.isEmpty() )
697     return;
698
699   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
700
701   QStringList modList;
702
703   QString args = QApplication::arguments().join( " " );
704
705   QRegExp rx1("--modules=([\\w,]*)");
706   rx1.setMinimal( false );
707   QRegExp rx2("--modules\\s+\\(\\s*(.*)\\s*\\)");
708   rx2.setMinimal( true );
709   int pos = 0;
710   while ( 1 ) {
711     QString modules;
712     int pos1 = rx1.indexIn( args, pos );
713     int pos2 = rx2.indexIn( args, pos );
714     if ( pos1 != -1 && pos2 != -1 ) {
715       modules = pos1 < pos2 ? rx1.cap( 1 ) : rx2.cap(1);
716       pos = pos1 < pos2 ? pos1 + rx1.matchedLength() : pos2 + rx2.matchedLength();
717     }
718     else if ( pos1 != -1 ) {
719       modules = rx1.cap( 1 );
720       pos = pos1 + rx1.matchedLength();
721     }
722     else if ( pos2 != -1 ) {
723       modules = rx2.cap( 1 );
724       pos = pos2 + rx2.matchedLength();
725     }
726     else {
727       break;
728     }
729
730     modList.clear();
731     QStringList mods = modules.split( QRegExp( "[:|,\\s]" ), QString::SkipEmptyParts );
732     for ( int i = 0; i < mods.count(); i++ ) {
733       if ( !mods[i].trimmed().isEmpty() )
734         modList.append( mods[i].trimmed() );
735     }
736   }
737
738   if ( modList.isEmpty() ) {
739     QString mods = resMgr->stringValue( "launch", "modules", QString() );
740     modList = mods.split( ",", QString::SkipEmptyParts );
741   }
742
743   for ( QStringList::const_iterator it = modList.begin(); it != modList.end(); ++it )
744   {
745     QString modName = (*it).trimmed();
746
747     if ( modName.isEmpty() )
748       continue;  // empty module name
749
750     if ( !moduleTitle( modName ).isEmpty() )
751       continue;  // already added
752
753     if ( modName == "KERNEL" || modName == "GUI" )
754       continue; // omit KERNEL and GUI modules
755
756     bool hasGui = resMgr->booleanValue( *it, "gui", true );
757     if ( !hasGui )
758       continue; // omit if module is explicitly declared as not having GUI
759
760     QString modTitle = resMgr->stringValue( *it, "name", QString() );
761     if ( modTitle.isEmpty() )
762     {
763       printf( "****************************************************************\n" );
764       printf( "     Warning: module %s is improperly configured!\n", qPrintable(*it) );
765       printf( "     Module %s will not be available in GUI mode!\n", qPrintable(*it) );
766       printf( "****************************************************************\n" );
767       continue;
768     }
769
770     QString modIcon = resMgr->stringValue( *it, "icon", QString() );
771
772     QString modLibrary = resMgr->stringValue( *it, "library", QString() ).trimmed();
773     if ( !modLibrary.isEmpty() )
774     {
775       modLibrary = SUIT_Tools::file( modLibrary.trimmed() );
776 #if defined(WIN32)
777       QString libExt = QString( "dll" );
778 #elif defined(__APPLE__)
779       QString libExt = QString( "dylib" );
780 #else
781       QString libExt = QString( "so" );
782 #endif
783       if ( SUIT_Tools::extension( modLibrary ).toLower() == libExt )
784         modLibrary.truncate( modLibrary.length() - libExt.length() - 1 );
785 #ifndef WIN32
786       QString prefix = QString( "lib" );
787       if ( modLibrary.startsWith( prefix ) )
788         modLibrary.remove( 0, prefix.length() );
789 #endif
790     }
791     else
792       modLibrary = modName;
793
794     QString version = resMgr->stringValue( *it, "version", QString() );
795
796     ModuleInfo inf;
797     inf.name = modName;
798     inf.title = modTitle;
799     inf.status = hasGui ? stUnknown : stNoGui;
800     if ( hasGui ) inf.library = modLibrary;
801     inf.icon = modIcon;
802     inf.version = version;
803     myInfoList.append( inf );
804   }
805
806   if ( myInfoList.isEmpty() ) {
807     if ( desktop() && desktop()->isVisible() )
808       SUIT_MessageBox::warning( desktop(), tr( "Warning" ), tr( "Modules list is empty" ) );
809     else
810       {
811         printf( "****************************************************************\n" );
812         printf( "*    Warning: modules list is empty.\n" );
813         printf( "****************************************************************\n" );
814       }
815   }
816 }
817
818 /*!
819   \brief Add common menu items to the popup menu.
820
821   Menu items list is defined by the active module.
822
823   \param type popup menu context
824   \param menu popup menu
825   \param title popup menu title, which can be set by the module if required
826 */
827 void CAM_Application::contextMenuPopup( const QString& type, QMenu* menu, QString& title )
828 {
829   // to do : add common items for popup menu ( if they are exist )
830   if ( activeModule() ) 
831     activeModule()->contextMenuPopup( type, menu, title );
832 }
833
834 /*!
835   \brief Create new empty study.
836 */
837 void CAM_Application::createEmptyStudy()
838 {
839   /*SUIT_Study* study = */activeStudy();
840   STD_Application::createEmptyStudy();
841 }
842
843 /*!
844   \brief Return information about version of the each module.
845 */
846 CAM_Application::ModuleShortInfoList CAM_Application::getVersionInfo()
847 {
848   ModuleShortInfoList info;
849
850   ModuleShortInfo kernel;
851   kernel.name = "KERNEL";
852   kernel.version = KERNEL_VERSION_STR;
853   info.append(kernel);
854
855   ModuleShortInfo gui;
856   gui.name = "GUI";
857   gui.version = GUI_VERSION_STR;
858   info.append(gui);
859
860   for(int i = 0; i < myInfoList.size(); i++) {
861     ModuleShortInfo infoItem;
862     infoItem.name = myInfoList.at(i).title;
863     infoItem.version = myInfoList.at(i).version;
864     info.append(infoItem);
865   }  
866   return info;
867 }
868
869 /*!
870   \brief Abort active operations if there are any
871  
872   Iterates through all modules and asks each of them if there are pending operations that cannot be aborted.
873  
874   \return \c false if some operation cannot be aborted
875 */
876 bool CAM_Application::abortAllOperations()
877 {
878   bool aborted = true;
879   for ( QList<CAM_Module*>::const_iterator it = myModules.begin(); it != myModules.end() && aborted; ++it )
880   {
881     aborted = (*it)->abortAllOperations();
882   }
883   return aborted;
884 }