Salome HOME
ptv, do not send mouse release event just after mouse double click
[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   {
143     mySplash->setPixmap( pix );
144     int w = mySplash->sizeHint().width() + MARGIN_SIZE*2;
145     myPrgBar->setFixedWidth( w );
146     myLabel->setFixedWidth( w );
147   }
148 }
149
150 InquireServersGUI::~InquireServersGUI()
151 {
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   myThread->stop(); //it's necessary to stop asking servers
168   hide();
169   qApp->exit( 1 );
170 }
171
172 void InquireServersGUI::customEvent( QCustomEvent* pe )
173 {
174   switch( pe->type() )
175     {
176         case InquireEvent::ProgressEvent:
177         {
178             int* value = ( int* )(( InquireEvent*)pe)->data();
179             myPrgBar->setProgress( *value );
180             break;
181         }
182         case InquireEvent::ProgressEventLabel:
183         {
184             QString* myString = ( QString* )(( InquireEvent*)pe)->data();
185             myLabel->setText( *myString );
186             break;
187         }
188         case InquireEvent::ProgressEventError:
189         {
190             QString* myErrDesc = ( QString* )(( InquireEvent*)pe)->data();
191             QString  appName = "SALOME Professional";
192             QString  error = "An internal error occurred.\n"+ *myErrDesc + "\n";
193             QMessageBox myMsgBox(appName,error,QMessageBox::Critical,QMessageBox::Ok,QMessageBox::NoButton,
194                                         QMessageBox::NoButton,0,"MY",TRUE,WStyle_DialogBorder|WStyle_StaysOnTop);
195             myMsgBox.exec();
196             ClickOnCancel();
197             break;
198         }
199       default:
200         {
201           ;
202         }
203     }
204 }
205
206 int InquireServersGUI::getExitStatus()
207 {
208   return myThread->getExitStatus();
209 }
210
211 InquireServersQThread::InquireServersQThread( InquireServersGUI* r )
212      : receiver(r),  myExitStatus(0)
213 {
214   char* cenv;
215
216   IsChecking = true;
217   myServersCount = 5;
218   //how many times we should repeat attempts to get response from all needed for launching SALOME servers
219   myRepeat = 30; // default value, user can change it by setting CSF_RepeatServerRequest env.variable
220   cenv = getenv( "CSF_RepeatServerRequest" );
221   if ( cenv ) {
222     int val = atoi( cenv );
223     if ( val > 0 )
224       myRepeat = val;
225   }
226   //define delay time between two attempts
227   myDelay = 1000000; // 1 second
228   QString str = "Loading: ";
229   myMessages[0] = "Checking naming service...";
230   myMessages[1] = str + "SALOME_Registry_Server" + "...";
231   myMessages[2] = str + "SALOMEDS_Server" + "...";
232   myMessages[3] = str + "SALOME_ModuleCatalog_Server" + "...";
233   myMessages[4] = str + "SALOME_Session_Server" + "...";
234   myMessages[5] = "";
235   myMessages[6] = "";
236   myMessages[7] = "";
237
238   r->getArgs( _argc, &_argv);
239
240   // NRI : Temporary solution for SuperVisionContainer
241   for ( int i=1; i<=(_argc-1); i++) {
242     if (strcmp(_argv[i],"CPP")==0) {
243       myMessages[5] = str + "SALOME_Container FactoryServer" + "...";
244       myServersCount++;
245     }
246     if (strcmp(_argv[i],"PY")==0) {
247       myMessages[6] = str + "SALOME_ContainerPy.py FactoryServerPy" + "...";
248       myServersCount++;
249     }
250     if (strcmp(_argv[i],"SUPERV")==0) {
251       myMessages[7] = str + "SALOME_Container SuperVisionContainer" + "...";
252       myServersCount++;
253     }
254 //    if (strcmp(_argv[i],"GUI")==0) {
255 //      r->withGUI(true);
256 //    }
257   }
258 }
259
260 void InquireServersQThread::run()
261 {
262   while ( IsChecking && receiver )
263   {
264     for (int i=1; i<=8; i++)
265     {
266       if ( myMessages[i-1].isEmpty() ) 
267       {
268         if ( i==8 ) 
269         {
270           IsChecking = false;
271           myExitStatus = 0;  //myExitStatus should be 0 because all servers exist and work
272           sleep( 1 ); // sleep( 1 second ) in order to see 100%.  in other case it closes on 85%..
273           break;
274         } 
275         else
276           continue;
277       }
278       QString *message = new QString(myMessages[i-1]);
279       QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEventLabel, message ) );
280       QThread::usleep(200000);
281       QString *errMsg;
282       bool result = AskServer(i,&errMsg);
283       if (result)
284       {
285         QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEvent, new int( i ) ) );
286         if ( i==8 )
287         {
288           IsChecking = false;
289           myExitStatus = 0; //myExitStatus should be 0 because all servers exist and work
290           sleep( 1 );  // sleep( 1 second ) in order to see 100%.  in other case it closes on 85%..
291           break;
292         }
293       }
294       else
295       {
296         QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEventError, errMsg ) );
297         stop();
298         break;
299       }
300     }
301   }
302
303   receiver->hide();
304   qApp->exit( myExitStatus );
305 }
306
307 void InquireServersQThread::stop()
308 {
309   IsChecking = false;
310   myExitStatus = 1;
311 }
312
313 InquireServersQThread::~InquireServersQThread()
314 {
315 }
316
317 bool InquireServersQThread::AskServer(int iteration, QString ** errMessage)
318 {
319   if ( iteration > myServersCount )
320     return true; // we did not launch server with number iteration, so checking for it is not neccessary
321
322   ASSERT(iteration<=myServersCount);
323
324   //will be set true if we get response from server
325   bool IsPassed = false;
326   QString errDescription;
327   switch (iteration)
328     {
329     case 1:
330       //First checking - existence of Naming Service
331       for (int i = myRepeat; i ; i--)
332         {
333           try
334             {
335               CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ;
336               CORBA::Object_var obj = orb->resolve_initial_references("NameService");
337               CosNaming::NamingContext_var _root_context = CosNaming::NamingContext::_narrow(obj);
338               if (CORBA::is_nil(_root_context))
339                 continue;
340               else
341                 IsPassed = true;
342               break;
343             }
344           catch(CORBA::COMM_FAILURE&)
345             {
346               MESSAGE("CORBA::COMM_FAILURE: unable to contact the naming service");
347             }
348           catch(...)
349             {
350               MESSAGE("Unknown Exception: unable to contact the naming service");
351             }
352           QThread::usleep(myDelay);
353         }
354       if (!IsPassed)
355         *errMessage = new QString("unable to contact the naming service");
356       break;
357     case 2:
358       //checking - existence of SALOME_Registry_Server
359     case 3:
360       //checking - existence of SALOMEDS_Server
361     case 4:
362       //checking - existence of SALOME_ModuleCatalog_Server
363     case 5:
364       //checking - existence of SALOME_Session_Server
365     case 6:
366       //checking - existence of SALOME_Container FactoryServer
367     case 7:
368       //checking - existence of SALOME_ContainerPy.py FactoryServerPy
369     case 8:
370       //checking - existence of SALOME_Container SuperVisionContainer
371
372
373       IsPassed = pingServer(iteration, errDescription);
374       if (!IsPassed)
375         *errMessage = new QString(errDescription);
376       break;
377     }
378 return IsPassed;
379 }
380
381 bool InquireServersQThread::pingServer(int iteration, QString& errMessage)
382 {
383   ASSERT(iteration<=myServersCount);
384   bool result = false;
385   QString errorDescr;
386   for (int i = myRepeat; i ; i--)
387     {
388       try
389         {
390           CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ;
391           SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance() ;
392           ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
393           NS.init_orb( orb ) ;
394           switch (iteration)
395             {
396             case 2:
397               {
398                 CORBA::Object_var obj = NS.Resolve("/Registry");
399                 Registry::Components_var registry = Registry::Components::_narrow(obj) ;
400                 if (!CORBA::is_nil(registry))
401                   {
402                     MESSAGE("/Registry is found");
403                     registry->ping();
404                     result = true;
405                     MESSAGE("Registry was activated");
406                     return result;
407                   }
408               }
409               break;
410             case 3:
411               {
412                 CORBA::Object_var obj = NS.Resolve("/myStudyManager");
413                 SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow(obj) ;
414                 if (!CORBA::is_nil(studyManager))
415
416
417
418
419
420                   {
421                     MESSAGE("/myStudyManager is found");
422                     studyManager->ping();
423                     result = true;
424                     MESSAGE("StudyManager was activated");
425                     return result;
426                   }
427               }
428               break;
429             case 4:
430               {
431                 CORBA::Object_var obj = NS.Resolve("/Kernel/ModulCatalog");
432                 SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
433                 if (!CORBA::is_nil(catalog))
434                   {
435                     MESSAGE("/Kernel/ModulCatalog is found");
436                     catalog->ping();
437                     result = true;
438                     MESSAGE("ModuleCatalog was activated");
439                     return result;
440                   }
441               }
442               break;
443             case 5:
444               {
445                 CORBA::Object_var obj = NS.Resolve("/Kernel/Session");
446                 SALOME::Session_var session = SALOME::Session::_narrow(obj) ;
447                 if (!CORBA::is_nil(session))
448                   {
449                     MESSAGE("/Kernel/Session is found");
450                     session->ping();
451                     result = true;
452                     MESSAGE("SALOME_Session was activated");
453                     return result;
454                   }
455               }
456               break;
457             case 6:
458               {
459                 string hostname = GetHostname();
460                 string containerName = "/Containers/";
461                 containerName += hostname;
462                 containerName += "/FactoryServer";
463
464                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
465                 Engines::Container_var FScontainer = Engines::Container::_narrow(obj) ;
466                 if (!CORBA::is_nil(FScontainer))
467                   {
468                     FScontainer->ping();
469                     result = true;
470                     MESSAGE("FactoryServer container was activated");
471                     return result;
472                   }
473               }
474               break;
475             case 7:
476               {
477                 string hostname = GetHostname();
478                 string containerName = "/Containers/";
479                 containerName += hostname;
480                 containerName += "/FactoryServerPy";
481                 
482                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
483                 Engines::Container_var FSPcontainer = Engines::Container::_narrow(obj) ;
484                 if (!CORBA::is_nil(FSPcontainer))
485                   {
486                     FSPcontainer->ping();
487                     result = true;
488                     MESSAGE("FactoryServerPy container was activated");
489                     return result;
490                   }
491               }
492               break;
493             case 8:
494               {
495                 string hostname = GetHostname();
496                 string containerName = "/Containers/";
497                 containerName += hostname;
498                 containerName += "/SuperVisionContainer";
499                 
500                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
501                 Engines::Container_var SVcontainer = Engines::Container::_narrow(obj) ;
502                 if (!CORBA::is_nil(SVcontainer))
503                   {
504                     SVcontainer->ping();
505
506                     result = true;
507                     MESSAGE("SuperVisionContainer container was activated");
508                     return result;
509                   }
510               }
511               break;
512             }
513          }
514       catch (ServiceUnreachable&)
515         {
516           MESSAGE("Caught exception: Naming Service Unreachable");
517           errorDescr = "Caught exception: Naming Service Unreachable";
518         }
519       catch (CORBA::COMM_FAILURE&)
520         {
521           MESSAGE("Caught CORBA::SystemException CommFailure.");
522           errorDescr = "Caught CORBA::SystemException CommFailure";
523         }
524       catch (CORBA::SystemException&)
525         {
526           MESSAGE("Caught CORBA::SystemException.");
527           errorDescr = "Caught CORBA::SystemException";
528         }
529       catch (CORBA::Exception&)
530         {
531           MESSAGE("Caught CORBA::Exception.");
532           errorDescr = "Caught CORBA::Exception";
533         }
534       catch (...)
535         {
536           MESSAGE("Caught unknown exception.");
537           errorDescr = "Caught unknown exception";
538         }
539       QThread::usleep(myDelay);
540     }
541   if (!result)
542     {
543       QString serverName;
544       switch (iteration)
545         {
546         case 2:
547           serverName = "SALOME_Registry_Server is not loaded. ";
548           break;
549         case 3:
550           serverName = "SALOMEDS_Server is not loaded. ";
551           break;
552         case 4:
553           serverName = "SALOME_ModuleCatalog_Server is not loaded. ";
554           break;
555         case 5:
556           serverName = "SALOME_Session_Server is not loaded. ";
557           break;
558         case 6:
559           serverName = "SALOME_Container FactoryServer is not loaded. ";
560           break;
561         case 7:
562           serverName = "SALOME_ContainerPy.py FactoryServerPy is not loaded. ";
563           break;
564         case 8:
565           serverName = "SALOME_Container SuperVisionContainer is not loaded. ";
566           break;
567         }
568       errMessage = serverName + errorDescr;
569     }
570   return result;
571 }
572