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