]> SALOME platform Git repositories - modules/gui.git/blob - src/CAM/CAM_Application.cxx
Salome HOME
Add the possibility to launch Salome with --modules option.
[modules/gui.git] / src / CAM / CAM_Application.cxx
1 #include "CAM_Application.h"
2
3 #include "CAM_Study.h"
4 #include "CAM_Module.h"
5
6 #include <SUIT_Tools.h>
7 #include <SUIT_Session.h>
8 #include <SUIT_MessageBox.h>
9
10 #include <qfile.h> 
11 #include <qfileinfo.h>
12 #include <qtextstream.h>
13 #include <qlabel.h>
14 #include <qfont.h>
15 #include <qapplication.h>
16
17 #ifdef WIN32
18 #include <windows.h>
19 #else
20 #include <dlfcn.h>
21 #endif
22
23 /*!Create new instance of CAM_Application*/
24 extern "C" CAM_EXPORT SUIT_Application* createApplication()
25 {
26   return new CAM_Application();
27 }
28
29 /*!Constructor. read module list.
30  * \param autoLoad - auto load flag.
31  */
32 CAM_Application::CAM_Application( const bool autoLoad )
33 : STD_Application(),
34 myModule( 0 ),
35 myAutoLoad( autoLoad )
36 {
37   readModuleList();
38 }
39
40 /*!Destructor. Do nothing.*/
41 CAM_Application::~CAM_Application()
42 {
43 }
44
45 /*! Load modules, if \a myAutoLoad flag is true.\n
46  * Start application - call start() method from parent class.
47  */
48 void CAM_Application::start()
49 {
50   if ( myAutoLoad )
51     loadModules();
52
53   STD_Application::start();
54 }
55
56 /*!Get active module.
57  * \retval CAM_Module - active module.
58  */
59 CAM_Module* CAM_Application::activeModule() const
60 {
61   return myModule;
62 }
63
64 /*!Get module with name \a modName from modules list.
65  * \retval CAM_Module pointer - module.
66  */
67 CAM_Module* CAM_Application::module(  const QString& modName ) const
68 {
69   CAM_Module* mod = 0;
70   for ( ModuleListIterator it( myModules ); it.current() && !mod; ++it )
71     if ( it.current()->moduleName() == modName )
72       mod = it.current();
73   return mod;
74 }
75
76 /*!Gets modules iterator.*/
77 CAM_Application::ModuleListIterator CAM_Application::modules() const
78 {
79   return ModuleListIterator( myModules );
80 }
81
82 /*!Gets modules list.
83  * \param out - output list of modules.
84  */
85 void CAM_Application::modules( CAM_Application::ModuleList& out ) const
86 {
87   out.setAutoDelete( false );
88   out.clear();
89
90   for ( ModuleListIterator it( myModules ); it.current(); ++it )
91     out.append( it.current() );
92 }
93
94 /*!Gets list of names for modules.\n
95  * Get loaded modules names, if \a loaded is true, else \n
96  * get names from information list.
97  * \param lst - output list of names.
98  * \param loaded - boolean flag.
99  */
100 void CAM_Application::modules( QStringList& lst, const bool loaded ) const
101 {
102   lst.clear();
103
104   if ( loaded )
105     for ( ModuleListIterator it( myModules ); it.current(); ++it )
106       lst.append( it.current()->moduleName() );
107   else
108     for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end(); ++it )
109       lst.append( (*it).title );
110 }
111
112 /*!Adding module \a mod to list.
113  *\param mod - module.
114  */
115 void CAM_Application::addModule( CAM_Module* mod )
116 {
117   if ( !mod || myModules.contains( mod ) )
118     return;
119
120   mod->initialize( this );
121
122   QMap<CAM_Module*, int> map;
123
124   ModuleList newList;
125   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end(); ++it )
126   {
127     if ( (*it).title == mod->moduleName() )
128       newList.append( mod );
129     else
130     {
131       CAM_Module* curMod = module( (*it).title );
132       if ( curMod )
133         newList.append( curMod );
134     }
135     if ( !newList.isEmpty() )
136       map.insert( newList.getLast(), 0 );
137   }
138
139   for ( ModuleListIterator itr( myModules ); itr.current(); ++itr )
140   {
141     if ( !map.contains( itr.current() ) )
142       newList.append( itr.current() );
143   }
144
145   if ( !map.contains( mod ) )
146       newList.append( mod );
147
148   myModules = newList;
149
150   moduleAdded( mod );
151 }
152
153 /*!Load modules from information list.
154  * \warning If some of modules not loaded, error message appear on desktop.
155  */
156 void CAM_Application::loadModules()
157 {
158   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end(); ++it )
159   {
160     CAM_Module* mod = loadModule( (*it).title );
161     if ( mod )
162       addModule( mod );
163     else
164       SUIT_MessageBox::error1( desktop(), tr( "Loading modules" ),
165                                tr( "Can not load module %1" ).arg( (*it).title ), tr( "Ok" ) );
166   }
167 }
168
169 /*!Load module with name \a modName.
170  *\param modName - module name for loading.
171  *\warning If information list is empty.
172  *\warning If module library (for module with \a modName) is empty.
173  *\warning If module library is not loaded.
174  */
175 CAM_Module* CAM_Application::loadModule( const QString& modName )
176 {
177   if ( myInfoList.isEmpty() )
178   {
179     qWarning( tr( "Modules configuration is not defined." ) );
180     return 0;
181   }
182
183   QString libName = moduleLibrary( modName );
184   if ( libName.isEmpty() )
185   {
186     qWarning( tr( "Information about module \"%1\" doesn't exist." ).arg( modName ) );
187     return 0;
188   }
189
190   QString err;
191   GET_MODULE_FUNC crtInst = 0;
192
193 #ifdef WIN32
194   HINSTANCE modLib = ::LoadLibrary( libName ); 
195   if ( !modLib )
196   {
197     LPVOID lpMsgBuf;
198     ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
199                      FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
200     err = QString( "Failed to load  %1. %2" ).arg( libName ).arg( (LPTSTR)lpMsgBuf );
201     ::LocalFree( lpMsgBuf );
202   }
203   else
204   {
205     crtInst = (GET_MODULE_FUNC)::GetProcAddress( modLib, GET_MODULE_NAME );
206     if ( !crtInst )
207     {
208       LPVOID lpMsgBuf;
209       ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
210                        FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
211     err = QString( "Failed to find  %1 function. %2" ).arg( GET_MODULE_NAME ).arg( (LPTSTR)lpMsgBuf );
212     ::LocalFree( lpMsgBuf );
213     }
214   }
215 #else
216   void* modLib = dlopen( (char*)libName.latin1(), RTLD_LAZY );
217   if ( !modLib )
218     err = QString( "Can not load library %1. %2" ).arg( libName ).arg( dlerror() );
219   else
220   {
221     crtInst = (GET_MODULE_FUNC)dlsym( modLib, GET_MODULE_NAME );
222     if ( !crtInst )
223       err = QString( "Failed to find function %1. %2" ).arg( GET_MODULE_NAME ).arg( dlerror() );
224   }
225 #endif
226
227   CAM_Module* module = crtInst ? crtInst() : 0;
228   if ( module )
229   {
230     module->setModuleName( modName );
231     module->setName( moduleName( modName ) );
232   }
233
234   if ( !err.isEmpty() )
235     SUIT_MessageBox::warn1( desktop(), tr( "Error" ), err, tr( "Ok" ) );
236
237   return module;
238 }
239
240 /**@name Activate module group.*/
241 //@{
242 /*!Activate module with name \a modName.
243  *\param modName - module name.
244  *\ratval true, if module loaded and activated successful, else false.
245  */
246 bool CAM_Application::activateModule( const QString& modName )
247 {
248   if ( !modName.isEmpty() && !activeStudy() )
249     return false;
250
251   bool res = false;
252   if ( !modName.isEmpty() )
253   {
254     CAM_Module* mod = module( modName );
255     if ( !mod && !moduleLibrary( modName ).isEmpty() )
256     {
257       mod = loadModule( modName );
258       addModule( mod );
259     }
260
261     if ( mod )
262       res = activateModule( mod );
263   }
264   else
265     res = activateModule( 0 );
266
267   return res;
268 }
269
270 /*!Activate module \a mod
271  *\param mod - module for activation.
272  *\retval true - if all sucessful.
273  *\warning Error message if module not activated in active study.
274  */
275 bool CAM_Application::activateModule( CAM_Module* mod )
276 {
277   if ( mod && !activeStudy() )
278     return false;
279
280   if ( myModule == mod )
281     return true;
282
283   if ( myModule )
284   {
285     if ( !myModule->deactivateModule( activeStudy() ) )
286     {
287       // ....      
288     }    
289   }     
290   myModule = mod;
291
292   if ( myModule ){
293     // Connect the module to the active study
294     myModule->connectToStudy( dynamic_cast<CAM_Study*>( activeStudy() ) );
295     if ( !myModule->activateModule( activeStudy() ) )
296     {
297       myModule->setMenuShown( false );
298       myModule->setToolShown( false );
299       SUIT_MessageBox::error1( desktop(), tr( "ERROR_TLT" ), tr( "ERROR_ACTIVATE_MODULE_MSG" ).arg( myModule->moduleName() ), tr( "BUT_OK" ) );
300       myModule = 0;
301       return false;
302     }
303   }
304
305   updateCommandsStatus();
306
307   return true;
308 }
309 //@}
310
311 /*!Create new study for current application.
312  *\retval study pointer.
313  */
314 SUIT_Study* CAM_Application::createNewStudy() 
315
316   return new CAM_Study( this );
317 }
318
319 /*!Update commands status for parent class and for current class(if module is active)*/
320 void CAM_Application::updateCommandsStatus()
321 {
322   STD_Application::updateCommandsStatus();
323
324   if ( activeModule() )
325     activeModule()->updateCommandsStatus();
326 }
327
328 /*!Close all modules in study \a theDoc.
329  *\param theDoc - study
330  */
331 void CAM_Application::beforeCloseDoc( SUIT_Study* theDoc )
332 {
333   for ( ModuleListIterator it( myModules ); it.current(); ++it )
334     it.current()->studyClosed( theDoc );
335 }
336
337 /*!Sets active study for parent class.
338  *\param study - study.
339  */
340 void CAM_Application::setActiveStudy( SUIT_Study* study )
341 {
342   STD_Application::setActiveStudy( study );
343 }
344
345 /*!Do nothing.*/
346 void CAM_Application::moduleAdded( CAM_Module* mod )
347 {
348 //  CAM_Study* study = dynamic_cast<CAM_Study*>( activeStudy() );
349 //  if ( !study )
350 //    return;
351
352 //  study->insertDataModel( mod->dataModel() );
353 }
354
355 /*!Gets module name by title \a title
356  *\param title - title name
357  *\retval QString module name.
358  */
359 QString CAM_Application::moduleName( const QString& title ) const
360 {
361   QString res;
362   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
363   {
364     if ( (*it).title == title )
365       res = (*it).name;
366   }
367   return res;
368 }
369
370 /*!Gets module title by module name \a name
371  *\param name - module name
372  *\retval QString module title.
373  */
374 QString CAM_Application::moduleTitle( const QString& name ) const
375 {
376   QString res;
377   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
378   {
379     if ( (*it).name == name )
380       res = (*it).title;
381   }
382   return res;
383 }
384
385 /*!Get library name for module with title \a title.
386  *\param title - module title name.
387  *\param full  - boolean flag (if true - return full library name, else internal name)
388  *\retval QString - library name.
389  */
390 QString CAM_Application::moduleLibrary( const QString& title, const bool full ) const
391 {
392   QString res;
393   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
394   {
395     if ( (*it).title == title )
396       res = (*it).internal;
397   }
398   if ( !res.isEmpty() && full )
399     res = SUIT_Tools::library( res );
400   return res;
401 }
402
403 /*!Read modules list*/
404 void CAM_Application::readModuleList()
405 {
406   if ( !myInfoList.isEmpty() )
407     return;
408
409   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
410
411   QStringList modList;
412
413   // parse command line arguments
414   int nbArgs = qApp->argc();
415   char** CmdLine = qApp->argv();
416   QString CmdStr;
417   for ( int i = 0; i < nbArgs; i++ )
418   {
419     CmdStr.append(CmdLine[i]);
420     CmdStr.append(" ");
421   }
422   int startId = CmdStr.find("--modules (");
423   if ( startId != -1 ) { // application launch with --modules option
424     startId = CmdStr.find("(", startId);
425     int stopId = CmdStr.find(" )", startId);
426     QString ModStr = CmdStr.mid( startId+1, stopId - (startId+1) ).stripWhiteSpace();
427     int i = 0;
428     while ( i < ModStr.length() )
429     {
430       int nextId = ModStr.find( ":", i );
431       modList.append( ModStr.mid( i, nextId - i ).stripWhiteSpace() );
432       i = nextId + 1;
433     }
434   }
435   else {
436     QString modStr = resMgr->stringValue( "launch", "modules", QString::null );
437     modList = QStringList::split( ",", modStr );
438   }
439
440   for ( QStringList::const_iterator it = modList.begin(); it != modList.end(); ++it )
441   {
442     QString modName = (*it).stripWhiteSpace();
443     if ( modName.isEmpty() )
444       continue;
445
446     QString modTitle = resMgr->stringValue( *it, QString( "name" ), QString::null );
447     if ( modTitle.isEmpty() )
448       continue;
449
450     QString modLibrary = resMgr->stringValue( *it, QString( "library" ), QString::null ).stripWhiteSpace();
451     if ( !modLibrary.isEmpty() )
452     {
453       QString libExt;
454       modLibrary = SUIT_Tools::file( modLibrary.stripWhiteSpace() );
455       libExt = QString( "so" );
456       if ( SUIT_Tools::extension( modLibrary ).lower() == libExt )
457         modLibrary = modLibrary.mid( 0, modLibrary.length() - libExt.length() - 1 );
458       libExt = QString( "dll" );
459       if ( SUIT_Tools::extension( modLibrary ).lower() == libExt )
460         modLibrary = modLibrary.mid( 0, modLibrary.length() - libExt.length() - 1 );
461 #ifndef WIN32
462       if ( modLibrary.startsWith( "lib" ) )
463         modLibrary = modLibrary.mid( 3 );
464 #endif
465     }
466     else
467       modLibrary = modName;
468
469     ModuleInfo inf;
470     inf.name = modName;
471     inf.title = modTitle;
472     inf.internal = modLibrary;
473     myInfoList.append( inf );
474   }
475
476   if ( myInfoList.isEmpty() )
477     SUIT_MessageBox::error1( 0, tr( "Error" ), tr( "Can not load modules configuration file " ), tr( "Ok" ) );
478 }
479
480 /*!Add common items for popup menu ( if they are exist )
481  *\param type - type of popup menu
482  *\param thePopup - popup menu
483  *\param title - title of popup menu
484  */
485 void CAM_Application::contextMenuPopup( const QString& type, QPopupMenu* thePopup, QString& title )
486 {
487   // to do : add common items for popup menu ( if they are exist )
488   if ( activeModule() ) 
489     activeModule()->contextMenuPopup( type, thePopup, title );
490 }
491
492 /*!Create empty study.*/
493 void CAM_Application::createEmptyStudy()
494 {
495   SUIT_Study* study = activeStudy();
496
497   STD_Application::createEmptyStudy();
498 }