Salome HOME
Dialog SetupCurveDlg has been added
[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 extern "C" CAM_EXPORT SUIT_Application* createApplication()
23 {
24   return new CAM_Application();
25 }
26
27 CAM_Application::CAM_Application( const bool autoLoad )
28 : STD_Application(),
29 myModule( 0 ),
30 myAutoLoad( autoLoad )
31 {
32   readModuleList();
33 }
34
35 CAM_Application::~CAM_Application()
36 {
37 }
38
39 void CAM_Application::start()
40 {
41   if ( myAutoLoad )
42     loadModules();
43
44   STD_Application::start();
45 }
46
47 CAM_Module* CAM_Application::activeModule() const
48 {
49   return myModule;
50 }
51
52 CAM_Module* CAM_Application::module(  const QString& modName ) const
53 {
54   CAM_Module* mod = 0;
55   for ( ModuleListIterator it( myModules ); it.current() && !mod; ++it )
56     if ( it.current()->moduleName() == modName )
57       mod = it.current();
58   return mod;
59 }
60
61 CAM_Application::ModuleListIterator CAM_Application::modules() const
62 {
63   return ModuleListIterator( myModules );
64 }
65
66 void CAM_Application::modules( CAM_Application::ModuleList& out ) const
67 {
68   out.setAutoDelete( false );
69   out.clear();
70
71   for ( ModuleListIterator it( myModules ); it.current(); ++it )
72     out.append( it.current() );
73 }
74
75 void CAM_Application::modules( QStringList& lst, const bool loaded ) const
76 {
77   lst.clear();
78
79   if ( loaded )
80     for ( ModuleListIterator it( myModules ); it.current(); ++it )
81       lst.append( it.current()->moduleName() );
82   else
83     for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end(); ++it )
84       lst.append( (*it).title );
85 }
86
87 void CAM_Application::addModule( CAM_Module* mod )
88 {
89   if ( !mod || myModules.contains( mod ) )
90     return;
91
92   mod->initialize( this );
93
94   QMap<CAM_Module*, int> map;
95
96   ModuleList newList;
97   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end(); ++it )
98   {
99     if ( (*it).title == mod->moduleName() )
100       newList.append( mod );
101     else
102     {
103       CAM_Module* curMod = module( (*it).title );
104       if ( curMod )
105         newList.append( curMod );
106     }
107     if ( !newList.isEmpty() )
108       map.insert( newList.getLast(), 0 );
109   }
110
111   for ( ModuleListIterator itr( myModules ); itr.current(); ++itr )
112   {
113     if ( !map.contains( itr.current() ) )
114       newList.append( itr.current() );
115   }
116
117   if ( !map.contains( mod ) )
118       newList.append( mod );
119
120   myModules = newList;
121
122   moduleAdded( mod );
123 }
124
125 void CAM_Application::loadModules()
126 {
127   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end(); ++it )
128   {
129     CAM_Module* mod = loadModule( (*it).title );
130     if ( mod )
131       addModule( mod );
132     else
133       SUIT_MessageBox::error1( desktop(), tr( "Loading modules" ),
134                                tr( "Can not load module %1" ).arg( (*it).title ), tr( "Ok" ) );
135   }
136 }
137
138 CAM_Module* CAM_Application::loadModule( const QString& modName )
139 {
140   if ( myInfoList.isEmpty() )
141   {
142     qWarning( tr( "Modules configuration is not defined." ) );
143     return 0;
144   }
145
146   QString libName = moduleLibrary( modName );
147   if ( libName.isEmpty() )
148   {
149     qWarning( tr( "Information about module \"%1\" doesn't exist." ).arg( modName ) );
150     return 0;
151   }
152
153   QString err;
154   GET_MODULE_FUNC crtInst = 0;
155
156 #ifdef WIN32
157   HINSTANCE modLib = ::LoadLibrary( libName ); 
158   if ( !modLib )
159   {
160     LPVOID lpMsgBuf;
161     ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
162                      FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
163     err = QString( "Failed to load  %1. %2" ).arg( libName ).arg( (LPTSTR)lpMsgBuf );
164     ::LocalFree( lpMsgBuf );
165   }
166   else
167   {
168     crtInst = (GET_MODULE_FUNC)::GetProcAddress( modLib, GET_MODULE_NAME );
169     if ( !crtInst )
170     {
171       LPVOID lpMsgBuf;
172       ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
173                        FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
174     err = QString( "Failed to find  %1 function. %2" ).arg( GET_MODULE_NAME ).arg( (LPTSTR)lpMsgBuf );
175     ::LocalFree( lpMsgBuf );
176     }
177   }
178 #else
179   void* modLib = dlopen( (char*)libName.latin1(), RTLD_LAZY );
180   if ( !modLib )
181     err = QString( "Can not load library %1. %2" ).arg( libName ).arg( dlerror() );
182   else
183   {
184     crtInst = (GET_MODULE_FUNC)dlsym( modLib, GET_MODULE_NAME );
185     if ( !crtInst )
186       err = QString( "Failed to find function %1. %2" ).arg( GET_MODULE_NAME ).arg( dlerror() );
187   }
188 #endif
189
190   CAM_Module* module = crtInst ? crtInst() : 0;
191   if ( module )
192   {
193     module->setModuleName( modName );
194     module->setName( moduleName( modName ) );
195   }
196
197   if ( !err.isEmpty() )
198     SUIT_MessageBox::warn1( desktop(), tr( "Error" ), err, tr( "Ok" ) );
199
200   return module;
201 }
202
203 bool CAM_Application::activateModule( const QString& modName )
204 {
205   if ( !modName.isEmpty() && !activeStudy() )
206     return false;
207
208   bool res = false;
209   if ( !modName.isEmpty() )
210   {
211     CAM_Module* mod = module( modName );
212     if ( !mod && !moduleLibrary( modName ).isEmpty() )
213     {
214       mod = loadModule( modName );
215       addModule( mod );
216     }
217
218     if ( mod )
219       res = activateModule( mod );
220   }
221   else
222     res = activateModule( 0 );
223
224   return res;
225 }
226
227 bool CAM_Application::activateModule( CAM_Module* mod )
228 {
229   if ( mod && !activeStudy() )
230     return false;
231
232   if ( myModule == mod )
233     return true;
234
235   if ( myModule )
236   {
237     if ( !myModule->deactivateModule( activeStudy() ) )
238     {
239       // ....      
240     }    
241   }     
242   myModule = mod;
243
244   if ( myModule ){
245     // Connect the module to the active study
246     CAM_Study* camStudy = dynamic_cast<CAM_Study*>( activeStudy() );
247     if ( camStudy ){
248       CAM_DataModel* prev = 0;
249       for ( ModuleListIterator it( myModules ); it.current(); ++it ) {
250         CAM_DataModel* dm = it.current()->dataModel();
251         if ( it.current() == myModule && !camStudy->containsDataModel( dm ) ){
252           if ( prev )
253             camStudy->insertDataModel( it.current()->dataModel(), prev );
254           else
255             camStudy->insertDataModel( it.current()->dataModel(), 0 );
256         }
257         prev = dm;
258       }
259     }
260     if ( !myModule->activateModule( activeStudy() ) )
261     {
262       myModule->setMenuShown( false );
263       myModule->setToolShown( false );
264       SUIT_MessageBox::error1( desktop(), tr( "ERROR_TLT" ), tr( "ERROR_ACTIVATE_MODULE_MSG" ).arg( myModule->moduleName() ), tr( "BUT_OK" ) );
265       myModule = 0;
266       return false;
267     }
268   }
269
270   updateCommandsStatus();
271
272   return true;
273 }
274
275 SUIT_Study* CAM_Application::createNewStudy() 
276
277   return new CAM_Study( this );
278 }
279
280 void CAM_Application::updateCommandsStatus()
281 {
282   STD_Application::updateCommandsStatus();
283
284   if ( activeModule() )
285     activeModule()->updateCommandsStatus();
286 }
287
288 void CAM_Application::beforeCloseDoc( SUIT_Study* theDoc )
289 {
290   for ( ModuleListIterator it( myModules ); it.current(); ++it )
291     it.current()->studyClosed( theDoc );
292 }
293
294 void CAM_Application::setActiveStudy( SUIT_Study* study )
295 {
296   STD_Application::setActiveStudy( study );
297 }
298
299 void CAM_Application::moduleAdded( CAM_Module* mod )
300 {
301 //  CAM_Study* study = dynamic_cast<CAM_Study*>( activeStudy() );
302 //  if ( !study )
303 //    return;
304
305 //  study->insertDataModel( mod->dataModel() );
306 }
307
308 QString CAM_Application::moduleName( const QString& title ) const
309 {
310   QString res;
311   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
312   {
313     if ( (*it).title == title )
314       res = (*it).name;
315   }
316   return res;
317 }
318
319 QString CAM_Application::moduleTitle( const QString& name ) const
320 {
321   QString res;
322   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
323   {
324     if ( (*it).name == name )
325       res = (*it).title;
326   }
327   return res;
328 }
329
330 QString CAM_Application::moduleLibrary( const QString& title, const bool full ) const
331 {
332   QString res;
333   for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
334   {
335     if ( (*it).title == title )
336       res = (*it).internal;
337   }
338   if ( !res.isEmpty() && full )
339     res = SUIT_Tools::library( res );
340   return res;
341 }
342
343 void CAM_Application::readModuleList()
344 {
345   if ( !myInfoList.isEmpty() )
346     return;
347
348   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
349
350   QString modStr = resMgr->stringValue( "launch", "modules", QString::null );
351   QStringList modList = QStringList::split( ",", modStr );
352
353   for ( QStringList::const_iterator it = modList.begin(); it != modList.end(); ++it )
354   {
355     QString modName = (*it).stripWhiteSpace();
356     if ( modName.isEmpty() )
357       continue;
358
359     QString modTitle = resMgr->stringValue( *it, QString( "name" ), QString::null );
360     if ( modTitle.isEmpty() )
361       continue;
362
363     QString modLibrary = resMgr->stringValue( *it, QString( "library" ), QString::null ).stripWhiteSpace();
364     if ( !modLibrary.isEmpty() )
365     {
366       QString libExt;
367       modLibrary = SUIT_Tools::file( modLibrary.stripWhiteSpace() );
368       libExt = QString( "so" );
369       if ( SUIT_Tools::extension( modLibrary ).lower() == libExt )
370         modLibrary = modLibrary.mid( 0, modLibrary.length() - libExt.length() - 1 );
371       libExt = QString( "dll" );
372       if ( SUIT_Tools::extension( modLibrary ).lower() == libExt )
373         modLibrary = modLibrary.mid( 0, modLibrary.length() - libExt.length() - 1 );
374 #ifndef WIN32
375       if ( modLibrary.startsWith( "lib" ) )
376         modLibrary = modLibrary.mid( 3 );
377 #endif
378     }
379     else
380       modLibrary = modName;
381
382     ModuleInfo inf;
383     inf.name = modName;
384     inf.title = modTitle;
385     inf.internal = modLibrary;
386     myInfoList.append( inf );
387   }
388
389   if ( myInfoList.isEmpty() )
390     SUIT_MessageBox::error1( 0, tr( "Error" ), tr( "Can not load modules configuration file " ), tr( "Ok" ) );
391 }
392
393 void CAM_Application::contextMenuPopup( const QString& type, QPopupMenu* thePopup, QString& title )
394 {
395   // to do : add common items for popup menu ( if they are exist )
396   if ( activeModule() ) 
397     activeModule()->contextMenuPopup( type, thePopup, title );
398 }