]> SALOME platform Git repositories - modules/gui.git/blob - src/Session/SALOME_Session_Server.cxx
Salome HOME
415c5328ac0b8d8feaa9c36d956308a7b2cdc1ac
[modules/gui.git] / src / Session / SALOME_Session_Server.cxx
1 //  SALOME Session : implementation of Session.idl
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SALOME_Session_Server.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SALOME
27 //  $Header$
28
29 #include <Container_init_python.hxx>
30 #include "Utils_ORB_INIT.hxx"
31 #include "Utils_SINGLETON.hxx"
32 #include "SALOME_NamingService.hxx"
33 #include "SALOMETraceCollector.hxx"
34
35 #include <iostream>
36 #include <unistd.h>
37
38 #include <qdir.h>
39 #include <qfile.h>
40 #include <qapplication.h>
41 #include <qwaitcondition.h>
42
43 #include "Utils_SALOME_Exception.hxx"
44 #include "Utils_CorbaException.hxx"
45 #include "SALOME_Event.hxx"
46
47 #include <SALOMEconfig.h>
48 #include CORBA_SERVER_HEADER(SALOME_Session)
49 #include CORBA_SERVER_HEADER(SALOMEDS)
50
51 #include <utilities.h>
52 #include "Session_Session_i.hxx"
53 #include "Session_ServerLauncher.hxx"
54
55 #include "SUIT_Session.h"
56 #include "SUIT_Application.h"
57 #include "SUIT_MessageBox.h"
58
59
60 #include "SUIT_ExceptionHandler.h"
61 using namespace std;
62
63 extern "C" int HandleSignals(QApplication *theQApplication);
64
65 /*! - read arguments, define list of server to launch with their arguments.
66  *  - wait for naming service
67  *  - create and run a thread for launch of all servers
68  *  
69  */
70
71 //! CORBA server for SALOME Session
72 /*!
73  *  SALOME_Session Server launches a SALOME session servant.
74  *  The servant registers to the Naming Service.
75  *  See SALOME_Session.idl for interface specification.
76  *
77  *  Main services offered by the servant are:
78  *   - launch GUI
79  *   - stop Session (must be idle)
80  *   - get session state
81  */
82
83 QString salomeVersion()
84 {
85   QString path( ::getenv( "GUI_ROOT_DIR" ) );
86   if ( !path.isEmpty() )
87     path += QDir::separator();
88   path += QString( "bin/salome/VERSION" );
89
90   QFile vf( path );
91   if ( !vf.open( IO_ReadOnly ) )
92     return QString::null;
93
94   QString line;
95   vf.readLine( line, 1024 );
96   vf.close();
97
98   if ( line.isEmpty() )
99     return QString::null;
100
101   while ( !line.isEmpty() && line.at( line.length() - 1 ) == QChar( '\n' ) )
102     line.remove( line.length() - 1, 1 );
103
104   QString ver;
105   int idx = line.findRev( ":" );
106   if ( idx != -1 )
107     ver = line.mid( idx + 1 ).stripWhiteSpace();
108
109   return ver;
110 }
111
112 PyObject *salome_shared_modules_module = NULL;
113
114 void MessageOutput( QtMsgType type, const char *msg )
115 {
116   switch ( type ) {
117   case QtDebugMsg:
118     MESSAGE( "Debug: " << msg );
119     break;
120   case QtWarningMsg:
121     MESSAGE( "Warning: " << msg );
122     break;
123   case QtFatalMsg:
124     MESSAGE( "Fatal: " << msg );
125     break;
126   }
127 }
128
129 class SALOME_Session : public SUIT_Session
130 {
131 public:
132   SALOME_Session() : SUIT_Session() {}
133   virtual ~SALOME_Session() {}
134
135 protected:
136   virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const
137   {
138     SUIT_ResourceMgr* resMgr = new SUIT_ResourceMgr( appName, QString( "%1Config" ) );
139     resMgr->setVersion( salomeVersion() );
140     resMgr->setCurrentFormat( "xml" );
141     resMgr->setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) );
142     return resMgr;
143   }
144 };
145
146 class SALOME_QApplication : public QApplication 
147 {
148 public:
149   SALOME_QApplication( int& argc, char** argv ) : QApplication( argc, argv ) 
150   {
151     myHandler = 0;
152   }
153   
154   virtual bool notify( QObject* receiver, QEvent* e ) 
155   {
156     return myHandler ? myHandler->handle( receiver, e ) :
157                        QApplication::notify( receiver, e );
158   }
159   SUIT_ExceptionHandler*  handler() const { return myHandler; }
160   void setHandler( SUIT_ExceptionHandler* h ) { myHandler = h; }
161
162 private:
163   SUIT_ExceptionHandler*  myHandler;
164 };
165
166 int main(int argc, char **argv)
167 {
168   qInstallMsgHandler( MessageOutput );
169
170   /*
171   char* _argv_0[512];
172   strcpy( (char*)_argv_0, (char*)argv[0] );
173   */
174
175   // QApplication should be create before all other operations
176   // When uses QApplication::libraryPaths() (example, QFile::encodeName())
177   // qApp used for detection of the executable dir path.
178   SALOME_QApplication _qappl( argc, argv );
179   ASSERT( QObject::connect(&_qappl, SIGNAL( lastWindowClosed() ), &_qappl, SLOT( quit() ) ) );
180   QString path( ::getenv( "GUI_ROOT_DIR" ) );
181   if ( !path.isEmpty() )
182     path += QDir::separator();
183   path += QString( "bin/salome" );
184   _qappl.addLibraryPath( path );
185   _qappl.setStyle( "salome" );
186
187   /*
188     Python initialisation : only once
189   */
190
191   int _argc = 1;
192   char* _argv[] = {""};
193   KERNEL_PYTHON::init_python(_argc,_argv);
194   PyEval_RestoreThread(KERNEL_PYTHON::_gtstate);
195   if(!KERNEL_PYTHON::salome_shared_modules_module) // import only once
196     {
197       KERNEL_PYTHON::salome_shared_modules_module =
198         PyImport_ImportModule("salome_shared_modules");
199     }
200   if(!KERNEL_PYTHON::salome_shared_modules_module)
201     {
202       INFOS("salome_shared_modules_module == NULL");
203       PyErr_Print();
204       PyErr_Clear();
205     }
206   PyEval_ReleaseThread(KERNEL_PYTHON::_gtstate);
207
208   int result = -1;
209
210   // 1. create ORB, get RootPOA object, NamingService, etc.
211   ORB_INIT &init = *SINGLETON_<ORB_INIT>::Instance() ;
212   ASSERT(SINGLETON_<ORB_INIT>::IsAlreadyExisting()) ;
213   int orbArgc = 1;
214   CORBA::ORB_var &orb = init( orbArgc , argv ) ;
215   SALOMETraceCollector *myThreadTrace = SALOMETraceCollector::instance(orb);
216
217   try
218     {
219       SALOME_Event::GetSessionThread();
220
221       CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
222       PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
223
224       PortableServer::POAManager_var pman = poa->the_POAManager() ;
225       pman->activate() ;
226       INFOS("pman->activate()");
227
228       SALOME_NamingService *_NS = new SALOME_NamingService(orb);
229
230       // CORBA Servant Launcher
231       QMutex _GUIMutex ;
232       QWaitCondition _ServerLaunch;
233       _GUIMutex.lock();     // to block Launch server thread until wait(mutex)
234
235       // 2. activate embedded CORBA servers: Registry, SALOMEDS, etc.
236       Session_ServerLauncher* myServerLauncher
237         = new Session_ServerLauncher(argc, argv, orb, poa, &_GUIMutex, &_ServerLaunch);
238       myServerLauncher->start();
239
240       // 3. GUI activation
241       // Allow multiple activation/deactivation of GUI
242       //while ( 1 ) {
243         MESSAGE("waiting wakeAll()");
244         _ServerLaunch.wait(&_GUIMutex); // to be reseased by Launch server thread when ready:
245         // atomic operation lock - unlock on mutex
246         // unlock mutex: serverThread runs, calls  _ServerLaunch->wakeAll()
247         // this thread wakes up, and lock mutex
248
249         INFOS("Session activated, Launch IAPP...");
250         /*
251         int qArgc = 1;
252         argv[0] = (char*)_argv_0;
253         SALOME_QApplication* _qappl = new SALOME_QApplication( qArgc, argv );
254
255         QStringList lst = _qappl->libraryPaths();
256         for ( QStringList::const_iterator it = lst.begin(); it != lst.end(); ++it )
257           printf( "=====> Library path: %s\n", (*it).latin1() );
258
259         _qappl->setStyle( "salome" );
260
261         ASSERT ( QObject::connect(_qappl, SIGNAL(lastWindowClosed()), _qappl, SLOT(quit()) ) );
262         */
263         
264         INFOS("creation QApplication");
265         _GUIMutex.unlock();
266
267         // 3.1 SUIT_Session creation    
268         SUIT_Session* aGUISession = new SALOME_Session();
269         INFOS("creation SUIT_Application");
270
271         SCRUTE(_NS);
272
273         // 3.3 run GUI loop
274         // T2.12 - catch exceptions thrown on attempts to modified a locked study
275         while (1) {
276           try 
277           {
278             MESSAGE("run(): starting the main event loop");
279
280             // 3.2 load SalomeApp dynamic library
281             SUIT_Application* aGUIApp = aGUISession->startApplication( "SalomeApp", 0, 0 );
282             if ( aGUIApp ) 
283             {
284               _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application
285                                                             // aGUISession contains SalomeApp_ExceptionHandler
286               result = _qappl.exec();
287             }
288             break;
289           }
290           catch (SALOME::SALOME_Exception& e)
291           {
292             INFOS("run(): SALOME_Exception was caught!");
293             QApplication::restoreOverrideCursor();
294             SUIT_MessageBox::warn1 ( 0,
295                                     QObject::tr("WRN_WARNING"), 
296                                     QObject::tr("SALOME_Exception was caught!"),
297                                     QObject::tr("BUT_OK") );
298             //QtCatchCorbaException(e);
299           }
300           catch(SALOMEDS::StudyBuilder::LockProtection&)
301           {
302             INFOS("run(): An attempt to modify a locked study has not been handled by QAD_Operation");
303             QApplication::restoreOverrideCursor();
304             SUIT_MessageBox::warn1 ( 0,
305                                     QObject::tr("WRN_WARNING"), 
306                                     QObject::tr("WRN_STUDY_LOCKED"),
307                                     QObject::tr("BUT_OK") );
308           }
309           catch (const CORBA::Exception& e)
310           {
311             CORBA::Any tmp;
312             tmp<<= e;
313             CORBA::TypeCode_var tc = tmp.type();
314             const char *p = tc->name();
315             INFOS ("run(): CORBA exception of the kind : "<<p<< " is caught");
316
317             QApplication::restoreOverrideCursor();
318             SUIT_MessageBox::error1 ( 0,
319                                      QObject::tr("ERR_ERROR"), 
320                                      QObject::tr("ERR_APP_EXCEPTION")
321                                      + QObject::tr(" CORBA exception ") + QObject::tr(p),
322                                      QObject::tr("BUT_OK") );
323           }
324           catch(exception& e)
325           {
326             INFOS("run(): An exception has been caught");
327             QApplication::restoreOverrideCursor();
328             SUIT_MessageBox::error1 ( 0,
329                                      QObject::tr("ERR_ERROR"), 
330                                      QObject::tr("ERR_APP_EXCEPTION")+ "\n" +QObject::tr(e.what()),
331                                      QObject::tr("BUT_OK") );
332           }
333           catch(...)
334           {
335             INFOS("run(): An exception has been caught");
336             QApplication::restoreOverrideCursor();
337             SUIT_MessageBox::error1 ( 0,
338                                      QObject::tr("ERR_ERROR"), 
339                                      QObject::tr("ERR_APP_EXCEPTION"),
340                                      QObject::tr("BUT_OK") );
341           }
342         }
343 //}  end of "outer" while( 1 )
344
345       // Prepare _GUIMutex for a new GUI activation
346       //_GUIMutex.lock(); 
347         //      }
348
349       //orb->shutdown(0);
350       //myServerLauncher->KillAll();
351     }
352   catch (SALOME_Exception& e)
353     {
354       INFOS("run(): SALOME::SALOME_Exception is caught: "<<e.what());
355     }
356   catch (CORBA::SystemException& e)
357     {
358       INFOS("Caught CORBA::SystemException.");
359     }
360   catch (CORBA::Exception& e)
361     {
362       INFOS("Caught CORBA::Exception.");
363       CORBA::Any tmp;
364       tmp<<= e;
365       CORBA::TypeCode_var tc = tmp.type();
366       const char *p = tc->name();
367       INFOS ("run(): CORBA exception of the kind : "<<p<< " is caught");
368     }
369   catch(exception& e)
370     {
371       INFOS("run(): An exception has been caught: " <<e.what());
372     }
373   catch (...)
374     {
375       INFOS("Caught unknown exception.");
376     }
377   delete myThreadTrace;
378   return result ;
379 }