1 // SALOME Session : implementation of Session.idl
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : SALOME_Session_Server.cxx
25 // Author : Paul RASCLE, EDF
28 #include <Container_init_python.hxx>
29 #include "Utils_ORB_INIT.hxx"
30 #include "Utils_SINGLETON.hxx"
31 #include "SALOME_NamingService.hxx"
32 #include "SALOMETraceCollector.hxx"
34 #include "InquireServersQThread.h" // splash
43 #include <qapplication.h>
44 #include <qwaitcondition.h>
46 #include "Utils_SALOME_Exception.hxx"
47 #include "Utils_CorbaException.hxx"
48 #include "SALOME_Event.hxx"
50 #include <SALOMEconfig.h>
51 #include CORBA_SERVER_HEADER(SALOME_Session)
52 #include CORBA_SERVER_HEADER(SALOMEDS)
54 #include <utilities.h>
55 #include "Session_Session_i.hxx"
56 #include "Session_ServerLauncher.hxx"
58 #include "SUIT_Tools.h"
59 #include "SUIT_Session.h"
60 #include "SUIT_Application.h"
61 #include "SUIT_MessageBox.h"
62 #include "SUIT_ResourceMgr.h"
64 #include "SUIT_ExceptionHandler.h"
66 /*! - read arguments, define list of server to launch with their arguments.
67 * - wait for naming service
68 * - create and run a thread for launch of all servers
72 //! CORBA server for SALOME Session
74 * SALOME_Session Server launches a SALOME session servant.
75 * The servant registers to the Naming Service.
76 * See SALOME_Session.idl for interface specification.
78 * Main services offered by the servant are:
80 * - stop Session ( must be idle )
84 PyObject* salome_shared_modules_module = 0;
86 void MessageOutput( QtMsgType type, const char* msg )
91 MESSAGE( "Debug: " << msg );
94 MESSAGE( "Warning: " << msg );
97 MESSAGE( "Fatal: " << msg );
103 static const char* pixmap_not_found_xpm[] = {
125 QString salomeVersion()
127 QString path( ::getenv( "GUI_ROOT_DIR" ) );
128 if ( !path.isEmpty() )
129 path += QDir::separator();
130 path += QString( "bin/salome/VERSION" );
133 if ( !vf.open( IO_ReadOnly ) )
134 return QString::null;
137 vf.readLine( line, 1024 );
140 if ( line.isEmpty() )
141 return QString::null;
143 while ( !line.isEmpty() && line.at( line.length() - 1 ) == QChar( '\n' ) )
144 line.remove( line.length() - 1, 1 );
147 int idx = line.findRev( ":" );
149 ver = line.mid( idx + 1 ).stripWhiteSpace();
154 class SALOME_ResourceMgr : public SUIT_ResourceMgr
157 SALOME_ResourceMgr( const QString& app, const QString& resVarTemplate ) : SUIT_ResourceMgr( app, resVarTemplate )
159 setCurrentFormat( "xml" );
160 setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) );
161 setDefaultPixmap( QPixmap( pixmap_not_found_xpm ) );
163 static void initResourceMgr()
165 if ( myExtAppName.isNull() || myExtAppVersion.isNull() ) {
166 SALOME_ResourceMgr resMgr( "SalomeApp", QString( "%1Config" ) );
167 resMgr.loadLanguage( "SalomeApp", "en" );
169 myExtAppName = QObject::tr( "APP_NAME" ).stripWhiteSpace();
170 if ( myExtAppName == "APP_NAME" || myExtAppName.lower() == "salome" )
171 myExtAppName = "SalomeApp";
172 myExtAppVersion = QObject::tr( "APP_VERSION" );
173 if ( myExtAppVersion == "APP_VERSION" ) {
174 if ( myExtAppName != "SalomeApp" )
175 myExtAppVersion = "";
176 else myExtAppVersion = salomeVersion();
180 QString version() const { return myExtAppVersion; }
183 QString userFileName( const QString& appName ) const
185 if ( version().isNull() ) return "";
186 return SUIT_ResourceMgr::userFileName( myExtAppName );
190 static QString myExtAppName;
191 static QString myExtAppVersion;
194 QString SALOME_ResourceMgr::myExtAppName = QString::null;
195 QString SALOME_ResourceMgr::myExtAppVersion = QString::null;
197 class SALOME_Session : public SUIT_Session
200 SALOME_Session() : SUIT_Session() {}
201 virtual ~SALOME_Session() {}
204 virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const
206 SALOME_ResourceMgr::initResourceMgr();
207 SALOME_ResourceMgr* resMgr = new SALOME_ResourceMgr( appName, QString( "%1Config" ) );
212 class SALOME_QApplication : public QApplication
215 SALOME_QApplication( int& argc, char** argv ) : QApplication( argc, argv ), myHandler ( 0 ) {}
217 virtual bool notify( QObject* receiver, QEvent* e )
219 return myHandler ? myHandler->handle( receiver, e ) :
220 QApplication::notify( receiver, e );
222 SUIT_ExceptionHandler* handler() const { return myHandler; }
223 void setHandler( SUIT_ExceptionHandler* h ) { myHandler = h; }
226 SUIT_ExceptionHandler* myHandler;
229 // class which calls SALOME::Session::GetInterface() from another thread
230 // to avoid mutual lock ( if called from the same thread as main()
231 class GetInterfaceThread : public QThread
234 GetInterfaceThread( SALOME::Session_var s ) : session ( s ) {}
238 if ( !CORBA::is_nil( session ) )
239 session->GetInterface();
241 printf( "\nFATAL ERROR: SALOME::Session object is nil! Can not display GUI\n\n" );
244 SALOME::Session_var session;
247 // returns true if 'str' is found in argv
248 bool isFound( const char* str, int argc, char** argv )
250 for ( int i = 1; i <= ( argc-1 ); i++ )
251 if ( !strcmp( argv[i], str ) )
256 // ---------------------------- MAIN -----------------------
257 int main( int argc, char **argv )
259 qInstallMsgHandler( MessageOutput );
261 // QApplication should be create before all other operations
262 // When uses QApplication::libraryPaths() ( example, QFile::encodeName() )
263 // qApp used for detection of the executable dir path.
264 SALOME_QApplication _qappl( argc, argv );
265 ASSERT( QObject::connect( &_qappl, SIGNAL( lastWindowClosed() ), &_qappl, SLOT( quit() ) ) );
267 QString path = QDir::convertSeparators( SUIT_Tools::addSlash( QString( ::getenv( "GUI_ROOT_DIR" ) ) ) + QString( "bin/salome" ) );
268 _qappl.addLibraryPath( path );
270 _qappl.setStyle( "salome" );
275 PortableServer::POA_var poa;
277 SUIT_Session* aGUISession = 0;
278 SALOME_NamingService* _NS = 0;
279 GetInterfaceThread* guiThread = 0;
280 Session_ServerLauncher* myServerLauncher = 0;
284 // Python initialisation : only once
287 char* _argv[] = {""};
288 KERNEL_PYTHON::init_python( _argc,_argv );
289 PyEval_RestoreThread( KERNEL_PYTHON::_gtstate );
290 if ( !KERNEL_PYTHON::salome_shared_modules_module ) // import only once
291 KERNEL_PYTHON::salome_shared_modules_module = PyImport_ImportModule( "salome_shared_modules" );
292 if ( !KERNEL_PYTHON::salome_shared_modules_module )
294 INFOS( "salome_shared_modules_module == NULL" );
297 PyEval_ReleaseThread( KERNEL_PYTHON::_gtstate );
299 // Create ORB, get RootPOA object, NamingService, etc.
300 ORB_INIT &init = *SINGLETON_<ORB_INIT>::Instance();
301 ASSERT( SINGLETON_<ORB_INIT>::IsAlreadyExisting() );
303 orb = init( orbArgc, argv );
305 // Install SALOME thread event handler
306 SALOME_Event::GetSessionThread();
308 CORBA::Object_var obj = orb->resolve_initial_references( "RootPOA" );
309 poa = PortableServer::POA::_narrow( obj );
311 PortableServer::POAManager_var pman = poa->the_POAManager();
313 INFOS( "pman->activate()" );
315 _NS = new SALOME_NamingService( orb );
319 catch ( SALOME_Exception& e ) {
320 INFOS( "run(): SALOME::SALOME_Exception is caught: "<<e.what() );
322 catch ( CORBA::SystemException& e ) {
323 INFOS( "Caught CORBA::SystemException." );
325 catch ( CORBA::Exception& e ) {
326 INFOS( "Caught CORBA::Exception." );
329 CORBA::TypeCode_var tc = tmp.type();
330 const char *p = tc->name();
331 INFOS ( "run(): CORBA exception of the kind : "<<p<< " is caught" );
333 catch ( exception& e ) {
334 INFOS( "run(): An exception has been caught: " <<e.what() );
337 INFOS( "Caught unknown exception." );
340 // CORBA Servant Launcher
342 QWaitCondition _ServerLaunch, _SessionStarted;
346 _GUIMutex.lock(); // to block Launch server thread until wait( mutex )
348 // Activate embedded CORBA servers: Registry, SALOMEDS, etc.
349 myServerLauncher = new Session_ServerLauncher( argc, argv, orb, poa, &_GUIMutex, &_ServerLaunch, &_SessionStarted );
350 myServerLauncher->start();
352 _ServerLaunch.wait( &_GUIMutex ); // to be reseased by Launch server thread when ready:
354 // show splash screen if "SPLASH" parameter was passed ( default )
355 if ( isFound( "SPLASH", argc, argv ) )
357 // create temporary resource manager just to load splash icon
358 SUIT_ResourceMgr resMgr( "SalomeApp", QString( "%1Config" ) );
359 resMgr.setCurrentFormat( "xml" );
360 resMgr.loadLanguage( "LightApp", "en" );
362 // create splash object: widget ( splash with progress bar ) and "pinging" thread
363 InquireServersGUI splash;
364 splash.setPixmap( resMgr.loadPixmap( "LightApp", QObject::tr( "ABOUT_SPLASH" ) ) );
365 SUIT_Tools::centerWidget( &splash, _qappl.desktop() );
367 _qappl.setMainWidget( &splash );
368 QObject::connect( &_qappl, SIGNAL( lastWindowClosed() ), &_qappl, SLOT( quit() ) );
369 splash.show(); // display splash with running progress bar
370 _qappl.exec(); // wait untill splash closes ( progress runs till end or Cancel is pressed )
372 result = splash.getExitStatus(); // 1 is error
375 _SessionStarted.wait();
378 // call Session::GetInterface() if "GUI" parameter was passed ( default )
379 if ( !result && isFound( "GUI", argc, argv ) )
381 CORBA::Object_var obj = _NS->Resolve( "/Kernel/Session" );
382 SALOME::Session_var session = SALOME::Session::_narrow( obj ) ;
383 ASSERT ( ! CORBA::is_nil( session ) );
385 INFOS( "Session activated, Launch IAPP..." );
386 guiThread = new GetInterfaceThread( session );
394 // Allow multiple activation/deactivation of GUI
397 MESSAGE( "waiting wakeAll()" );
398 _ServerLaunch.wait( &_GUIMutex ); // to be reseased by Launch server thread when ready:
399 // atomic operation lock - unlock on mutex
400 // unlock mutex: serverThread runs, calls _ServerLaunch->wakeAll()
401 // this thread wakes up, and lock mutex
405 // SUIT_Session creation
406 aGUISession = new SALOME_Session();
408 // Load SalomeApp dynamic library
409 INFOS( "creation SUIT_Application" );
410 SUIT_Application* aGUIApp = aGUISession->startApplication( "SalomeApp", 0, 0 );
413 if ( !isFound( "noexcepthandler", argc, argv ) )
414 _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application
415 // aGUISession contains SalomeApp_ExceptionHandler
417 MESSAGE( "run(): starting the main event loop" );
418 result = _qappl.exec();
420 if ( result == SUIT_Session::FROM_GUI ) // desktop is closed by user from GUI
427 // Prepare _GUIMutex for a new GUI activation
432 if ( myServerLauncher )
433 myServerLauncher->KillAll(); // kill embedded servers
437 delete myServerLauncher;
440 LocalTraceBufferPool *bp1 = LocalTraceBufferPool::instance();
441 LocalTraceBufferPool::deleteInstance(bp1);