Salome HOME
Changed mechanizm of Session::activeApplication(): now it returns an internal field...
[modules/gui.git] / src / SUIT / SUIT_Session.cxx
1 #include "SUIT_Session.h"
2
3 #include "SUIT_Tools.h"
4 #include "SUIT_Desktop.h"
5 #include "SUIT_MessageBox.h"
6 #include "SUIT_ViewWindow.h"
7 #include "SUIT_ViewManager.h"
8 #include "SUIT_ExceptionHandler.h"
9
10 #include <qtextcodec.h>
11 #include <qmessagebox.h>
12 #include <qapplication.h>
13
14 #ifdef WIN32
15 #include <windows.h>
16 #else
17 #include <dlfcn.h>
18 #endif
19
20 SUIT_Session* SUIT_Session::mySession = 0;
21
22 SUIT_Session::SUIT_Session()
23 : QObject(),
24 myResMgr( 0 ),
25 myHandler( 0 ),
26 myActiveApp( 0 )
27 {
28   SUIT_ASSERT( !mySession )
29
30   mySession = this;
31
32   myAppList.setAutoDelete( true );
33 }
34
35 SUIT_Session::~SUIT_Session()
36 {
37   myAppList.clear();
38
39   mySession = 0;
40 }
41
42 SUIT_Session* SUIT_Session::session()
43 {
44   return mySession;
45 }
46
47 /*!
48   Starts new application using "createApplication" function of loaded DLL.
49 */
50
51 SUIT_Application* SUIT_Session::startApplication( const QString& name, int args, char** argv )
52 {
53   AppLib libHandle = 0;
54
55   QString appName = applicationName( name );
56   if ( myAppLibs.contains( appName ) )
57     libHandle = myAppLibs[appName];
58
59   if ( !libHandle )
60     libHandle = loadLibrary( name );
61
62   if ( !libHandle )
63   {
64     SUIT_MessageBox::warn1( 0, tr( "Error" ),
65                             tr( "Can not find function %1. %2").arg( APP_CREATE_NAME ).arg( lastError() ), tr( "Ok" ) );
66     return 0;
67   }
68
69   myAppLibs.insert( appName, libHandle );
70
71   APP_CREATE_FUNC crtInst = 0;
72
73 #ifdef WIN32
74   crtInst = (APP_CREATE_FUNC)::GetProcAddress( libHandle, APP_CREATE_NAME );
75 #else
76   crtInst = (APP_CREATE_FUNC)dlsym( libHandle, APP_CREATE_NAME );
77 #endif
78
79   if ( !crtInst )
80   {
81     SUIT_MessageBox::warn1( 0, tr( "Error" ),
82                             tr( "Can not find function %1. %2").arg( APP_CREATE_NAME ).arg( lastError() ), tr( "Ok" ) );
83     return 0;
84   }
85
86   // Prepare Resource Manager for the new application if it doesn't exist yet
87   if ( !myResMgr )
88   {
89     myResMgr = createResourceMgr( appName );
90     myResMgr->loadLanguage();
91   }
92
93   SUIT_Application* anApp = crtInst( args, argv );
94   if ( !anApp )
95   {
96     SUIT_MessageBox::warn1(0, tr( "Error" ), tr( "Can not find function %1. %2").arg( APP_CREATE_NAME ).arg( lastError() ), tr( "Ok" ) );
97     return 0;
98   }
99
100   anApp->setName( appName );
101
102   connect( anApp, SIGNAL( applicationClosed( SUIT_Application* ) ),
103            this, SLOT( onApplicationClosed( SUIT_Application* ) ) );
104   connect( anApp, SIGNAL( activated( SUIT_Application* ) ), 
105            this, SLOT( onApplicationActivated( SUIT_Application* ) ) );
106
107   myAppList.append( anApp );
108
109   if ( !myHandler )
110   {
111     APP_GET_HANDLER_FUNC crtHndlr = 0;
112 #ifdef WIN32
113     crtHndlr = (APP_GET_HANDLER_FUNC)::GetProcAddress( libHandle, APP_GET_HANDLER_NAME );
114 #else
115     crtHndlr = (APP_GET_HANDLER_FUNC)dlsym( libHandle, APP_GET_HANDLER_NAME );
116 #endif
117     if ( crtHndlr )
118       myHandler = crtHndlr();
119   }
120
121   anApp->start();
122
123   return anApp;
124 }
125
126 /*!
127   Gets the list of all applications
128 */
129 QPtrList<SUIT_Application> SUIT_Session::applications() const
130 {
131   QPtrList<SUIT_Application> apps;
132   apps.setAutoDelete( false );
133
134   for ( AppListIterator it( myAppList ); it.current(); ++it )
135     apps.append( it.current() );
136
137   return apps;
138 }
139
140 /*!
141   Returns the active application
142 */
143 SUIT_Application* SUIT_Session::activeApplication() const
144 {
145   /*
146   if ( myAppList.count() == 1 )
147     return myAppList.getFirst();
148
149   SUIT_Desktop* desktop = 0;
150   for ( AppListIterator it( myAppList ); it.current() && !desktop; ++it )
151   {
152     SUIT_Desktop* desk = it.current()->desktop();
153     if ( desk && desk->isActiveWindow() )
154       desktop = desk;
155   }
156
157   if ( !desktop )
158     return 0;
159
160   SUIT_ViewWindow* win = desktop->activeWindow();
161   if ( !win || !win->getViewManager() )
162     return 0;
163
164   SUIT_Study* study = win->getViewManager()->study();
165   if ( !study )
166     return 0;
167
168   return study->application();
169   */
170   return myActiveApp;
171 }
172
173 /*!
174   Returns the resource manager for the specified application name.
175 */
176 SUIT_ResourceMgr* SUIT_Session::resourceMgr() const
177 {
178   return myResMgr;
179 }
180
181 /*!
182   Removes the application from the list of launched applications.
183   If it is a last application the session will be closed.
184 */
185 void SUIT_Session::onApplicationClosed( SUIT_Application* theApp )
186 {
187   emit applicationClosed( theApp );
188
189   myAppList.remove( theApp );
190   if ( theApp == myActiveApp )
191     myActiveApp = 0;
192
193   if ( myAppList.isEmpty() )
194     qApp->quit();
195 }
196
197 /*!
198   Destroys session by closing all applications.
199 */
200 void SUIT_Session::closeSession()
201 {
202   while ( !myAppList.isEmpty() )
203   {
204     SUIT_Application* app = myAppList.getFirst();
205     if ( !app->isPossibleToClose() )
206       return;
207
208     app->closeApplication();
209   }
210 }
211
212 SUIT_ExceptionHandler* SUIT_Session::handler() const
213 {
214   return myHandler;
215 }
216
217 QString SUIT_Session::lastError() const
218 {
219   QString str;
220 #ifdef WNT
221   LPVOID lpMsgBuf;
222   ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
223                    FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
224   str = QString( (LPTSTR)lpMsgBuf );
225   LocalFree( lpMsgBuf );
226 #else
227   str = QString( dlerror() );
228 #endif
229   return str;
230 }
231
232 SUIT_Session::AppLib SUIT_Session::loadLibrary( const QString& name )
233 {
234   QString libFile = SUIT_Tools::library( name );
235
236   if ( libFile.isEmpty() )
237     return 0;
238
239   AppLib lib = 0;
240 #ifdef WIN32
241   lib = ::LoadLibrary( (char*)libFile.latin1() );
242 #else
243   lib = dlopen( (char*)libFile.latin1(), RTLD_LAZY );
244 #endif
245   return lib;
246 }
247
248 QString SUIT_Session::applicationName( const QString& str ) const
249 {
250 #ifdef WIN32
251   return SUIT_Tools::file( str, false );
252 #else
253   QString fileName = SUIT_Tools::file( str, false );
254   if ( fileName.startsWith( "lib" ) )
255     fileName = fileName.right( fileName.length() - 3 );
256   return fileName;
257 #endif
258 }
259
260 /*!
261   Virtual method, creates an instance of ResourceManager
262 */
263 SUIT_ResourceMgr* SUIT_Session::createResourceMgr( const QString& appName ) const
264 {
265   return new SUIT_ResourceMgr( appName );
266 }
267
268 /*!
269   Slot, called on activation of some application's desktop
270 */
271 void SUIT_Session::onApplicationActivated( SUIT_Application* app ) 
272 {
273   myActiveApp = app;
274 }