From 4520adfc050edcd145464c01d076255ac00b28a0 Mon Sep 17 00:00:00 2001 From: asv Date: Thu, 23 Jun 2005 11:15:58 +0000 Subject: [PATCH] Splash screen was implemented. Changes in packages SUIT and Session are integrated. --- src/SUIT/SUIT_Session.cxx | 23 +- src/SUIT/SUIT_Session.h | 7 +- src/Session/InquireServersQThread.cxx | 556 +++++++++++++++++++++++++ src/Session/InquireServersQThread.h | 118 ++++++ src/Session/Makefile.in | 5 +- src/Session/SALOME_Session_Server.cxx | 327 +++++++-------- src/Session/Session_ServerLauncher.cxx | 8 +- src/Session/Session_Session_i.cxx | 8 +- 8 files changed, 876 insertions(+), 176 deletions(-) create mode 100755 src/Session/InquireServersQThread.cxx create mode 100755 src/Session/InquireServersQThread.h diff --git a/src/SUIT/SUIT_Session.cxx b/src/SUIT/SUIT_Session.cxx index 082d49add..d47b8d3e3 100755 --- a/src/SUIT/SUIT_Session.cxx +++ b/src/SUIT/SUIT_Session.cxx @@ -23,7 +23,8 @@ SUIT_Session::SUIT_Session() : QObject(), myResMgr( 0 ), myHandler( 0 ), -myActiveApp( 0 ) +myActiveApp( 0 ), +myExitStatus( FROM_GUI ) { SUIT_ASSERT( !mySession ) @@ -193,19 +194,33 @@ void SUIT_Session::onApplicationClosed( SUIT_Application* theApp ) myActiveApp = 0; if ( myAppList.isEmpty() ) - qApp->quit(); + { + printf( "Calling QApplication::exit() with exit code = %d\n", myExitStatus ); + qApp->exit( myExitStatus ); + } } /*! Destroys session by closing all applications. */ -void SUIT_Session::closeSession() +void SUIT_Session::closeSession( int mode ) { while ( !myAppList.isEmpty() ) { SUIT_Application* app = myAppList.getFirst(); - if ( !app->isPossibleToClose() ) + if ( mode == ASK && !app->isPossibleToClose() ) return; + else if ( mode == SAVE ) + { + SUIT_Study* study = app->activeStudy(); + if ( study->isModified() && study->isSaved() ) + study->saveDocument(); + } + else if ( mode == DONT_SAVE ) + { + myExitStatus = FROM_CORBA_SESSION; + //.... + } app->closeApplication(); } diff --git a/src/SUIT/SUIT_Session.h b/src/SUIT/SUIT_Session.h index 842ef0ae9..7496955f3 100755 --- a/src/SUIT/SUIT_Session.h +++ b/src/SUIT/SUIT_Session.h @@ -37,6 +37,9 @@ class SUIT_EXPORT SUIT_Session: public QObject public: typedef LIB_HANDLE AppLib; + enum { ASK = 0, SAVE, DONT_SAVE } CloseMode; + enum { FROM_GUI = 0, FROM_CORBA_SESSION } ExitStatus; + public: SUIT_Session(); virtual ~SUIT_Session(); @@ -50,7 +53,7 @@ public: SUIT_ResourceMgr* resourceMgr() const; - void closeSession(); + void closeSession( int mode = ASK ); SUIT_ExceptionHandler* handler() const; @@ -82,6 +85,8 @@ private: SUIT_ExceptionHandler* myHandler; static SUIT_Session* mySession; + + int myExitStatus; }; #endif diff --git a/src/Session/InquireServersQThread.cxx b/src/Session/InquireServersQThread.cxx new file mode 100755 index 000000000..00bc1dab7 --- /dev/null +++ b/src/Session/InquireServersQThread.cxx @@ -0,0 +1,556 @@ +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : InquireServersQThread.cxx +// Author : Vasily RUSYAEV +// Module : SALOME +// $Header$ + +using namespace std; +#include "InquireServersQThread.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//VRV: porting on Qt 3.0.5 +#if QT_VERSION >= 0x030005 +#include +#endif +//VRV: porting on Qt 3.0.5 + +#include + +#include + +#include "Utils_ORB_INIT.hxx" +#include "Utils_SINGLETON.hxx" +#include "SALOME_NamingService.hxx" +#include "utilities.h" +#include "OpUtil.hxx" + +#include CORBA_CLIENT_HEADER(SALOME_Session) +#include CORBA_CLIENT_HEADER(SALOME_Registry) +#include CORBA_CLIENT_HEADER(SALOMEDS) +#include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog) +#include CORBA_CLIENT_HEADER(SALOME_Component) + +#define MARGIN_SIZE 5 +#define SPACING_SIZE 3 + +InquireServersGUI::InquireServersGUI() + : QVBox(0, "SFA splash", Qt::WDestructiveClose | Qt::WStyle_Customize | Qt::WStyle_NoBorder | WType_TopLevel | WStyle_StaysOnTop | WX11BypassWM ) +{ + // myGUI = false; + myThread = new InquireServersQThread( this ); + + // 1. Polish the appearance + setMargin( MARGIN_SIZE ); + setSpacing( SPACING_SIZE ); + setFrameStyle( QFrame::Plain | QFrame::Box ); + setLineWidth( 2 ); + setMinimumSize( 200, 150 ); + + // 2. Splash image + QFrame* frm = new QFrame( this ); + frm->setFrameStyle( QFrame::Box | QFrame::Raised ); + QHBoxLayout* frmLayout = new QHBoxLayout( frm ); + frmLayout->setMargin( MARGIN_SIZE ); + mySplash = new QLabel( frm, "splash" ); + frmLayout->addWidget( mySplash ); + + // setting pixmap + //QPixmap pix = SUIT_ResourceMgr( "SalomeApp" ).loadPixmap( "SalomeApp", tr( "ABOUT" ) ); + //splash->setPixmap( pix ); + + // 3. Progress bar + myPrgBar = new QProgressBar( this, "QProgressBar" ); + myPrgBar->setFixedWidth( 180 ); + //Sets the total number of steps . + myPrgBar->setTotalSteps ( myThread->getInquiredServers() ); + myPrgBar->setProgress( 0 ); + + // 4. Info label + QWidget* aWgt1 = new QWidget( this ); + QHBoxLayout* aHBoxLayout1 = new QHBoxLayout( aWgt1 ); + myLabel = new QLabel( tr( "Loading:" ), aWgt1 ); + myLabel->setFixedWidth( 180 ); + myLabel->setAlignment( AlignLeft ); + QFont theFont = myLabel->font(); + theFont.setBold(true); + myLabel->setFont( theFont ); + aHBoxLayout1->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) ); + aHBoxLayout1->addWidget( myLabel ); + aHBoxLayout1->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) ); + + // 5. button + QWidget* aWgt = new QWidget( this ); + QHBoxLayout* aHBoxLayout = new QHBoxLayout( aWgt ); + QPushButton* myCancelBtn = new QPushButton( tr( "Cancel" ), aWgt ); + connect( myCancelBtn, SIGNAL( clicked() ), this, SLOT( ClickOnCancel() ) ) ; + aHBoxLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) ); + aHBoxLayout->addWidget( myCancelBtn ); + aHBoxLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) ); + + //Center widget +#if QT_VERSION >= 0x030005 + QDesktopWidget *d = QApplication::desktop(); +#else + QWidget *d = QApplication::desktop(); +#endif +//VRV: porting on Qt 3.0.5 + + int w = d->width(); // returns desktop width + int h = d->height(); // returns desktop height + QSize mySize = sizeHint (); // returns widget size + int Xc = ( w - mySize.width() ) / 2; + int Yc = ( h - mySize.height() ) / 2; + move( Xc, Yc ); + + myThread->start(); +} + +void InquireServersGUI::setPixmap( QPixmap pix ) +{ + if ( !pix.isNull() ) { + mySplash->setPixmap( pix ); + myPrgBar->setFixedWidth( mySplash->sizeHint().width() ); + myLabel->setFixedWidth( mySplash->sizeHint().width() ); + } +} + +InquireServersGUI::~InquireServersGUI() +{ + delete myThread; +} + +void InquireServersGUI::getArgs( int& _argc, char *** _argv) +{ + _argc = qApp->argc(); + *_argv = qApp->argv(); +} + +//================================================================================= +// function : ClickOnCancel() +// purpose : cancel loading of SALOME +//================================================================================= +void InquireServersGUI::ClickOnCancel() +{ + //it's necessary to stop asking servers + myThread->stop(); + // myGUI = false; + //Also we should send QCloseEvent in order to close this widget (and remove from screen) + //QThread::postEvent ( this, new QCloseEvent() ); + qApp->exit(1); +} + +void InquireServersGUI::closeEvent ( QCloseEvent * pe) +{ + //default implementation calls e->accept(), which hides this widget. + //See the QCloseEvent documentation for more details. + pe->accept(); + QApplication::flushX (); + QApplication::syncX (); + qApp->exit(); +} + +void InquireServersGUI::customEvent( QCustomEvent* pe ) +{ + switch( pe->type() ) + { + case InquireEvent::ProgressEvent: + { + int* value = ( int* )(( InquireEvent*)pe)->data(); + myPrgBar->setProgress( *value ); + break; + } + case InquireEvent::ProgressEventLabel: + { + QString* myString = ( QString* )(( InquireEvent*)pe)->data(); + myLabel->setText( *myString ); + break; + } + case InquireEvent::ProgressEventError: + { + QString* myErrDesc = ( QString* )(( InquireEvent*)pe)->data(); + QString appName = "SALOME Professional"; + QString error = "An internal error occurred.\n"+ *myErrDesc + "\n"; + QMessageBox myMsgBox(appName,error,QMessageBox::Critical,QMessageBox::Ok,QMessageBox::NoButton, + QMessageBox::NoButton,0,"MY",TRUE,WStyle_DialogBorder|WStyle_StaysOnTop); + myMsgBox.exec(); + ClickOnCancel(); + break; + } + default: + { + ; + } + } +} + +int InquireServersGUI::getExitStatus() +{ + return myThread->getExitStatus(); +} + +InquireServersQThread::InquireServersQThread( InquireServersGUI* r ) + : receiver(r), myExitStatus(0) +{ + char* cenv; + + IsChecking = true; + myServersCount = 5; + //how many times we should repeat attempts to get response from all needed for launching SALOME servers + myRepeat = 30; // default value, user can change it by setting CSF_RepeatServerRequest env.variable + cenv = getenv( "CSF_RepeatServerRequest" ); + if ( cenv ) { + int val = atoi( cenv ); + if ( val > 0 ) + myRepeat = val; + } + //define delay time between two attempts + myDelay = 1000000; // 1 second + QString str = "Loading: "; + myMessages[0] = "Checking naming service..."; + myMessages[1] = str + "SALOME_Registry_Server" + "..."; + myMessages[2] = str + "SALOMEDS_Server" + "..."; + myMessages[3] = str + "SALOME_ModuleCatalog_Server" + "..."; + myMessages[4] = str + "SALOME_Session_Server" + "..."; + myMessages[5] = ""; + myMessages[6] = ""; + myMessages[7] = ""; + + r->getArgs( _argc, &_argv); + + // NRI : Temporary solution for SuperVisionContainer + for ( int i=1; i<=(_argc-1); i++) { + if (strcmp(_argv[i],"CPP")==0) { + myMessages[5] = str + "SALOME_Container FactoryServer" + "..."; + myServersCount++; + } + if (strcmp(_argv[i],"PY")==0) { + myMessages[6] = str + "SALOME_ContainerPy.py FactoryServerPy" + "..."; + myServersCount++; + } + if (strcmp(_argv[i],"SUPERV")==0) { + myMessages[7] = str + "SALOME_Container SuperVisionContainer" + "..."; + myServersCount++; + } +// if (strcmp(_argv[i],"GUI")==0) { +// r->withGUI(true); +// } + } +} + +void InquireServersQThread::run() +{ + while (IsChecking) + { + if ( !receiver ) + { + myExitStatus = 0; + return; + } + for (int i=1; i<=8; i++) + { + if ( myMessages[i-1].isEmpty() ) { + if (i==8) { + IsChecking = false; + //myExitStatus should be 0 because all servers exist and work + myExitStatus = 0; + //we should send QCloseEvent in order to close this widget (and remove from screen) + QThread::postEvent ( receiver , new QCloseEvent() ); + } else + continue; + } + QString *message = new QString(myMessages[i-1]); + QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEventLabel, message ) ); + QThread::usleep(200000); + QString *errMsg; + bool result = AskServer(i,&errMsg); + if (result) + { + QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEvent, new int( i ) ) ); + if (i==8) + { + IsChecking = false; + //myExitStatus should be 0 because all servers exist and work + myExitStatus = 0; + //we should send QCloseEvent in order to close this widget (and remove from screen) + QThread::postEvent ( receiver , new QCloseEvent() ); + } + } + else + { + QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEventError, errMsg ) ); + //myExitStatus should be 1 because we didn't receive response from server + myExitStatus = 1; + return; + } + } + } +} + +bool InquireServersQThread::AskServer(int iteration, QString ** errMessage) +{ + if ( iteration > myServersCount ) + return true; // we did not launch server with number iteration, so checking for it is not neccessary + + ASSERT(iteration<=myServersCount); + + //will be set true if we get response from server + bool IsPassed = false; + QString errDescription; + switch (iteration) + { + case 1: + //First checking - existence of Naming Service + for (int i = myRepeat; i ; i--) + { + try + { + CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ; + CORBA::Object_var obj = orb->resolve_initial_references("NameService"); + CosNaming::NamingContext_var _root_context = CosNaming::NamingContext::_narrow(obj); + if (CORBA::is_nil(_root_context)) + continue; + else + IsPassed = true; + break; + } + catch(CORBA::COMM_FAILURE&) + { + MESSAGE("CORBA::COMM_FAILURE: unable to contact the naming service"); + } + catch(...) + { + MESSAGE("Unknown Exception: unable to contact the naming service"); + } + QThread::usleep(myDelay); + } + if (!IsPassed) + *errMessage = new QString("unable to contact the naming service"); + break; + case 2: + //checking - existence of SALOME_Registry_Server + case 3: + //checking - existence of SALOMEDS_Server + case 4: + //checking - existence of SALOME_ModuleCatalog_Server + case 5: + //checking - existence of SALOME_Session_Server + case 6: + //checking - existence of SALOME_Container FactoryServer + case 7: + //checking - existence of SALOME_ContainerPy.py FactoryServerPy + case 8: + //checking - existence of SALOME_Container SuperVisionContainer + + + IsPassed = pingServer(iteration, errDescription); + if (!IsPassed) + *errMessage = new QString(errDescription); + break; + } +return IsPassed; +} + +bool InquireServersQThread::pingServer(int iteration, QString& errMessage) +{ + ASSERT(iteration<=myServersCount); + bool result = false; + QString errorDescr; + for (int i = myRepeat; i ; i--) + { + try + { + CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ; + SALOME_NamingService &NS = *SINGLETON_::Instance() ; + ASSERT(SINGLETON_::IsAlreadyExisting()) ; + NS.init_orb( orb ) ; + switch (iteration) + { + case 2: + { + CORBA::Object_var obj = NS.Resolve("/Registry"); + Registry::Components_var registry = Registry::Components::_narrow(obj) ; + if (!CORBA::is_nil(registry)) + { + MESSAGE("/Registry is found"); + registry->ping(); + result = true; + MESSAGE("Registry was activated"); + return result; + } + } + break; + case 3: + { + CORBA::Object_var obj = NS.Resolve("/myStudyManager"); + SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow(obj) ; + if (!CORBA::is_nil(studyManager)) + + + + + + { + MESSAGE("/myStudyManager is found"); + studyManager->ping(); + result = true; + MESSAGE("StudyManager was activated"); + return result; + } + } + break; + case 4: + { + CORBA::Object_var obj = NS.Resolve("/Kernel/ModulCatalog"); + SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ; + if (!CORBA::is_nil(catalog)) + { + MESSAGE("/Kernel/ModulCatalog is found"); + catalog->ping(); + result = true; + MESSAGE("ModuleCatalog was activated"); + return result; + } + } + break; + case 5: + { + CORBA::Object_var obj = NS.Resolve("/Kernel/Session"); + SALOME::Session_var session = SALOME::Session::_narrow(obj) ; + if (!CORBA::is_nil(session)) + { + MESSAGE("/Kernel/Session is found"); + session->ping(); + result = true; + MESSAGE("SALOME_Session was activated"); + return result; + } + } + break; + case 6: + { + string hostname = GetHostname(); + string containerName = "/Containers/"; + containerName += hostname; + containerName += "/FactoryServer"; + + CORBA::Object_var obj = NS.Resolve(containerName.c_str()); + Engines::Container_var FScontainer = Engines::Container::_narrow(obj) ; + if (!CORBA::is_nil(FScontainer)) + { + FScontainer->ping(); + result = true; + MESSAGE("FactoryServer container was activated"); + return result; + } + } + break; + case 7: + { + string hostname = GetHostname(); + string containerName = "/Containers/"; + containerName += hostname; + containerName += "/FactoryServerPy"; + + CORBA::Object_var obj = NS.Resolve(containerName.c_str()); + Engines::Container_var FSPcontainer = Engines::Container::_narrow(obj) ; + if (!CORBA::is_nil(FSPcontainer)) + { + FSPcontainer->ping(); + result = true; + MESSAGE("FactoryServerPy container was activated"); + return result; + } + } + break; + case 8: + { + string hostname = GetHostname(); + string containerName = "/Containers/"; + containerName += hostname; + containerName += "/SuperVisionContainer"; + + CORBA::Object_var obj = NS.Resolve(containerName.c_str()); + Engines::Container_var SVcontainer = Engines::Container::_narrow(obj) ; + if (!CORBA::is_nil(SVcontainer)) + { + SVcontainer->ping(); + + result = true; + MESSAGE("SuperVisionContainer container was activated"); + return result; + } + } + break; + } + } + catch (ServiceUnreachable&) + { + MESSAGE("Caught exception: Naming Service Unreachable"); + errorDescr = "Caught exception: Naming Service Unreachable"; + } + catch (CORBA::COMM_FAILURE&) + { + MESSAGE("Caught CORBA::SystemException CommFailure."); + errorDescr = "Caught CORBA::SystemException CommFailure"; + } + catch (CORBA::SystemException&) + { + MESSAGE("Caught CORBA::SystemException."); + errorDescr = "Caught CORBA::SystemException"; + } + catch (CORBA::Exception&) + { + MESSAGE("Caught CORBA::Exception."); + errorDescr = "Caught CORBA::Exception"; + } + catch (...) + { + MESSAGE("Caught unknown exception."); + errorDescr = "Caught unknown exception"; + } + QThread::usleep(myDelay); + } + if (!result) + { + QString serverName; + switch (iteration) + { + case 2: + serverName = "SALOME_Registry_Server is not loaded. "; + break; + case 3: + serverName = "SALOMEDS_Server is not loaded. "; + break; + case 4: + serverName = "SALOME_ModuleCatalog_Server is not loaded. "; + break; + case 5: + serverName = "SALOME_Session_Server is not loaded. "; + break; + case 6: + serverName = "SALOME_Container FactoryServer is not loaded. "; + break; + case 7: + serverName = "SALOME_ContainerPy.py FactoryServerPy is not loaded. "; + break; + case 8: + serverName = "SALOME_Container SuperVisionContainer is not loaded. "; + break; + } + errMessage = serverName + errorDescr; + } + return result; +} diff --git a/src/Session/InquireServersQThread.h b/src/Session/InquireServersQThread.h new file mode 100755 index 000000000..37b32cd62 --- /dev/null +++ b/src/Session/InquireServersQThread.h @@ -0,0 +1,118 @@ +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : InquireServersQThread.h +// Author : Vasily RUSYAEV +// Module : SALOME +// $Header$ + +#include +#include +#include +#include +#include + +/********************************************************** +** Class: InquireEvent +** Descr: Contains QCustomEvents for posting to InquireServersQThread +** Level: Private +***********************************************************/ + +class InquireEvent : public QCustomEvent +{ +public: + + enum myCustomEvents{ ProgressEvent = QEvent::User + 10, ProgressEventLabel, ProgressEventError }; + + InquireEvent( QEvent::Type type , void* data = 0 ) + : QCustomEvent( type, data ) {} + ~InquireEvent() + { + type() == (QEvent::Type)ProgressEvent ? + delete ( int* )data() : delete ( QString* )data(); + } +}; + +class InquireServersGUI; + +class InquireServersQThread : public QThread +{ +public: + InquireServersQThread( InquireServersGUI* r ); + + //the main loop of this thread + virtual void run() ; + //stop to ask servers + void stop() + { + IsChecking = false; + myExitStatus = 1; + } + //return exit status: 0 - OK, >0 - BAD (some servers doesn't exists or user click cancel button) + int getExitStatus() { return myExitStatus;} + //return count of inquired servers + int getInquiredServers() { return myServersCount; } + +private: + +//functions: + + bool AskServer(int iteration, QString ** message); + bool pingServer(int iteration, QString& errMessage); + +//variables: + + InquireServersGUI* receiver; + int _argc ; + char ** _argv; + //this variable is true if we are checking servers + bool IsChecking; + //count of inquired servers + int myServersCount; + //how many times we should repeat attempt to get response from all needed for launching SALOME servers + int myRepeat; + //define delay time between two attempts in microseconds + int myDelay; + //this strings' array contains messages for each server (e.g. "Loading: SALOMEDS_Server") + QString myMessages[8]; + //exit status: 0 - OK, >0 - BAD (some servers doesn't exists or user click cancel button) + int myExitStatus; + +} ; + +class InquireServersGUI : public QVBox +{ + Q_OBJECT + +public: + InquireServersGUI() ; + ~InquireServersGUI(); + + //returns arguments of QApplication + //they are needed for CORBA servers initialization + void getArgs( int& _argc, char *** _argv); + //return exit status: 0 - OK, >0 - BAD (some servers doesn't exists or user click cancel button) + int getExitStatus(); + //launch IAPP + // bool withGUI() { return myGUI; } + // void withGUI(bool gui) { myGUI = gui; } + + void setPixmap( QPixmap ); + +protected: + virtual void customEvent( QCustomEvent* ); + virtual void closeEvent ( QCloseEvent * ); + +private: + InquireServersQThread* myThread; + QProgressBar* myPrgBar; + //this string contains description of currently asked server + QLabel* myLabel; + QLabel* mySplash; + // bool myGUI; + +private slots: + + void ClickOnCancel(); +} ; diff --git a/src/Session/Makefile.in b/src/Session/Makefile.in index 69ee385f0..a97a1583b 100755 --- a/src/Session/Makefile.in +++ b/src/Session/Makefile.in @@ -47,7 +47,10 @@ LIB_SRC=Session_Session_i.cxx \ Session_ServerThread.cxx \ Session_ServerLauncher.cxx \ Session_SignalsHandler.cxx \ - SalomeApp_Engine_i.cxx + SalomeApp_Engine_i.cxx \ + InquireServersQThread.cxx + +LIB_MOC = InquireServersQThread.h # Executables targets BIN = SALOME_Session_Server diff --git a/src/Session/SALOME_Session_Server.cxx b/src/Session/SALOME_Session_Server.cxx index 415c5328a..368b63c8d 100755 --- a/src/Session/SALOME_Session_Server.cxx +++ b/src/Session/SALOME_Session_Server.cxx @@ -32,6 +32,8 @@ #include "SALOME_NamingService.hxx" #include "SALOMETraceCollector.hxx" +#include "InquireServersQThread.h" // splash + #include #include @@ -55,6 +57,7 @@ #include "SUIT_Session.h" #include "SUIT_Application.h" #include "SUIT_MessageBox.h" +#include "SUIT_Tools.h" #include "SUIT_ExceptionHandler.h" @@ -163,15 +166,38 @@ private: SUIT_ExceptionHandler* myHandler; }; +// class which calls SALOME::Session::GetInterface() from another thread +// to avoid mutual lock (if called from the same thread as main() +class GetInterfaceThread : public QThread +{ +public: + GetInterfaceThread( SALOME::Session_var s ) : session ( s ) {} +protected: + virtual void run() + { + if ( !CORBA::is_nil( session ) ) + session->GetInterface(); + else + printf( "\nFATAL ERROR: SALOME::Session object is nil! Can not display GUI\n\n" ); + } +private: + SALOME::Session_var session; +}; + +// returns true if 'str' is found in argv +bool isFound( const char* str, int argc, char** argv ) +{ + for ( int i = 1; i <= (argc-1); i++ ) + if ( !strcmp( argv[i], str ) ) + return true; + return false; +} + +// ---------------------------- MAIN ----------------------- int main(int argc, char **argv) { qInstallMsgHandler( MessageOutput ); - /* - char* _argv_0[512]; - strcpy( (char*)_argv_0, (char*)argv[0] ); - */ - // QApplication should be create before all other operations // When uses QApplication::libraryPaths() (example, QFile::encodeName()) // qApp used for detection of the executable dir path. @@ -192,17 +218,17 @@ int main(int argc, char **argv) char* _argv[] = {""}; KERNEL_PYTHON::init_python(_argc,_argv); PyEval_RestoreThread(KERNEL_PYTHON::_gtstate); - if(!KERNEL_PYTHON::salome_shared_modules_module) // import only once - { - KERNEL_PYTHON::salome_shared_modules_module = - PyImport_ImportModule("salome_shared_modules"); - } - if(!KERNEL_PYTHON::salome_shared_modules_module) - { - INFOS("salome_shared_modules_module == NULL"); - PyErr_Print(); - PyErr_Clear(); - } + if ( !KERNEL_PYTHON::salome_shared_modules_module ) // import only once + { + KERNEL_PYTHON::salome_shared_modules_module = + PyImport_ImportModule("salome_shared_modules"); + } + if ( !KERNEL_PYTHON::salome_shared_modules_module ) + { + INFOS("salome_shared_modules_module == NULL"); + PyErr_Print(); + PyErr_Clear(); + } PyEval_ReleaseThread(KERNEL_PYTHON::_gtstate); int result = -1; @@ -213,167 +239,138 @@ int main(int argc, char **argv) int orbArgc = 1; CORBA::ORB_var &orb = init( orbArgc , argv ) ; SALOMETraceCollector *myThreadTrace = SALOMETraceCollector::instance(orb); + GetInterfaceThread* guiThread = 0; try + { + SALOME_Event::GetSessionThread(); + + CORBA::Object_var obj = orb->resolve_initial_references("RootPOA"); + PortableServer::POA_var poa = PortableServer::POA::_narrow(obj); + + PortableServer::POAManager_var pman = poa->the_POAManager() ; + pman->activate() ; + INFOS("pman->activate()"); + + SALOME_NamingService *_NS = new SALOME_NamingService(orb); + + // CORBA Servant Launcher + QMutex _GUIMutex ; + QWaitCondition _ServerLaunch; + _GUIMutex.lock(); // to block Launch server thread until wait(mutex) + + // 2. activate embedded CORBA servers: Registry, SALOMEDS, etc. + Session_ServerLauncher* myServerLauncher + = new Session_ServerLauncher(argc, argv, orb, poa, &_GUIMutex, &_ServerLaunch); + myServerLauncher->start(); + + _ServerLaunch.wait(&_GUIMutex); // to be reseased by Launch server thread when ready: + // show splash screen if "SPLASH" parameter was passed (default) + if ( isFound( "SPLASH", argc, argv ) ) { - SALOME_Event::GetSessionThread(); - - CORBA::Object_var obj = orb->resolve_initial_references("RootPOA"); - PortableServer::POA_var poa = PortableServer::POA::_narrow(obj); - - PortableServer::POAManager_var pman = poa->the_POAManager() ; - pman->activate() ; - INFOS("pman->activate()"); - - SALOME_NamingService *_NS = new SALOME_NamingService(orb); - - // CORBA Servant Launcher - QMutex _GUIMutex ; - QWaitCondition _ServerLaunch; - _GUIMutex.lock(); // to block Launch server thread until wait(mutex) - - // 2. activate embedded CORBA servers: Registry, SALOMEDS, etc. - Session_ServerLauncher* myServerLauncher - = new Session_ServerLauncher(argc, argv, orb, poa, &_GUIMutex, &_ServerLaunch); - myServerLauncher->start(); - - // 3. GUI activation - // Allow multiple activation/deactivation of GUI - //while ( 1 ) { - MESSAGE("waiting wakeAll()"); - _ServerLaunch.wait(&_GUIMutex); // to be reseased by Launch server thread when ready: - // atomic operation lock - unlock on mutex - // unlock mutex: serverThread runs, calls _ServerLaunch->wakeAll() - // this thread wakes up, and lock mutex - - INFOS("Session activated, Launch IAPP..."); - /* - int qArgc = 1; - argv[0] = (char*)_argv_0; - SALOME_QApplication* _qappl = new SALOME_QApplication( qArgc, argv ); - - QStringList lst = _qappl->libraryPaths(); - for ( QStringList::const_iterator it = lst.begin(); it != lst.end(); ++it ) - printf( "=====> Library path: %s\n", (*it).latin1() ); - - _qappl->setStyle( "salome" ); - - ASSERT ( QObject::connect(_qappl, SIGNAL(lastWindowClosed()), _qappl, SLOT(quit()) ) ); - */ - - INFOS("creation QApplication"); - _GUIMutex.unlock(); - - // 3.1 SUIT_Session creation - SUIT_Session* aGUISession = new SALOME_Session(); - INFOS("creation SUIT_Application"); - - SCRUTE(_NS); - - // 3.3 run GUI loop - // T2.12 - catch exceptions thrown on attempts to modified a locked study - while (1) { - try - { - MESSAGE("run(): starting the main event loop"); - - // 3.2 load SalomeApp dynamic library - SUIT_Application* aGUIApp = aGUISession->startApplication( "SalomeApp", 0, 0 ); - if ( aGUIApp ) - { - _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application - // aGUISession contains SalomeApp_ExceptionHandler - result = _qappl.exec(); - } - break; - } - catch (SALOME::SALOME_Exception& e) - { - INFOS("run(): SALOME_Exception was caught!"); - QApplication::restoreOverrideCursor(); - SUIT_MessageBox::warn1 ( 0, - QObject::tr("WRN_WARNING"), - QObject::tr("SALOME_Exception was caught!"), - QObject::tr("BUT_OK") ); - //QtCatchCorbaException(e); - } - catch(SALOMEDS::StudyBuilder::LockProtection&) - { - INFOS("run(): An attempt to modify a locked study has not been handled by QAD_Operation"); - QApplication::restoreOverrideCursor(); - SUIT_MessageBox::warn1 ( 0, - QObject::tr("WRN_WARNING"), - QObject::tr("WRN_STUDY_LOCKED"), - QObject::tr("BUT_OK") ); - } - catch (const CORBA::Exception& e) - { - CORBA::Any tmp; - tmp<<= e; - CORBA::TypeCode_var tc = tmp.type(); - const char *p = tc->name(); - INFOS ("run(): CORBA exception of the kind : "<Resolve("/Kernel/Session"); + SALOME::Session_var session = SALOME::Session::_narrow( obj ) ; + ASSERT (! CORBA::is_nil( session ) ); - //orb->shutdown(0); - //myServerLauncher->KillAll(); + INFOS("Session activated, Launch IAPP..."); + guiThread = new GetInterfaceThread( session ); + guiThread->start(); } - catch (SALOME_Exception& e) + + // 3. GUI activation + // Allow multiple activation/deactivation of GUI + while ( 1 ) { - INFOS("run(): SALOME::SALOME_Exception is caught: "<wakeAll() + // this thread wakes up, and lock mutex + + _GUIMutex.unlock(); + + // 3.1 SUIT_Session creation + SUIT_Session* aGUISession = new SALOME_Session(); + INFOS("creation SUIT_Application"); + + SCRUTE(_NS); + + // 3.3 run GUI loop + // T2.12 - catch exceptions thrown on attempts to modified a locked study + MESSAGE("run(): starting the main event loop"); + + // 3.2 load SalomeApp dynamic library + SUIT_Application* aGUIApp = aGUISession->startApplication( "SalomeApp", 0, 0 ); + if ( aGUIApp ) + { + _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application + // aGUISession contains SalomeApp_ExceptionHandler + result = _qappl.exec(); + + if ( result == SUIT_Session::FROM_GUI ) // desktop is closed by user from GUI + break; + } + + // Prepare _GUIMutex for a new GUI activation + _GUIMutex.lock(); } + + //orb->shutdown(0); + myServerLauncher->KillAll(); // kill embedded servers + } + catch (SALOME_Exception& e) + { + INFOS("run(): SALOME::SALOME_Exception is caught: "<name(); - INFOS ("run(): CORBA exception of the kind : "<name(); + INFOS ("run(): CORBA exception of the kind : "<>> Session_ServerLauncher::run"); _GUIMutex->lock(); // lock released by calling thread when ready: wait(mutex) - //MESSAGE("Server Launcher thread free to go..."); + MESSAGE("****>>> Server Launcher thread free to go..."); _GUIMutex->unlock(); - + _ServerLaunch->wakeAll(); CheckArgs(); ActivateAll(); @@ -206,6 +206,8 @@ std::cout << "*** activating [" << argc << "] : " << argv[0] << std::endl; // Always launch Session Server +std::cout << "*** activating [ SESSION ] " << std::endl; + int argc=1; char** argv = new char*[argc]; argv[0] = "Session"; diff --git a/src/Session/Session_Session_i.cxx b/src/Session/Session_Session_i.cxx index 0b9fe8ae0..e383b774f 100755 --- a/src/Session/Session_Session_i.cxx +++ b/src/Session/Session_Session_i.cxx @@ -134,6 +134,8 @@ void SALOME_Session_i::NSregister() void SALOME_Session_i::GetInterface() { + _GUIMutex->lock(); + _GUIMutex->unlock(); if( !SUIT_Session::session() ) { _GUILauncher->wakeAll(); MESSAGE("SALOME_Session_i::GetInterface() called, starting GUI...") @@ -149,8 +151,10 @@ class CloseEvent : public SALOME_Event { public: virtual void Execute() { -//if ( SUIT_Application::getDesktop() ) -// QAD_Application::getDesktop()->closeDesktop( true ); + SUIT_Session* session = SUIT_Session::session(); + session->closeSession( SUIT_Session::DONT_SAVE ); + //if ( SUIT_Application::getDesktop() ) + // QAD_Application::getDesktop()->closeDesktop( true ); } }; -- 2.39.2