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