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