Salome HOME
studyActivated() virtual method has been added
[modules/gui.git] / src / Session / InquireServersQThread.cxx
1 //  Copyright (C) 2003  CEA/DEN, EDF R&D
2 //
3 //
4 //
5 //  File   : InquireServersQThread.cxx
6 //  Author : Vasily RUSYAEV
7 //  Module : SALOME
8 //  $Header$
9
10 using namespace std;
11 #include "InquireServersQThread.h"
12
13 #include <qlabel.h>
14 #include <qpushbutton.h>
15 #include <qabstractlayout.h> 
16 #include <qlayout.h>
17 #include <qevent.h> 
18 #include <qfont.h> 
19 #include <qmessagebox.h> 
20 #include <qdir.h>
21 #include <qfileinfo.h>
22 #include <qstringlist.h>
23
24 //VRV: porting on Qt 3.0.5
25 #if QT_VERSION >= 0x030005
26 #include <qdesktopwidget.h> 
27 #endif
28 //VRV: porting on Qt 3.0.5
29
30 #include <qsize.h> 
31
32 #include <SALOMEconfig.h>
33
34 #include "Utils_ORB_INIT.hxx"
35 #include "Utils_SINGLETON.hxx"
36 #include "SALOME_NamingService.hxx"
37 #include "utilities.h"
38 #include "OpUtil.hxx"
39
40 #include CORBA_CLIENT_HEADER(SALOME_Session)
41 #include CORBA_CLIENT_HEADER(SALOME_Registry)
42 #include CORBA_CLIENT_HEADER(SALOMEDS)
43 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
44 #include CORBA_CLIENT_HEADER(SALOME_Component)
45
46 #define MARGIN_SIZE  5
47 #define SPACING_SIZE 3
48
49 InquireServersGUI::InquireServersGUI()
50      : QVBox(0, "SFA splash", Qt::WDestructiveClose | Qt::WStyle_Customize | Qt::WStyle_NoBorder | WType_TopLevel | WStyle_StaysOnTop | WX11BypassWM  )
51 {
52   //  myGUI = false;
53   myThread = new InquireServersQThread( this );
54
55   // 1. Polish the appearance
56   setMargin( MARGIN_SIZE );
57   setSpacing( SPACING_SIZE );
58   setFrameStyle( QFrame::Plain | QFrame::Box );
59   setLineWidth( 2 );
60   setMinimumSize( 200, 150 );
61
62   // 2. Splash image
63   QFrame* frm = new QFrame( this );
64   frm->setFrameStyle( QFrame::Box | QFrame::Raised );
65   QHBoxLayout* frmLayout = new QHBoxLayout( frm );
66   frmLayout->setMargin( MARGIN_SIZE );
67   mySplash = new QLabel( frm, "splash" );
68   frmLayout->addWidget( mySplash );
69
70   // setting pixmap
71   //QPixmap pix = SUIT_ResourceMgr( "SalomeApp" ).loadPixmap( "SalomeApp", tr( "ABOUT" ) );
72   //splash->setPixmap( pix  );
73   
74   // 3. Progress bar
75   myPrgBar = new QProgressBar( this, "QProgressBar" );
76   myPrgBar->setFixedWidth( 180 );
77   //Sets the total number of steps . 
78   myPrgBar->setTotalSteps ( myThread->getInquiredServers() );
79   myPrgBar->setProgress( 0 );
80
81   // 4. Info label
82   QWidget* aWgt1 = new QWidget( this );
83   QHBoxLayout* aHBoxLayout1 = new QHBoxLayout( aWgt1 );
84   myLabel = new QLabel( tr( "Loading:" ), aWgt1 );
85   myLabel->setFixedWidth( 180 );
86   myLabel->setAlignment( AlignLeft );
87   QFont theFont = myLabel->font();
88   theFont.setBold(true);
89   myLabel->setFont( theFont );
90   aHBoxLayout1->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) );
91   aHBoxLayout1->addWidget( myLabel );
92   aHBoxLayout1->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) );
93
94   // 5. <Cancel> button
95   QWidget* aWgt = new QWidget( this );
96   QHBoxLayout* aHBoxLayout = new QHBoxLayout( aWgt );
97   QPushButton* myCancelBtn = new QPushButton( tr( "Cancel" ), aWgt );
98   connect( myCancelBtn, SIGNAL( clicked() ), this, SLOT( ClickOnCancel() ) ) ;
99   aHBoxLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum )  );
100   aHBoxLayout->addWidget( myCancelBtn );
101   aHBoxLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum )  );
102
103   //Center widget
104 #if QT_VERSION >= 0x030005
105   QDesktopWidget *d = QApplication::desktop();
106 #else
107   QWidget *d = QApplication::desktop();
108 #endif
109 //VRV: porting on Qt 3.0.5
110
111   int w = d->width();         // returns desktop width
112   int h = d->height();        // returns desktop height
113   QSize mySize = sizeHint (); // returns widget size
114   int Xc = ( w - mySize.width() )  / 2;
115   int Yc = ( h - mySize.height() ) / 2;
116   move( Xc, Yc );
117
118   myThread->start();
119 }
120
121 void InquireServersGUI::setPixmap( QPixmap pix )
122 {
123   if ( !pix.isNull() ) {
124     mySplash->setPixmap( pix );
125     myPrgBar->setFixedWidth( mySplash->sizeHint().width() );
126     myLabel->setFixedWidth( mySplash->sizeHint().width() );
127   }
128 }
129
130 InquireServersGUI::~InquireServersGUI()
131 {
132   delete myThread;
133 }
134
135 void InquireServersGUI::getArgs( int& _argc, char *** _argv)
136 {
137   _argc = qApp->argc();
138   *_argv = qApp->argv();
139 }
140
141 //=================================================================================
142 // function : ClickOnCancel()
143 // purpose  : cancel loading of SALOME
144 //=================================================================================
145 void InquireServersGUI::ClickOnCancel()
146 {
147   //it's necessary to stop asking servers
148   myThread->stop();
149   //  myGUI = false;
150   //Also we should send QCloseEvent in order to close this widget (and remove from screen) 
151   //QThread::postEvent ( this, new QCloseEvent() );
152   qApp->exit(1);
153 }
154
155 void InquireServersGUI::closeEvent ( QCloseEvent * pe)
156 {
157   //default implementation calls e->accept(), which hides this widget. 
158   //See the QCloseEvent documentation for more details.
159   pe->accept();
160   QApplication::flushX ();
161   QApplication::syncX ();
162   qApp->exit();
163 }
164
165 void InquireServersGUI::customEvent( QCustomEvent* pe )
166 {
167   switch( pe->type() )
168     {
169         case InquireEvent::ProgressEvent:
170         {
171             int* value = ( int* )(( InquireEvent*)pe)->data();
172             myPrgBar->setProgress( *value );
173             break;
174         }
175         case InquireEvent::ProgressEventLabel:
176         {
177             QString* myString = ( QString* )(( InquireEvent*)pe)->data();
178             myLabel->setText( *myString );
179             break;
180         }
181         case InquireEvent::ProgressEventError:
182         {
183             QString* myErrDesc = ( QString* )(( InquireEvent*)pe)->data();
184             QString  appName = "SALOME Professional";
185             QString  error = "An internal error occurred.\n"+ *myErrDesc + "\n";
186             QMessageBox myMsgBox(appName,error,QMessageBox::Critical,QMessageBox::Ok,QMessageBox::NoButton,
187                                         QMessageBox::NoButton,0,"MY",TRUE,WStyle_DialogBorder|WStyle_StaysOnTop);
188             myMsgBox.exec();
189             ClickOnCancel();
190             break;
191         }
192       default:
193         {
194           ;
195         }
196     }
197 }
198
199 int InquireServersGUI::getExitStatus()
200 {
201   return myThread->getExitStatus();
202 }
203
204 InquireServersQThread::InquireServersQThread( InquireServersGUI* r )
205      : receiver(r),  myExitStatus(0)
206 {
207   char* cenv;
208
209   IsChecking = true;
210   myServersCount = 5;
211   //how many times we should repeat attempts to get response from all needed for launching SALOME servers
212   myRepeat = 30; // default value, user can change it by setting CSF_RepeatServerRequest env.variable
213   cenv = getenv( "CSF_RepeatServerRequest" );
214   if ( cenv ) {
215     int val = atoi( cenv );
216     if ( val > 0 )
217       myRepeat = val;
218   }
219   //define delay time between two attempts
220   myDelay = 1000000; // 1 second
221   QString str = "Loading: ";
222   myMessages[0] = "Checking naming service...";
223   myMessages[1] = str + "SALOME_Registry_Server" + "...";
224   myMessages[2] = str + "SALOMEDS_Server" + "...";
225   myMessages[3] = str + "SALOME_ModuleCatalog_Server" + "...";
226   myMessages[4] = str + "SALOME_Session_Server" + "...";
227   myMessages[5] = "";
228   myMessages[6] = "";
229   myMessages[7] = "";
230
231   r->getArgs( _argc, &_argv);
232
233   // NRI : Temporary solution for SuperVisionContainer
234   for ( int i=1; i<=(_argc-1); i++) {
235     if (strcmp(_argv[i],"CPP")==0) {
236       myMessages[5] = str + "SALOME_Container FactoryServer" + "...";
237       myServersCount++;
238     }
239     if (strcmp(_argv[i],"PY")==0) {
240       myMessages[6] = str + "SALOME_ContainerPy.py FactoryServerPy" + "...";
241       myServersCount++;
242     }
243     if (strcmp(_argv[i],"SUPERV")==0) {
244       myMessages[7] = str + "SALOME_Container SuperVisionContainer" + "...";
245       myServersCount++;
246     }
247 //    if (strcmp(_argv[i],"GUI")==0) {
248 //      r->withGUI(true);
249 //    }
250   }
251 }
252
253 void InquireServersQThread::run()
254 {
255   while (IsChecking)
256   {
257     if ( !receiver ) 
258     {
259       myExitStatus = 0;
260       return;
261     }
262     for (int i=1; i<=8; i++)
263       {
264         if ( myMessages[i-1].isEmpty() ) {
265           if (i==8) {
266             IsChecking = false;
267             //myExitStatus should be 0 because all servers exist and work
268             myExitStatus = 0;
269             //we should send QCloseEvent in order to close this widget (and remove from screen) 
270             QThread::postEvent ( receiver , new QCloseEvent() );
271           } else
272             continue;
273         }
274         QString *message = new QString(myMessages[i-1]);
275         QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEventLabel, message ) );
276         QThread::usleep(200000);
277         QString *errMsg;
278         bool result = AskServer(i,&errMsg);
279         if (result)
280           {
281             QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEvent, new int( i ) ) );
282             if (i==8)
283               {
284                 IsChecking = false;
285                 //myExitStatus should be 0 because all servers exist and work
286                 myExitStatus = 0;
287                 //we should send QCloseEvent in order to close this widget (and remove from screen) 
288                 QThread::postEvent ( receiver , new QCloseEvent() );
289               }
290           }
291         else
292           {
293             QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEventError, errMsg ) );
294             //myExitStatus should be 1 because we didn't receive response from server
295             myExitStatus = 1;
296             return;
297           }
298       }
299   }
300 }
301
302 bool InquireServersQThread::AskServer(int iteration, QString ** errMessage)
303 {
304   if ( iteration > myServersCount )
305     return true; // we did not launch server with number iteration, so checking for it is not neccessary
306
307   ASSERT(iteration<=myServersCount);
308
309   //will be set true if we get response from server
310   bool IsPassed = false;
311   QString errDescription;
312   switch (iteration)
313     {
314     case 1:
315       //First checking - existence of Naming Service
316       for (int i = myRepeat; i ; i--)
317         {
318           try
319             {
320               CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ;
321               CORBA::Object_var obj = orb->resolve_initial_references("NameService");
322               CosNaming::NamingContext_var _root_context = CosNaming::NamingContext::_narrow(obj);
323               if (CORBA::is_nil(_root_context))
324                 continue;
325               else
326                 IsPassed = true;
327               break;
328             }
329           catch(CORBA::COMM_FAILURE&)
330             {
331               MESSAGE("CORBA::COMM_FAILURE: unable to contact the naming service");
332             }
333           catch(...)
334             {
335               MESSAGE("Unknown Exception: unable to contact the naming service");
336             }
337           QThread::usleep(myDelay);
338         }
339       if (!IsPassed)
340         *errMessage = new QString("unable to contact the naming service");
341       break;
342     case 2:
343       //checking - existence of SALOME_Registry_Server
344     case 3:
345       //checking - existence of SALOMEDS_Server
346     case 4:
347       //checking - existence of SALOME_ModuleCatalog_Server
348     case 5:
349       //checking - existence of SALOME_Session_Server
350     case 6:
351       //checking - existence of SALOME_Container FactoryServer
352     case 7:
353       //checking - existence of SALOME_ContainerPy.py FactoryServerPy
354     case 8:
355       //checking - existence of SALOME_Container SuperVisionContainer
356
357
358       IsPassed = pingServer(iteration, errDescription);
359       if (!IsPassed)
360         *errMessage = new QString(errDescription);
361       break;
362     }
363 return IsPassed;
364 }
365
366 bool InquireServersQThread::pingServer(int iteration, QString& errMessage)
367 {
368   ASSERT(iteration<=myServersCount);
369   bool result = false;
370   QString errorDescr;
371   for (int i = myRepeat; i ; i--)
372     {
373       try
374         {
375           CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ;
376           SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance() ;
377           ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
378           NS.init_orb( orb ) ;
379           switch (iteration)
380             {
381             case 2:
382               {
383                 CORBA::Object_var obj = NS.Resolve("/Registry");
384                 Registry::Components_var registry = Registry::Components::_narrow(obj) ;
385                 if (!CORBA::is_nil(registry))
386                   {
387                     MESSAGE("/Registry is found");
388                     registry->ping();
389                     result = true;
390                     MESSAGE("Registry was activated");
391                     return result;
392                   }
393               }
394               break;
395             case 3:
396               {
397                 CORBA::Object_var obj = NS.Resolve("/myStudyManager");
398                 SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow(obj) ;
399                 if (!CORBA::is_nil(studyManager))
400
401
402
403
404
405                   {
406                     MESSAGE("/myStudyManager is found");
407                     studyManager->ping();
408                     result = true;
409                     MESSAGE("StudyManager was activated");
410                     return result;
411                   }
412               }
413               break;
414             case 4:
415               {
416                 CORBA::Object_var obj = NS.Resolve("/Kernel/ModulCatalog");
417                 SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
418                 if (!CORBA::is_nil(catalog))
419                   {
420                     MESSAGE("/Kernel/ModulCatalog is found");
421                     catalog->ping();
422                     result = true;
423                     MESSAGE("ModuleCatalog was activated");
424                     return result;
425                   }
426               }
427               break;
428             case 5:
429               {
430                 CORBA::Object_var obj = NS.Resolve("/Kernel/Session");
431                 SALOME::Session_var session = SALOME::Session::_narrow(obj) ;
432                 if (!CORBA::is_nil(session))
433                   {
434                     MESSAGE("/Kernel/Session is found");
435                     session->ping();
436                     result = true;
437                     MESSAGE("SALOME_Session was activated");
438                     return result;
439                   }
440               }
441               break;
442             case 6:
443               {
444                 string hostname = GetHostname();
445                 string containerName = "/Containers/";
446                 containerName += hostname;
447                 containerName += "/FactoryServer";
448
449                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
450                 Engines::Container_var FScontainer = Engines::Container::_narrow(obj) ;
451                 if (!CORBA::is_nil(FScontainer))
452                   {
453                     FScontainer->ping();
454                     result = true;
455                     MESSAGE("FactoryServer container was activated");
456                     return result;
457                   }
458               }
459               break;
460             case 7:
461               {
462                 string hostname = GetHostname();
463                 string containerName = "/Containers/";
464                 containerName += hostname;
465                 containerName += "/FactoryServerPy";
466                 
467                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
468                 Engines::Container_var FSPcontainer = Engines::Container::_narrow(obj) ;
469                 if (!CORBA::is_nil(FSPcontainer))
470                   {
471                     FSPcontainer->ping();
472                     result = true;
473                     MESSAGE("FactoryServerPy container was activated");
474                     return result;
475                   }
476               }
477               break;
478             case 8:
479               {
480                 string hostname = GetHostname();
481                 string containerName = "/Containers/";
482                 containerName += hostname;
483                 containerName += "/SuperVisionContainer";
484                 
485                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
486                 Engines::Container_var SVcontainer = Engines::Container::_narrow(obj) ;
487                 if (!CORBA::is_nil(SVcontainer))
488                   {
489                     SVcontainer->ping();
490
491                     result = true;
492                     MESSAGE("SuperVisionContainer container was activated");
493                     return result;
494                   }
495               }
496               break;
497             }
498          }
499       catch (ServiceUnreachable&)
500         {
501           MESSAGE("Caught exception: Naming Service Unreachable");
502           errorDescr = "Caught exception: Naming Service Unreachable";
503         }
504       catch (CORBA::COMM_FAILURE&)
505         {
506           MESSAGE("Caught CORBA::SystemException CommFailure.");
507           errorDescr = "Caught CORBA::SystemException CommFailure";
508         }
509       catch (CORBA::SystemException&)
510         {
511           MESSAGE("Caught CORBA::SystemException.");
512           errorDescr = "Caught CORBA::SystemException";
513         }
514       catch (CORBA::Exception&)
515         {
516           MESSAGE("Caught CORBA::Exception.");
517           errorDescr = "Caught CORBA::Exception";
518         }
519       catch (...)
520         {
521           MESSAGE("Caught unknown exception.");
522           errorDescr = "Caught unknown exception";
523         }
524       QThread::usleep(myDelay);
525     }
526   if (!result)
527     {
528       QString serverName;
529       switch (iteration)
530         {
531         case 2:
532           serverName = "SALOME_Registry_Server is not loaded. ";
533           break;
534         case 3:
535           serverName = "SALOMEDS_Server is not loaded. ";
536           break;
537         case 4:
538           serverName = "SALOME_ModuleCatalog_Server is not loaded. ";
539           break;
540         case 5:
541           serverName = "SALOME_Session_Server is not loaded. ";
542           break;
543         case 6:
544           serverName = "SALOME_Container FactoryServer is not loaded. ";
545           break;
546         case 7:
547           serverName = "SALOME_ContainerPy.py FactoryServerPy is not loaded. ";
548           break;
549         case 8:
550           serverName = "SALOME_Container SuperVisionContainer is not loaded. ";
551           break;
552         }
553       errMessage = serverName + errorDescr;
554     }
555   return result;
556 }