]> SALOME platform Git repositories - modules/gui.git/blob - src/SUIT/SUIT_Session.cxx
Salome HOME
8848a2c868d24a35207f8ea42bc3413163d38442
[modules/gui.git] / src / SUIT / SUIT_Session.cxx
1 //  Copyright (C) 2007-2008  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.
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 #include "SUIT_Session.h"
23
24 #include "SUIT_Study.h"
25 #include "SUIT_Tools.h"
26 #include "SUIT_MessageBox.h"
27 #include "SUIT_ExceptionHandler.h"
28 #include "SUIT_ResourceMgr.h"
29
30 #include <QApplication>
31
32 #ifdef WIN32
33 #include <windows.h>
34 #else
35 #include <dlfcn.h>
36 #endif
37
38 SUIT_Session* SUIT_Session::mySession = 0;
39
40 /*! Constructor.*/
41
42 SUIT_Session::SUIT_Session()
43 : QObject(),
44   myResMgr( 0 ),
45   myActiveApp( 0 ),
46   myHandler( 0 ),
47   myExitStatus( NORMAL ),
48   myExitFlags ( 0 )
49 {
50   SUIT_ASSERT( !mySession )
51
52   mySession = this;
53 }
54
55 /*!destructor. Clear applications list and set mySession to zero.*/
56 SUIT_Session::~SUIT_Session()
57 {
58   for ( AppList::iterator it = myAppList.begin(); it != myAppList.end(); ++it )
59     delete *it;
60
61   myAppList.clear();
62
63   if ( myResMgr )
64   {
65     delete myResMgr;
66     myResMgr = 0;
67   }
68   mySession = 0;
69 }
70
71 /*! \retval return mySession */
72 SUIT_Session* SUIT_Session::session()
73 {
74   return mySession;
75 }
76
77 /*!
78   Starts new application using "createApplication" function of loaded DLL.
79 */
80
81 SUIT_Application* SUIT_Session::startApplication( const QString& name, int /*args*/, char** /*argv*/ )
82 {
83   AppLib libHandle = 0;
84
85   QString appName = applicationName( name );
86   if ( myAppLibs.contains( appName ) )
87     libHandle = myAppLibs[appName];
88
89   QString lib;
90   if ( !libHandle )
91     libHandle = loadLibrary( name, lib );
92
93   if ( !libHandle )
94   {
95     SUIT_MessageBox::warning( 0, tr( "Error" ),
96                               tr( "Can not load application library \"%1\": %2").arg( lib ).arg( lastError() ) );
97     return 0;
98   }
99
100   if ( !myAppLibs.contains( appName ) || !myAppLibs[appName] ) // jfa 22.06.2005
101     myAppLibs.insert( appName, libHandle );
102
103   APP_CREATE_FUNC crtInst = 0;
104
105 #ifdef WIN32
106   crtInst = (APP_CREATE_FUNC)::GetProcAddress( (HINSTANCE)libHandle, APP_CREATE_NAME );
107 #else
108   crtInst = (APP_CREATE_FUNC)dlsym( libHandle, APP_CREATE_NAME );
109 #endif
110
111   if ( !crtInst )
112   {
113     SUIT_MessageBox::warning( 0, tr( "Error" ),
114                               tr( "Can not find function \"%1\": %2" ).arg( APP_CREATE_NAME ).arg( lastError() ) );
115     return 0;
116   }
117
118   // Prepare Resource Manager for the new application if it doesn't exist yet
119   if ( !myResMgr )
120   {
121     myResMgr = createResourceMgr( appName );
122     myResMgr->loadLanguage();
123   }
124
125   //jfa 22.06.2005:SUIT_Application* anApp = crtInst( args, argv );
126   SUIT_Application* anApp = crtInst();
127   if ( !anApp )
128   {
129     SUIT_MessageBox::warning( 0, tr( "Error" ), tr( "Can not create application \"%1\": %2").arg( appName ).arg( lastError() ) );
130     return 0;
131   }
132
133   anApp->setObjectName( appName );
134
135   insertApplication( anApp );
136
137   if ( !myHandler )
138   {
139     APP_GET_HANDLER_FUNC crtHndlr = 0;
140 #ifdef WIN32
141     crtHndlr = (APP_GET_HANDLER_FUNC)::GetProcAddress( (HINSTANCE)libHandle, APP_GET_HANDLER_NAME );
142 #else
143     crtHndlr = (APP_GET_HANDLER_FUNC)dlsym( libHandle, APP_GET_HANDLER_NAME );
144 #endif
145     if ( crtHndlr )
146       myHandler = crtHndlr();
147   }
148
149   anApp->start();
150
151   // Application can be closed during starting (not started).
152   if ( !myAppList.contains( anApp ) )
153     anApp = 0;
154
155   return anApp;
156 }
157
158 /*!
159   Gets the list of all applications
160 */
161 QList<SUIT_Application*> SUIT_Session::applications() const
162 {
163   return myAppList;
164 }
165
166 void SUIT_Session::insertApplication( SUIT_Application* app )
167 {
168   if ( !app || myAppList.contains( app ) )
169     return;
170
171   myAppList.append( app );
172
173   connect( app, SIGNAL( applicationClosed( SUIT_Application* ) ),
174            this, SLOT( onApplicationClosed( SUIT_Application* ) ) );
175   connect( app, SIGNAL( activated( SUIT_Application* ) ), 
176                  this, SLOT( onApplicationActivated( SUIT_Application* ) ) );
177 }
178
179 /*!
180   Returns the active application
181 */
182 SUIT_Application* SUIT_Session::activeApplication() const
183 {
184   /*
185   if ( myAppList.count() == 1 )
186     return myAppList.getFirst();
187
188   SUIT_Desktop* desktop = 0;
189   for ( AppListIterator it( myAppList ); it.current() && !desktop; ++it )
190   {
191     SUIT_Desktop* desk = it.current()->desktop();
192     if ( desk && desk->isActiveWindow() )
193       desktop = desk;
194   }
195
196   if ( !desktop )
197     return 0;
198
199   SUIT_ViewWindow* win = desktop->activeWindow();
200   if ( !win || !win->getViewManager() )
201     return 0;
202
203   SUIT_Study* study = win->getViewManager()->study();
204   if ( !study )
205     return 0;
206
207   return study->application();
208   */
209   return myActiveApp;
210 }
211
212 /*!
213   Returns the resource manager for the specified application name.
214 */
215 SUIT_ResourceMgr* SUIT_Session::resourceMgr() const
216 {
217   return myResMgr;
218 }
219
220 /*!
221   Removes the application from the list of launched applications.
222   If it is a last application the session will be closed.
223 */
224 void SUIT_Session::onApplicationClosed( SUIT_Application* theApp )
225 {
226   emit applicationClosed( theApp );
227
228   myAppList.removeAll( theApp );
229   delete theApp;
230
231   if ( theApp == myActiveApp )
232     myActiveApp = 0;
233
234   if ( myAppList.isEmpty() )
235   {
236     //printf( "Calling QApplication::exit() with exit code = %d\n", myExitStatus );
237     QApplication::instance()->exit( myExitStatus );
238   }
239 }
240
241 /*!
242   Destroys session by closing all applications.
243 */
244 void SUIT_Session::closeSession( int mode, int flags )
245 {
246   AppList apps = myAppList;
247   for ( AppList::const_iterator it = apps.begin(); it != apps.end(); ++it )
248   {
249     SUIT_Application* app = *it;
250     bool closePermanently;
251     if ( mode == ASK && !app->isPossibleToClose( closePermanently ) )
252       return;
253     else if ( mode == SAVE )
254     {
255       SUIT_Study* study = app->activeStudy();
256       if ( study->isModified() && study->isSaved() )
257               study->saveDocument();
258     }
259     else if ( mode == DONT_SAVE )
260     {
261       myExitStatus = FORCED;
262     }
263
264     app->closeApplication();
265   }
266
267   myExitFlags = flags;
268 }
269
270 /*!
271   Get session exit flags.
272
273   By default, exit flags are set to 0. You can use pass any flags to the
274   closeSession() method if you need to process them later on application
275   quiting.
276
277   \return exit flags
278 */
279 int SUIT_Session::exitFlags() const
280 {
281   return myExitFlags;
282 }
283
284 /*! \retval return myHandler*/
285 SUIT_ExceptionHandler* SUIT_Session::handler() const
286 {
287   return myHandler;
288 }
289
290 /*! \retval return last error string.*/
291 QString SUIT_Session::lastError() const
292 {
293   QString str;
294 #ifdef WIN32
295   LPVOID lpMsgBuf;
296   ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
297                    FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
298   LPTSTR msg = (LPTSTR)lpMsgBuf;
299   str = QString( SUIT_Tools::toQString( msg ) );
300   LocalFree( lpMsgBuf );
301 #else
302   str = QString( dlerror() );
303 #endif
304   return str;
305 }
306
307 /*! Load library to session.
308  * \retval Loaded library.
309  */
310 SUIT_Session::AppLib SUIT_Session::loadLibrary( const QString& name, QString& libName )
311 {
312   QString libFile = SUIT_Tools::library( name );
313
314   libName = libFile;
315   if ( libFile.isEmpty() )
316     return 0;
317
318   AppLib lib = 0;
319   QByteArray bid = libFile.toLatin1();
320 #ifdef WIN32
321 #ifdef UNICODE
322   LPTSTR str = (LPTSTR)libFile.utf16();
323 #else
324   LPTSTR str = (LPTSTR)(const char*)bid;
325 #endif
326   lib = ::LoadLibrary( str );
327 #else
328   lib = dlopen( (const char*)libFile.toLatin1(), RTLD_LAZY | RTLD_GLOBAL  );
329 #endif
330   return lib;
331 }
332
333 /*! \retval Return file name by application name.*/
334 QString SUIT_Session::applicationName( const QString& str ) const
335 {
336 #ifdef WIN32
337   return SUIT_Tools::file( str, false );
338 #else
339   QString fileName = SUIT_Tools::file( str, false );
340   if ( fileName.startsWith( "lib" ) )
341     fileName = fileName.right( fileName.length() - 3 );
342   return fileName;
343 #endif
344 }
345
346 /*!
347   Virtual method, creates an instance of ResourceManager
348 */
349 SUIT_ResourceMgr* SUIT_Session::createResourceMgr( const QString& appName ) const
350 {
351   return new SUIT_ResourceMgr( applicationName( appName ) );
352 }
353
354 /*!
355   Slot, called on activation of some application's desktop
356 */
357 void SUIT_Session::onApplicationActivated( SUIT_Application* app ) 
358 {
359   myActiveApp = app;
360 }