Salome HOME
Copyright update 2022
[modules/gui.git] / src / CAM / CAM_Application.cxx
1 // Copyright (C) 2007-2022  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       if ( (*it).status != stNoGui )
212         lst.append( (*it).title );
213   }
214 }
215
216 /*!
217   \brief Add module \a mod to the modules list.
218
219   Performes module initialization. Does nothing if the module
220   is already added. 
221   
222   \param mod module being added
223   \sa CAM_Module::initialize()
224 */
225 void CAM_Application::addModule( CAM_Module* mod )
226 {
227   if ( !mod || myModules.contains( mod ) )
228     return;
229
230   mod->initialize( this );
231
232   QMap<CAM_Module*, int> map;
233
234   ModuleList newList;
235   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); 
236         it != myInfoList.end(); ++it )
237   {
238     if ( (*it).title == mod->moduleName() )
239       newList.append( mod );
240     else
241     {
242       CAM_Module* curMod = module( (*it).title );
243       if ( curMod )
244         newList.append( curMod );
245     }
246   }
247
248   for ( QList<CAM_Module*>::const_iterator it = myModules.begin();
249         it != myModules.end(); ++it )
250   {
251     if ( !newList.contains( *it ) )
252       newList.append( *it );
253   }
254
255   if ( !newList.contains( mod ) )
256       newList.append( mod );
257
258   myModules = newList;
259
260   moduleAdded( mod );
261 }
262
263 /*!
264   \brief Load modules from the modules information list.
265   
266   If some module can not be loaded, an error message is shown.
267 */
268 void CAM_Application::loadModules()
269 {
270   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end(); ++it )
271   {
272     CAM_Module* mod = loadModule( (*it).title );
273     if ( mod )
274       addModule( mod );
275     else {
276       QString wrn = tr( "Can not load module %1" ).arg( (*it).title );
277       if ( desktop() && desktop()->isVisible() )
278         SUIT_MessageBox::critical( desktop(), tr( "Loading modules" ), wrn );
279       else
280         qWarning( qPrintable( wrn ) ); 
281     }
282   }
283 }
284
285 /*!
286   \brief Load module \a modName.
287
288   The function prints warning message if:
289   - modules information list is empty
290   - modules information list does not include specified module info
291   - module library can not be loaded by some reason
292
293   \param modName module name
294   \return module object pointer or 0 if module could not be loaded
295 */
296 CAM_Module* CAM_Application::loadModule( const QString& modName, const bool showMsg )
297 {
298   if ( myInfoList.isEmpty() )
299   {
300     qWarning( qPrintable( tr( "Modules configuration is not defined." ) ) );
301     return 0;
302   }
303
304   QString libName = moduleLibrary( modName );
305   if ( libName.isEmpty() )
306   {
307     qWarning( qPrintable( tr( "Information about module \"%1\" doesn't exist." ).arg( modName ) ) );
308     return 0;
309   }
310
311   QString err;
312   GET_MODULE_FUNC crtInst = 0;
313   GET_VERSION_FUNC getVersion = 0;
314
315 #ifdef WIN32
316 #ifdef UNICODE
317   LPTSTR str_libname = new TCHAR[libName.length() + 1];
318   str_libname[libName.toWCharArray(str_libname)] = '\0';
319 #else
320   QByteArray arr = libName.toLatin1();
321   LPTSTR str_libname = arr.constData();
322 #endif
323   HINSTANCE modLib = ::LoadLibrary( str_libname );
324 #ifdef UNICODE
325   delete str_libname;
326 #endif
327   if ( !modLib )
328   {
329     LPVOID lpMsgBuf;
330     ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
331                      FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
332 #ifdef UNICODE
333         QString out_err = QString::fromWCharArray((LPTSTR)lpMsgBuf);
334 #else 
335         QString out_err = (LPTSTR)lpMsgBuf;
336 #endif
337     err = QString( "Failed to load  %1. %2" ).arg( libName ).arg(out_err);
338     ::LocalFree( lpMsgBuf );
339   }
340   else
341   {
342     crtInst = (GET_MODULE_FUNC)::GetProcAddress( modLib, GET_MODULE_NAME );
343     if ( !crtInst )
344     {
345       LPVOID lpMsgBuf;
346       ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
347                        FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
348 #ifdef UNICODE
349           QString out_err = QString::fromWCharArray((LPTSTR)lpMsgBuf);
350 #else 
351           QString out_err = (LPTSTR)lpMsgBuf;
352 #endif
353
354           err = QString( "Failed to find  %1 function. %2" ).arg( GET_MODULE_NAME ).arg( out_err );
355           ::LocalFree( lpMsgBuf );
356     }
357
358     getVersion = (GET_VERSION_FUNC)::GetProcAddress( modLib, GET_VERSION_NAME );
359   }
360 #else
361   void* modLib = dlopen( libName.toUtf8(), RTLD_LAZY | RTLD_GLOBAL );
362   if ( !modLib )
363     err = QString( "Can not load library %1. %2" ).arg( libName ).arg( dlerror() );
364   else
365   {
366     crtInst = (GET_MODULE_FUNC)dlsym( modLib, GET_MODULE_NAME );
367     if ( !crtInst )
368       err = QString( "Failed to find function %1. %2" ).arg( GET_MODULE_NAME ).arg( dlerror() );
369
370     getVersion = (GET_VERSION_FUNC)dlsym( modLib, GET_VERSION_NAME );
371   }
372 #endif
373
374   CAM_Module* module = crtInst ? crtInst() : 0;
375   if ( module )
376   {
377     module->setModuleName( modName );
378     module->setName( moduleName( modName ) );
379   }
380
381   if ( !err.isEmpty() && showMsg ) {
382     if ( desktop() && desktop()->isVisible() )
383       SUIT_MessageBox::warning( desktop(), tr( "Error" ), err );
384     else
385       qWarning( qPrintable( err ) ); 
386   }
387
388   char* version = getVersion ? getVersion() : 0;
389
390   if ( version ) {    
391     for ( ModuleInfoList::iterator it = myInfoList.begin(); it != myInfoList.end(); ++it ) {
392       if ( (*it).title == modName ) {
393         if( (*it).version.isEmpty() ) {
394           (*it).version = QString(version);
395         }
396         break;
397       }
398     }
399   }
400   
401   return module;
402 }
403
404 /*!
405   \brief Activate module \a modName.
406   \param modName module name
407   \return \c true, if module is loaded and activated successfully and \c false otherwise
408 */
409 bool CAM_Application::activateModule( const QString& modName )
410 {
411   if ( (!modName.isEmpty() && !activeStudy()) || myBlocked )
412     return false;
413
414   // VSR 25/10/2011: prevent nested activation/deactivation
415   // See issues 0021307, 0021373
416   BusyLocker lock( myBlocked );
417
418   bool res = false;
419   if ( !modName.isEmpty() )
420   {
421     setProperty("activateModule", true);
422     CAM_Module* mod = module( modName );
423     if ( !mod )
424       mod = loadModule( modName );
425     addModule( mod );
426
427     if ( mod )
428       res = activateModule( mod );
429     setProperty("activateModule", QVariant());
430   }
431   else
432     res = activateModule( 0 );
433
434   return res;
435 }
436
437 /*!
438   \brief Activate module \a mod.
439
440   Shows error message if module could not be activated in the current study.
441
442   \param mod module object pointer
443   \return \c true, if module is loaded and activated successfully and \c false otherwise
444 */
445 bool CAM_Application::activateModule( CAM_Module* mod )
446 {
447   if ( mod && !activeStudy() )
448     return false;
449
450   if ( myModule == mod )
451     return true;
452
453   if ( myModule )
454   {
455     if ( !myModule->deactivateModule( activeStudy() ) )
456     {
457       // ....      
458     }    
459   }     
460   myModule = mod;
461
462   if ( myModule ){
463     // Connect the module to the active study
464     myModule->connectToStudy( dynamic_cast<CAM_Study*>( activeStudy() ) );
465     if ( !myModule->activateModule( activeStudy() ) )
466     {
467       myModule->setMenuShown( false );
468       myModule->setToolShown( false );
469       QString wrn = tr( "ERROR_ACTIVATE_MODULE_MSG" ).arg( myModule->moduleName() );
470       if ( desktop() && desktop()->isVisible() )
471         SUIT_MessageBox::critical( desktop(), tr( "ERROR_TLT" ), wrn );
472       else
473         qWarning( qPrintable( wrn ) ); 
474       myModule = 0;
475       return false;
476     }
477   }
478
479   updateCommandsStatus();
480
481   return true;
482 }
483
484 /*!
485   \brief Load module \a modName and activate its operation, corresponding to \a actionId.
486   This method is dedicated to run operations of some module from any other module.
487   \param modName module name
488   \param actionId is a numerical unique operation identifier
489   \return \c true in case of success and \c false otherwise
490 */
491 bool CAM_Application::activateOperation( const QString& modName, int actionId )
492 {
493   CAM_Module* mod = loadModule(modName, false);
494   if (mod) {
495     addModule(mod);
496     return mod->activateOperation(actionId);
497   }
498   return false;
499 }
500
501 /*!
502   \brief Load module \a modName and activate its operation, corresponding to \a actionId.
503   This method is dedicated to run operations of some module from any other module.
504   \param modName module name
505   \param actionId is a string unique operation identifier
506   \return \c true in case of success and \c false otherwise
507 */
508 bool CAM_Application::activateOperation( const QString& modName, const QString& actionId )
509 {
510   CAM_Module* mod = loadModule(modName, false);
511   if (mod) {
512     addModule(mod);
513     return mod->activateOperation(actionId);
514   }
515   return false;
516 }
517
518 /*!
519   \brief Load module \a modName and activate its operation,
520          corresponding to \a actionId and \a pluginName.
521   This method is dedicated to run operations of some module from any other module.
522   \param modName module name
523   \param actionId is a string unique operation identifier
524   \param pluginName is a name of a plugin where the operation is implemented
525   \return \c true in case of success and \c false otherwise
526 */
527 bool CAM_Application::activateOperation( const QString& modName,
528                                          const QString& actionId,
529                                          const QString& pluginName )
530 {
531   CAM_Module* mod = loadModule(modName, false);
532   if (mod) {
533     addModule(mod);
534     return mod->activateOperation(actionId, pluginName);
535   }
536   return false;
537 }
538
539 /*!
540   \brief Create new study.
541   \return study object pointer
542 */
543 SUIT_Study* CAM_Application::createNewStudy() 
544
545   return new CAM_Study( this );
546 }
547
548 /*!
549   \brief Update menu commands status.
550 */
551 void CAM_Application::updateCommandsStatus()
552 {
553   STD_Application::updateCommandsStatus();
554
555   if ( activeModule() )
556     activeModule()->updateCommandsStatus();
557 }
558
559 /*!
560   \brief Prepare application to study closing.
561
562   Closes all modules in study \a theDoc.
563   
564   \param theDoc study
565 */
566 void CAM_Application::beforeCloseDoc( SUIT_Study* theDoc )
567 {
568   for ( QList<CAM_Module*>::iterator it = myModules.begin(); it != myModules.end(); ++it )
569     (*it)->studyClosed( theDoc );
570 }
571
572 void CAM_Application::afterCloseDoc()
573 {
574 }
575
576 /*!
577   \brief Set active study.
578   \param study study to be made active
579 */
580 void CAM_Application::setActiveStudy( SUIT_Study* study )
581 {
582   STD_Application::setActiveStudy( study );
583 }
584
585 /*!
586   \brief Check module availability.
587
588   The method can be redefined in successors. Default implementation returns \c true.
589
590   \param title module title
591   \return \c true if module is accessible; \c false otherwise
592 */
593 bool CAM_Application::checkModule( const QString& )
594 {
595   return true;
596 }
597
598 /*!
599   \brief Callback function, called when the module is added to the application.
600   
601   This virtual method can be re-implemented in the successors. Base implementation
602   does nothing.
603
604   \param mod module being added
605 */
606 void CAM_Application::moduleAdded( CAM_Module* /*mod*/ )
607 {
608 }
609
610 /*!
611   \brief Get module name by its title (user name).
612   \param title module title (user name)
613   \return module name or null QString if module is not found
614 */
615 QString CAM_Application::moduleName( const QString& title )
616 {
617   QString res;
618   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
619   {
620     if ( (*it).title == title )
621       res = (*it).name;
622   }
623   return res;
624 }
625
626 /*!
627   \brief Get module title (user name) by its name.
628   \param name module name
629   \return module title (user name) or null QString if module is not found
630 */
631 QString CAM_Application::moduleTitle( const QString& name )
632 {
633   QString res;
634   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
635   {
636     if ( (*it).name == name )
637       res = (*it).title;
638   }
639   return res;
640 }
641
642 /*!
643   \brief Get module icon name.
644   \param name module name or title
645   \return module icon or null QString if module is not found
646 */
647 QString CAM_Application::moduleIcon( const QString& name )
648 {
649   QString res;
650   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isNull(); ++it )
651   {
652     if ( (*it).name == name || (*it).title == name )
653       res = (*it).icon;
654   }
655   return res;
656 }
657
658 /*!
659   \brief Get module description.
660   \param name module name or title
661   \return module description or null QString if description is not provided in config file.
662 */
663 QString CAM_Application::moduleDescription( const QString& name )
664 {
665   QString res;
666   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isNull(); ++it )
667   {
668     if ( (*it).name == name || (*it).title == name )
669       res = tr((*it).description.toUtf8());
670   }
671   return res;
672 }
673
674 /*!
675   \brief Get module library name by its title (user name).
676   \param title module name or title
677   \param full if \c true, return full library name, otherwise return its internal name
678   \return module library name or null QString if module is not found
679  */
680 QString CAM_Application::moduleLibrary( const QString& name, const bool full )
681 {
682   QString res;
683   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
684   {
685     if ( (*it).name == name || (*it).title == name )
686       res = (*it).library;
687   }
688   if ( !res.isEmpty() && full )
689     res = SUIT_Tools::library( res );
690   return res;
691 }
692
693 /*!
694   \brief Get displayer proxy for given module, by its title (user name).
695   \param name module name or title
696   \return name of module which provides displayer for requested module
697  */
698 QString CAM_Application::moduleDisplayer( const QString& name )
699 {
700   QString res;
701
702   if ( !name.isEmpty() )
703   {
704     for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
705     {
706       if ( (*it).title == name || (*it).name == name ) {
707         res = (*it).displayer;
708         if ( res.isEmpty() )
709           res = (*it).title;
710       }
711     }
712   }
713
714   return res;
715 }
716
717 /*!
718   \brief Read modules information list
719
720   This function first tries to get the modules names list by parsing
721   the application command line arguments, looking for the
722   "--modules ( <mod_name>[:<mod_name>...] )" option.
723   List of modules is separated by colon symbol (":").
724   
725   If "--modules" command line option is not used, the list of modules
726   is retrieved from the application resource file: parameter "modules" of
727   the section "launch".
728
729   Then the information about each module (module title (user name), 
730   library name) is retrieved from the corresponding section of resource
731   file with help of resources manager.
732
733   Shows the warning message, if module information list is empty.
734
735   \sa SUIT_ResourceMgr
736 */
737 void CAM_Application::readModuleList()
738 {
739   if ( !myInfoList.isEmpty() )
740     return;
741
742   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
743
744   QStringList modList;
745
746   QString args = QApplication::arguments().join( " " );
747
748   QRegExp rx1("--modules=([\\w,]*)");
749   rx1.setMinimal( false );
750   QRegExp rx2("--modules\\s+\\(\\s*(.*)\\s*\\)");
751   rx2.setMinimal( true );
752   int pos = 0;
753   while ( 1 ) {
754     QString modules;
755     int pos1 = rx1.indexIn( args, pos );
756     int pos2 = rx2.indexIn( args, pos );
757     if ( pos1 != -1 && pos2 != -1 ) {
758       modules = pos1 < pos2 ? rx1.cap( 1 ) : rx2.cap(1);
759       pos = pos1 < pos2 ? pos1 + rx1.matchedLength() : pos2 + rx2.matchedLength();
760     }
761     else if ( pos1 != -1 ) {
762       modules = rx1.cap( 1 );
763       pos = pos1 + rx1.matchedLength();
764     }
765     else if ( pos2 != -1 ) {
766       modules = rx2.cap( 1 );
767       pos = pos2 + rx2.matchedLength();
768     }
769     else {
770       break;
771     }
772
773     modList.clear();
774     QStringList mods = modules.split( QRegExp( "[:|,\\s]" ), QString::SkipEmptyParts );
775     for ( int i = 0; i < mods.count(); i++ ) {
776       if ( !mods[i].trimmed().isEmpty() )
777         modList.append( mods[i].trimmed() );
778     }
779   }
780
781   if ( modList.isEmpty() ) {
782     QString mods = resMgr->stringValue( "launch", "modules", QString() );
783     modList = mods.split( ",", QString::SkipEmptyParts );
784   }
785
786   for ( QStringList::const_iterator it = modList.begin(); it != modList.end(); ++it )
787   {
788     QString modName = (*it).trimmed();
789
790     if ( modName.isEmpty() )
791       continue;  // empty module name
792
793     if ( !moduleTitle( modName ).isEmpty() )
794       continue;  // already added
795
796     if ( modName == "KERNEL" || modName == "GUI" )
797       continue; // omit KERNEL and GUI modules
798
799     bool hasGui = resMgr->booleanValue( *it, "gui", true );
800
801     QString modTitle, modIcon, modLibrary, modDescription;
802
803     if ( hasGui )
804     {
805       // if module has GUI, check that it is present
806       modTitle = resMgr->stringValue( *it, "name", QString() );
807       if ( modTitle.isEmpty() )
808       {
809         printf( "****************************************************************\n" );
810         printf( "     Warning: module %s is improperly configured!\n", qPrintable(*it) );
811         printf( "     Module %s will not be available in GUI mode!\n", qPrintable(*it) );
812         printf( "****************************************************************\n" );
813         continue;
814       }
815
816       modIcon = resMgr->stringValue( *it, "icon", QString() );
817
818       modDescription = resMgr->stringValue( *it, "description", QString() );
819
820       modLibrary = resMgr->stringValue( *it, "library", QString() ).trimmed();
821       if ( !modLibrary.isEmpty() )
822       {
823         modLibrary = SUIT_Tools::file( modLibrary.trimmed() );
824 #if defined(WIN32)
825         QString libExt = QString( "dll" );
826 #elif defined(__APPLE__)
827         QString libExt = QString( "dylib" );
828 #else
829         QString libExt = QString( "so" );
830 #endif
831         if ( SUIT_Tools::extension( modLibrary ).toLower() == libExt )
832           modLibrary.truncate( modLibrary.length() - libExt.length() - 1 );
833 #ifndef WIN32
834         QString prefix = QString( "lib" );
835         if ( modLibrary.startsWith( prefix ) )
836           modLibrary.remove( 0, prefix.length() );
837 #endif
838       }
839       else
840         modLibrary = modName;
841     }
842
843     QString version = resMgr->stringValue( *it, "version", QString() );
844
845     QString modDisplayer = resMgr->stringValue( *it, "displayer", QString() );
846
847     ModuleInfo inf;
848     inf.name = modName;
849     inf.title = modTitle;
850     inf.status = hasGui ? stUnknown : stNoGui;
851     if ( hasGui ) inf.library = modLibrary;
852     inf.icon = modIcon;
853     inf.description = modDescription;
854     inf.displayer = modDisplayer;
855     inf.version = version;
856     myInfoList.append( inf );
857   }
858
859   if ( myInfoList.isEmpty() ) {
860     if ( desktop() && desktop()->isVisible() )
861       SUIT_MessageBox::warning( desktop(), tr( "Warning" ), tr( "Modules list is empty" ) );
862     else
863       {
864         printf( "****************************************************************\n" );
865         printf( "*    Warning: modules list is empty.\n" );
866         printf( "****************************************************************\n" );
867       }
868   }
869 }
870
871 /*!
872   \brief Add common menu items to the popup menu.
873
874   Menu items list is defined by the active module.
875
876   \param type popup menu context
877   \param menu popup menu
878   \param title popup menu title, which can be set by the module if required
879 */
880 void CAM_Application::contextMenuPopup( const QString& type, QMenu* menu, QString& title )
881 {
882   // to do : add common items for popup menu ( if they are exist )
883   if ( activeModule() ) 
884     activeModule()->contextMenuPopup( type, menu, title );
885 }
886
887 /*!
888   \brief Create new empty study.
889 */
890 void CAM_Application::createEmptyStudy()
891 {
892   /*SUIT_Study* study = */activeStudy();
893   STD_Application::createEmptyStudy();
894 }
895
896 /*!
897   \brief Return information about version of the each module.
898 */
899 CAM_Application::ModuleShortInfoList CAM_Application::getVersionInfo()
900 {
901   ModuleShortInfoList info;
902
903   ModuleShortInfo kernel;
904   kernel.name = "KERNEL";
905   kernel.version = KERNEL_VERSION_STR;
906   info.append(kernel);
907
908   ModuleShortInfo gui;
909   gui.name = "GUI";
910   gui.version = GUI_VERSION_STR;
911   info.append(gui);
912
913   for(int i = 0; i < myInfoList.size(); i++) {
914     ModuleShortInfo infoItem;
915     infoItem.name = myInfoList.at(i).title;
916     infoItem.version = myInfoList.at(i).version;
917     info.append(infoItem);
918   }  
919   return info;
920 }
921
922 /*!
923   \brief Abort active operations if there are any
924  
925   Iterates through all modules and asks each of them if there are pending operations that cannot be aborted.
926  
927   \return \c false if some operation cannot be aborted
928 */
929 bool CAM_Application::abortAllOperations()
930 {
931   bool aborted = true;
932   for ( QList<CAM_Module*>::const_iterator it = myModules.begin(); it != myModules.end() && aborted; ++it )
933   {
934     aborted = (*it)->abortAllOperations();
935   }
936   return aborted;
937 }