X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSession%2FSALOME_Session_Server.cxx;h=c8b52cf4f4c4b7204bd83da04392f17d8ec3561e;hb=06535b81ff1cf8ac920dd2212c6b28d168ddcc08;hp=daa2dbb18e7e80014e75aeaac5c071a6afae4993;hpb=f830c97c748d8f8a6a7eccc8e3a58e19066a1181;p=modules%2Fgui.git diff --git a/src/Session/SALOME_Session_Server.cxx b/src/Session/SALOME_Session_Server.cxx index daa2dbb18..c8b52cf4f 100755 --- a/src/Session/SALOME_Session_Server.cxx +++ b/src/Session/SALOME_Session_Server.cxx @@ -1,75 +1,82 @@ -// SALOME Session : implementation of Session.idl +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE // -// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// -// -// File : SALOME_Session_Server.cxx -// Author : Paul RASCLE, EDF -// Module : SALOME + +// SALOME Session : implementation of Session.idl +// File : SALOME_Session_Server.cxx +// Author : Paul RASCLE, EDF +// Module : SALOME + +#include +#include +#include +#include + +#include #include -#include "Utils_ORB_INIT.hxx" -#include "Utils_SINGLETON.hxx" -#include "SALOME_NamingService.hxx" -#include "SALOMETraceCollector.hxx" - -#include "SALOME_ModuleCatalog_impl.hxx" -#include "OpUtil.hxx" -#include "RegistryService.hxx" -#include "ConnectionManager_i.hxx" - -#include -#ifndef WNT -#include -#include -#include +#include +#include + +#ifdef ENABLE_TESTRECORDER + #include #endif -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include + +#include +#include "Session_ServerLauncher.hxx" +#include "Session_ServerCheck.hxx" +#include "Session_Session_i.hxx" + +#include +#include + +#include -#include "Utils_SALOME_Exception.hxx" -#include "Utils_CorbaException.hxx" -#include "SALOME_Event.hxx" +#include "GUI_version.h" +#include +#include +#include +#include +#include +#include #include #include CORBA_SERVER_HEADER(SALOME_Session) #include CORBA_SERVER_HEADER(SALOMEDS) -#include -#include "Session_Session_i.hxx" -#include "Session_ServerLauncher.hxx" -#include "Session_ServerCheck.hxx" +#include -#include -#include "SUIT_Tools.h" -#include "SUIT_Session.h" -#include "SUIT_Application.h" -#include "SUIT_Desktop.h" -#include "SUIT_MessageBox.h" -#include "SUIT_ResourceMgr.h" -#include "SUIT_ExceptionHandler.h" +#include +#include +#include +#include +#include +#include +#include /*! - read arguments, define list of server to launch with their arguments. * - wait for naming service @@ -89,14 +96,12 @@ * - get session state */ -PyObject* salome_shared_modules_module = 0; - void MessageOutput( QtMsgType type, const char* msg ) { switch ( type ) { case QtDebugMsg: - MESSAGE( "Debug: " << msg ); + //MESSAGE( "Debug: " << msg ); break; case QtWarningMsg: MESSAGE( "Warning: " << msg ); @@ -107,56 +112,9 @@ void MessageOutput( QtMsgType type, const char* msg ) } } -/* XPM */ -static const char* pixmap_not_found_xpm[] = { -"16 16 3 1", -" c None", -". c #000000", -"+ c #A80000", -" ", -" ", -" . . ", -" .+. .+. ", -" .+++. .+++. ", -" .+++.+++. ", -" .+++++. ", -" .+++. ", -" .+++++. ", -" .+++.+++. ", -" .+++. .+++. ", -" .+. .+. ", -" . . ", -" ", -" ", -" "}; - QString salomeVersion() { - QString path( ::getenv( "GUI_ROOT_DIR" ) ); - if ( !path.isEmpty() ) - path += QDir::separator(); - path += QString( "bin/salome/VERSION" ); - - QFile vf( path ); - if ( !vf.open( IO_ReadOnly ) ) - return QString::null; - - QString line; - vf.readLine( line, 1024 ); - vf.close(); - - if ( line.isEmpty() ) - return QString::null; - - while ( !line.isEmpty() && line.at( line.length() - 1 ) == QChar( '\n' ) ) - line.remove( line.length() - 1, 1 ); - - QString ver; - int idx = line.findRev( ":" ); - if ( idx != -1 ) - ver = line.mid( idx + 1 ).stripWhiteSpace(); - - return ver; + return GUI_VERSION_STR; } class SALOME_ResourceMgr : public SUIT_ResourceMgr @@ -166,7 +124,6 @@ public: { setCurrentFormat( "xml" ); setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) ); - setDefaultPixmap( QPixmap( pixmap_not_found_xpm ) ); } static void initResourceMgr() { @@ -175,14 +132,14 @@ public: resMgr.loadLanguage( "LightApp", "en" ); resMgr.loadLanguage( "SalomeApp", "en" ); - myExtAppName = QObject::tr( "APP_NAME" ).stripWhiteSpace(); - if ( myExtAppName == "APP_NAME" || myExtAppName.lower() == "salome" ) + myExtAppName = QObject::tr( "APP_NAME" ).trimmed(); + if ( myExtAppName == "APP_NAME" || myExtAppName.toLower() == "salome" ) myExtAppName = "SalomeApp"; myExtAppVersion = QObject::tr( "APP_VERSION" ); if ( myExtAppVersion == "APP_VERSION" ) { if ( myExtAppName != "SalomeApp" ) myExtAppVersion = ""; - else myExtAppVersion = salomeVersion(); + else myExtAppVersion = salomeVersion(); } } } @@ -191,39 +148,71 @@ public: protected: QString userFileName( const QString& appName, const bool for_load ) const { - if ( version().isNull() ) return ""; + if ( version().isEmpty() ) return ""; return SUIT_ResourceMgr::userFileName( myExtAppName, for_load ); } - virtual int userFileId( const QString& _fname ) const + virtual long userFileId( const QString& _fname ) const { + ////////////////////////////////////////////////////////////////////////////////////////////// + // In SALOME and SALOME-based applications the user preferences file is named as + // - .xml. on Windows + // - rc. on Linux + // where + // * AppName is application name, default SalomeApp (can be customized in SALOME-based + // applications + // * AppVersion is application version + // + // Since version 6.5.0 of SALOME, user file is situated in the ~/.config/salome + // directory. For backward compatibility, when user preferences from nearest + // version of application is searched, user home directory is also looked through, + // with lower priority. + // + // Since version 6.6.0 of SALOME, user file name on Linux is no more prefixed by dot + // symbol since it is situated in hidden ~/.config/salome directory. Files with dot + // prefix also though taken into account (with lower priority) for backward compatibility. + // + // Notes: + // - Currently the following format of version number is supported: + // [.[.[]]] + // Parts in square brackets are considered optional. Here: + // * major - major version id + // * minor - minor version id + // * release - maintenance version id + // * type - dev or patch marker; it can be either one alphabetical symbol (from 'a' to 'z') + // or 'rc' to point release candidate (case-insensitive) + // * dev - dev version or patch number + // All numerical values must be of range [1-99]. + // Examples: 1.0, 6.5.0, 1.2.0a1, 3.3.3rc3 (release candidate 3), 11.0.0p1 (patch 1) + // + // - Versioning approach can be customized by implementing and using own resource manager class, + // see QtxResurceMgr, SUIT_ResourceMgr classes. + ////////////////////////////////////////////////////////////////////////////////////////////// + long id = -1; if ( !myExtAppName.isEmpty() ) { - QRegExp exp( QString( "\\.%1rc\\.([a-zA-Z0-9.]+)$" ).arg( myExtAppName ) ); - QRegExp vers_exp( "^([0-9]+)([A-Za-z]?)([0-9]*)$" ); - +#ifdef WIN32 + // On Windows, user file name is something like SalomeApp.xml.6.5.0 where + // - SalomeApp is an application name (can be customized) + // - xml is a file format (xml or ini) + // - 6.5.0 is an application version, can include alfa/beta/rc marks, e.g. 6.5.0a3, 6.5.0rc1 + QRegExp exp( QString( "%1\\.%2\\.([a-zA-Z0-9.]+)" ).arg( myExtAppName ).arg( currentFormat() ) ); +#else + // On Linux, user file name is something like SalomeApprc.6.5.0 where + // - SalomeApp is an application name (can be customized) + // - 6.5.0 is an application version, can include alfa/beta/rc marks, e.g. 6.5.0a3, 6.5.0rc1 + + // VSR 24/09/2012: issue 0021781: since version 6.6.0 user filename is not prepended with "." + // when it is stored in the ~/.config/ directory; + // for backward compatibility we also check files prepended with "." with lower priority + QRegExp exp( QString( "\\.?%1rc\\.([a-zA-Z0-9.]+)" ).arg( myExtAppName ) ); +#endif QString fname = QFileInfo( _fname ).fileName(); - if( exp.exactMatch( fname ) ) { - QStringList vers = QStringList::split( ".", exp.cap( 1 ) ); - int major=0, minor=0; - major = vers[0].toInt(); - minor = vers[1].toInt(); - if( vers_exp.search( vers[2] )==-1 ) - return -1; - int release = 0, dev1 = 0, dev2 = 0; - release = vers_exp.cap( 1 ).toInt(); - dev1 = vers_exp.cap( 2 )[ 0 ].latin1(); - dev2 = vers_exp.cap( 3 ).toInt(); - - int dev = dev1*100+dev2, id = major; - id*=100; id+=minor; - id*=100; id+=release; - id*=10000; - if ( dev > 0 ) id+=dev-10000; - return id; + if ( exp.exactMatch( fname ) ) { + long fid = Qtx::versionToId( exp.cap( 1 ) ); + if ( fid > 0 ) id = fid; } } - - return -1; + return id; } public: @@ -231,8 +220,8 @@ public: static QString myExtAppVersion; }; -QString SALOME_ResourceMgr::myExtAppName = QString::null; -QString SALOME_ResourceMgr::myExtAppVersion = QString::null; +QString SALOME_ResourceMgr::myExtAppName = QString(); +QString SALOME_ResourceMgr::myExtAppVersion = QString(); class SALOME_Session : public SUIT_Session { @@ -240,7 +229,7 @@ public: SALOME_Session() : SUIT_Session() {} virtual ~SALOME_Session() {} -protected: +public: virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const { SALOME_ResourceMgr::initResourceMgr(); @@ -249,29 +238,53 @@ protected: } }; -class SALOME_QApplication : public QApplication +#ifdef ENABLE_TESTRECORDER + class SALOME_QApplication : public TestApplication +#else + class SALOME_QApplication : public QApplication +#endif { public: - SALOME_QApplication( int& argc, char** argv ) : QApplication( argc, argv ), myHandler ( 0 ) {} +#ifdef ENABLE_TESTRECORDER + SALOME_QApplication( int& argc, char** argv ) : TestApplication( argc, argv ), myHandler ( 0 ) {} +#else + SALOME_QApplication( int& argc, char** argv ) +#ifndef WIN32 + // san: Opening an X display and choosing a visual most suitable for 3D visualization + // in order to make SALOME viewers work with non-native X servers + : QApplication( (Display*)Qtx::getDisplay(), argc, argv, Qtx::getVisual() ), +#else + : QApplication( argc, argv ), +#endif + myHandler ( 0 ) {} +#endif virtual bool notify( QObject* receiver, QEvent* e ) { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) < 0x060101 - // Disable GUI user actions while python command is executed - if (SUIT_Session::IsPythonExecuted()) { - // Disable mouse and keyboard events - QEvent::Type aType = e->type(); - if (aType == QEvent::MouseButtonPress || aType == QEvent::MouseButtonRelease || - aType == QEvent::MouseButtonDblClick || aType == QEvent::MouseMove || - aType == QEvent::Wheel || aType == QEvent::ContextMenu || - aType == QEvent::KeyPress || aType == QEvent::KeyRelease || - aType == QEvent::Accel || aType == QEvent::AccelOverride) - return false; - } -#endif +#ifdef ENABLE_TESTRECORDER return myHandler ? myHandler->handle( receiver, e ) : - QApplication::notify( receiver, e ); + TestApplication::notify( receiver, e ); +#else + try { + return myHandler ? myHandler->handle( receiver, e ) : QApplication::notify( receiver, e ); + } + catch (std::exception& e) { + std::cerr << e.what() << std::endl; + } + catch (CORBA::Exception& e) { + std::cerr << "Caught CORBA::Exception" << std::endl; + CORBA::Any tmp; + tmp<<= e; + CORBA::TypeCode_var tc = tmp.type(); + const char *p = tc->name(); + std::cerr << "notify(): CORBA exception of the kind : " << p << " is caught" << std::endl; + } + catch (...) { + std::cerr << "Unknown exception caught in Qt handler: it's probably a bug in SALOME platform" << std::endl; + } + return false; // return false when exception is caught +#endif } SUIT_ExceptionHandler* handler() const { return myHandler; } void setHandler( SUIT_ExceptionHandler* h ) { myHandler = h; } @@ -312,123 +325,14 @@ bool isFound( const char* str, int argc, char** argv ) void killOmniNames() { - QString fileName( ::getenv ("OMNIORB_CONFIG") ); - QString portNumber; - if ( !fileName.isEmpty() ) - { - QFile aFile( fileName ); - if ( aFile.open(IO_ReadOnly) ) { - QRegExp re("InitRef = .*:([0-9]+)$"); - QTextStream stream ( &aFile ); - while ( !stream.atEnd() ) { - QString textLine = stream.readLine(); - if ( re.search( textLine ) > -1 ) - portNumber = re.cap(1); - } - aFile.close(); - } - } - - if ( !portNumber.isEmpty() ) - { - QString cmd ; - cmd = QString( "ps -eo pid,command | grep -v grep | grep -E \"omniNames.*%1\" | awk '{cmd=sprintf(\"kill -9 %s\",$1); system(cmd)}'" ).arg( portNumber ); - system ( cmd.latin1() ); - } - - /////////////////// NPAL 18309 (Kill Notifd) //////////////////////////// - if ( !portNumber.isEmpty() ) - { - QString cmd = QString("import pickle, os; "); - cmd += QString("from killSalomeWithPort import getPiDict; "); - cmd += QString("filedict=getPiDict(%1); ").arg(portNumber); - cmd += QString("f=open(filedict, 'r'); "); - cmd += QString("pids=pickle.load(f); "); - cmd += QString("m={}; "); - cmd += QString("[ m.update(i) for i in pids ]; "); - cmd += QString("pids=filter(lambda a: 'notifd' in m[a], m.keys()); "); - cmd += QString("[ os.kill(pid, 9) for pid in pids ]; "); - cmd += QString("os.remove(filedict); "); - cmd = QString("python -c \"%1\" > /dev/null").arg(cmd); - system( cmd.latin1() ); - } - + SALOME_LifeCycleCORBA::killOmniNames(); } // shutdown standalone servers void shutdownServers( SALOME_NamingService* theNS ) { - // get each Container from NamingService => shutdown it - // (the order is inverse to the order of servers initialization) - - CORBA::Object_var objS = theNS->Resolve("/Kernel/Session"); - SALOME::Session_var session = SALOME::Session::_narrow(objS); - if (!CORBA::is_nil(session)) { - session->ping(); - - string hostname = GetHostname(); - //string containerName = "/Containers/" + hostname; - - // 1) SuperVisionContainer - //string containerNameSV = containerName + "/SuperVisionContainer"; - //CORBA::Object_var objSV = theNS->Resolve(containerNameSV.c_str()); - //Engines::Container_var SVcontainer = Engines::Container::_narrow(objSV) ; - //if ( !CORBA::is_nil(SVcontainer) && ( session->getPID() != SVcontainer->getPID() ) ) - // SVcontainer->Shutdown(); - - // 2) FactoryServerPy - //string containerNameFSP = containerName + "/FactoryServerPy"; - //CORBA::Object_var objFSP = theNS->Resolve(containerNameFSP.c_str()); - //Engines::Container_var FSPcontainer = Engines::Container::_narrow(objFSP) ; - //if ( !CORBA::is_nil(FSPcontainer) && ( session->getPID() != FSPcontainer->getPID() ) ) - // FSPcontainer->Shutdown(); - - // 3) FactoryServer - //string containerNameFS = containerName + "/FactoryServer"; - //CORBA::Object_var objFS = theNS->Resolve(containerNameFS.c_str()); - //Engines::Container_var FScontainer = Engines::Container::_narrow(objFS) ; - //if ( !CORBA::is_nil(FScontainer) && ( session->getPID() != FScontainer->getPID() ) ) - // FScontainer->Shutdown(); - - // 4) ContainerManager - //CORBA::Object_var objCM=theNS->Resolve("/ContainerManager"); - //Engines::ContainerManager_var contMan=Engines::ContainerManager::_narrow(objCM); - //if ( !CORBA::is_nil(contMan) && ( session->getPID() != contMan->getPID() ) ) - // contMan->ShutdownWithExit(); - - // 4) SalomeLauncher - CORBA::Object_var objSL = theNS->Resolve("/SalomeLauncher"); - Engines::SalomeLauncher_var launcher = Engines::SalomeLauncher::_narrow(objSL); - if (!CORBA::is_nil(launcher) && (session->getPID() != launcher->getPID())) - launcher->Shutdown(); - - // 5) ConnectionManager - CORBA::Object_var objCnM=theNS->Resolve("/ConnectionManager"); - Engines::ConnectionManager_var connMan=Engines::ConnectionManager::_narrow(objCnM); - if ( !CORBA::is_nil(connMan) && ( session->getPID() != connMan->getPID() ) ) - connMan->ShutdownWithExit(); - - // 6) SALOMEDS - CORBA::Object_var objSDS = theNS->Resolve("/myStudyManager"); - SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow(objSDS) ; - if ( !CORBA::is_nil(studyManager) && ( session->getPID() != studyManager->getPID() ) ) - studyManager->Shutdown(); - - // 7) ModuleCatalog - CORBA::Object_var objMC=theNS->Resolve("/Kernel/ModulCatalog"); - SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(objMC); - if ( !CORBA::is_nil(catalog) && ( session->getPID() != catalog->getPID() ) ) - catalog->shutdown(); - - // 8) Registry - CORBA::Object_var objR = theNS->Resolve("/Registry"); - Registry::Components_var registry = Registry::Components::_narrow(objR); - if ( !CORBA::is_nil(registry) && ( session->getPID() != registry->getPID() ) ) - registry->Shutdown(); - - // 9) Kill OmniNames - //killOmniNames(); - } + SALOME_LifeCycleCORBA lcc(theNS); + lcc.shutdownServers(); } // ---------------------------- MAIN ----------------------- @@ -436,89 +340,75 @@ int main( int argc, char **argv ) { // Install Qt debug messages handler qInstallMsgHandler( MessageOutput ); + + //Set a "native" graphic system in case if application runs on the remote host + QString remote(getenv("REMOTEHOST")); + QString client(getenv("SSH_CLIENT")); + if(remote.length() > 0 || client.length() > 0 ) { + QApplication::setGraphicsSystem(QLatin1String("native")); + } + // add $QTDIR/plugins to the pluins search path for image plugins + QString qtdir( ::getenv( "QTDIR" ) ); + if ( !qtdir.isEmpty() ) + QApplication::addLibraryPath( QDir( qtdir ).absoluteFilePath( "plugins" ) ); + + { + SALOME_Session s; + QApplication::setApplicationName( "salome" ); + SUIT_ResourceMgr* resMgr = s.createResourceMgr( "SalomeApp" ); + bool isCloc = resMgr->booleanValue( "language", "locale", true ); + if ( isCloc ) { + QLocale::setDefault( QLocale::c() ); + } + else { + QLocale::setDefault( QLocale::system() ); + } + } + // Create Qt application instance; // this should be done the very first! SALOME_QApplication _qappl( argc, argv ); - ASSERT( QObject::connect( &_qappl, SIGNAL( lastWindowClosed() ), &_qappl, SLOT( quit() ) ) ); + _qappl.setOrganizationName( "salome" ); + _qappl.setApplicationName( "salome" ); + _qappl.setApplicationVersion( salomeVersion() ); // Add application library path (to search style plugin etc...) QString path = QDir::convertSeparators( SUIT_Tools::addSlash( QString( ::getenv( "GUI_ROOT_DIR" ) ) ) + QString( "bin/salome" ) ); _qappl.addLibraryPath( path ); - - // Set SALOME style to the application - _qappl.setStyle( "salome" ); bool isGUI = isFound( "GUI", argc, argv ); bool isSplash = isFound( "SPLASH", argc, argv ); // Show splash screen (only if both the "GUI" and "SPLASH" parameters are set) + // Note, that user preferences are not taken into account for splash settings - + // it is a property of the application! QtxSplash* splash = 0; if ( isGUI && isSplash ) { // ...create resource manager SUIT_ResourceMgr resMgr( "SalomeApp", QString( "%1Config" ) ); resMgr.setCurrentFormat( "xml" ); - resMgr.loadLanguage( "LightApp", "en" ); - // ...get splash preferences - QString splashIcon; - resMgr.value( "splash", "image", splashIcon ); - QPixmap px( splashIcon ); - if ( px.isNull() ) // try to get splash pixmap from resources - px = resMgr.loadPixmap( "LightApp", QObject::tr( "ABOUT_SPLASH" ) ); - if ( !px.isNull() ) { - // ...set splash pixmap - splash = QtxSplash::splash( px ); - // ... set margin - int splashMargin; - if ( resMgr.value( "splash", "margin", splashMargin ) && splashMargin > 0 ) { - splash->setMargin( splashMargin ); - } - // ...set splash text colors - QString splashTextColors; - if ( resMgr.value( "splash", "text_colors", splashTextColors ) && !splashTextColors.isEmpty() ) { - QStringList colors = QStringList::split( "|", splashTextColors ); - QColor c1, c2; - if ( colors.count() > 0 ) c1 = QColor( colors[0] ); - if ( colors.count() > 1 ) c2 = QColor( colors[1] ); - splash->setTextColors( c1, c2 ); - } - else { - splash->setTextColors( Qt::white, Qt::black ); - } - // ...set splash progress colors - QString splashProgressColors; - if ( resMgr.value( "splash", "progress_colors", splashProgressColors ) && !splashProgressColors.isEmpty() ) { - QStringList colors = QStringList::split( "|", splashProgressColors ); - QColor c1, c2; - int gradType = QtxSplash::Vertical; - if ( colors.count() > 0 ) c1 = QColor( colors[0] ); - if ( colors.count() > 1 ) c2 = QColor( colors[1] ); - if ( colors.count() > 2 ) gradType = colors[2].toInt(); - splash->setProgressColors( c1, c2, gradType ); - } - // ...set splash text font - QFont f = splash->font(); - f.setBold( true ); - splash->setFont( f ); - // ...show splash initial status - QString splashInfo; - if ( resMgr.value( "splash", "info", splashInfo, false ) && !splashInfo.isEmpty() ) { - splashInfo.replace( QRegExp( "%A" ), QObject::tr( "APP_NAME" ) ); - splashInfo.replace( QRegExp( "%V" ), QObject::tr( "ABOUT_VERSION" ).arg( salomeVersion() ) ); - splashInfo.replace( QRegExp( "%L" ), QObject::tr( "ABOUT_LICENSE" ) ); - splashInfo.replace( QRegExp( "%C" ), QObject::tr( "ABOUT_COPYRIGHT" ) ); - splashInfo.replace( QRegExp( "\\\\n" ), "\n" ); - splash->message( splashInfo ); - } - // ...set 'hide on click' flag -#ifdef _DEBUG_ - splash->setHideOnClick( true ); -#endif - // ...show splash + resMgr.setWorkingMode( QtxResourceMgr::IgnoreUserValues ); + resMgr.loadLanguage( "LightApp" ); + // + splash = QtxSplash::splash( QPixmap() ); + splash->readSettings( &resMgr ); + if ( splash->pixmap().isNull() ) + splash->setPixmap( resMgr.loadPixmap( "LightApp", QObject::tr( "ABOUT_SPLASH" ) ) ); + if ( splash->pixmap().isNull() ) { + delete splash; + splash = 0; + } + else { + splash->setOption( "%A", QObject::tr( "APP_NAME" ) ); + splash->setOption( "%V", QObject::tr( "ABOUT_VERSION" ).arg( salomeVersion() ) ); + splash->setOption( "%L", QObject::tr( "ABOUT_LICENSE" ) ); + splash->setOption( "%C", QObject::tr( "ABOUT_COPYRIGHT" ) ); splash->show(); - qApp->processEvents(); + QApplication::instance()->processEvents(); } } + // Initialization int result = -1; @@ -533,16 +423,8 @@ int main( int argc, char **argv ) try { // ...initialize Python (only once) int _argc = 1; - char* _argv[] = {""}; + char* _argv[] = {(char*)""}; 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(); - } - PyEval_ReleaseThread( KERNEL_PYTHON::_gtstate ); // ...create ORB, get RootPOA object, NamingService, etc. ORB_INIT &init = *SINGLETON_::Instance(); @@ -550,9 +432,6 @@ int main( int argc, char **argv ) int orbArgc = 1; orb = init( orbArgc, argv ); - // ...install SALOME thread event handler - SALOME_Event::GetSessionThread(); - CORBA::Object_var obj = orb->resolve_initial_references( "RootPOA" ); poa = PortableServer::POA::_narrow( obj ); @@ -578,7 +457,7 @@ int main( int argc, char **argv ) const char *p = tc->name(); INFOS ( "run(): CORBA exception of the kind : "<setProgress( 0, sc.totalSteps() ); + // start check loop + while ( true ) { + int step = sc.currentStep(); + int total = sc.totalSteps(); + QString msg = sc.currentMessage(); + QString err = sc.error(); + if ( !err.isEmpty() ) { + QtxSplash::setError( err ); + QApplication::instance()->processEvents(); + result = -1; + break; + } + QtxSplash::setStatus( msg, step ); + QApplication::instance()->processEvents(); + if ( step >= total ) + break; + // ...block this thread until servers checking is finished + _SplashStarted.wait( &_SplashMutex ); + } // ...unlock mutex 'cause it is no more needed _SplashMutex.unlock(); - // get servers checking thread status - result = splash->error(); - QString info = splash->message().isEmpty() ? "%1" : QString( "%1\n%2" ).arg( splash->message() ); - splash->setStatus( info.arg( "Activating desktop..." ) ); } // Finalize embedded servers launcher @@ -624,14 +518,17 @@ int main( int argc, char **argv ) _GUIMutex.unlock(); } - bool shutdown = false; + // Obtain Session interface reference + CORBA::Object_var obj = _NS->Resolve( "/Kernel/Session" ); + SALOME::Session_var session = SALOME::Session::_narrow( obj ) ; + + bool shutdownAll = false; + bool shutdownSession = false; if ( !result ) { // Launch GUI activator if ( isGUI ) { - // ...retrieve Session interface reference - CORBA::Object_var obj = _NS->Resolve( "/Kernel/Session" ); - SALOME::Session_var session = SALOME::Session::_narrow( obj ) ; - ASSERT ( ! CORBA::is_nil( session ) ); + if ( splash ) + splash->setStatus( QApplication::translate( "", "Activating desktop..." ) ); // ...create GUI launcher MESSAGE( "Session activated, Launch IAPP..." ); guiThread = new GetInterfaceThread( session ); @@ -648,6 +545,14 @@ int main( int argc, char **argv ) _SessionMutex.unlock(); + // Session might be shutdowning here, check status + SALOME::StatSession stat = session->GetStatSession(); + shutdownSession = stat.state == SALOME::shutdown; + if ( shutdownSession ) { + _SessionMutex.lock(); // lock mutex before leaving loop - it will be unlocked later + break; + } + // SUIT_Session creation aGUISession = new SALOME_Session(); @@ -656,30 +561,45 @@ int main( int argc, char **argv ) SUIT_Application* aGUIApp = aGUISession->startApplication( "SalomeApp", 0, 0 ); if ( aGUIApp ) { - if ( !isFound( "noexcepthandler", argc, argv ) ) - _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application - // aGUISession contains SalomeApp_ExceptionHandler - // Run GUI loop - MESSAGE( "run(): starting the main event loop" ); - - if ( splash ) - splash->finish( aGUIApp->desktop() ); - - result = _qappl.exec(); - - if ( splash ) - delete splash; - splash = 0; - - if ( result == SUIT_Session::NORMAL ) { // desktop is closed by user from GUI - shutdown = aGUISession->exitFlags(); - break; - } + Style_Salome::initialize( aGUIApp->resourceMgr() ); + if ( aGUIApp->resourceMgr()->booleanValue( "Style", "use_salome_style", true ) ) + Style_Salome::apply(); + + if ( !isFound( "noexcepthandler", argc, argv ) ) + _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application + // aGUISession contains SalomeApp_ExceptionHandler + // Run GUI loop + MESSAGE( "run(): starting the main event loop" ); + + if ( splash ) + splash->finish( aGUIApp->desktop() ); + + result = _qappl.exec(); + + splash = 0; + + if ( result == SUIT_Session::NORMAL ) { + // desktop is explicitly closed by user from GUI + // exit flags says if it's necessary to shutdown all servers + // all session server only + shutdownAll = aGUISession->exitFlags(); + } + else { + // desktop might be closed from: + // - StopSesion() /temporarily/ or + // - Shutdown() /permanently/ + stat = session->GetStatSession(); + shutdownSession = stat.state == SALOME::shutdown; + } + if ( shutdownAll || shutdownSession ) { + _SessionMutex.lock(); // lock mutex before leaving loop - it will be unlocked later + break; + } } delete aGUISession; aGUISession = 0; - + // Prepare _GUIMutex for a new GUI activation _SessionMutex.lock(); } @@ -688,37 +608,70 @@ int main( int argc, char **argv ) // unlock Session mutex _SessionMutex.unlock(); - if ( shutdown ) + if ( myServerLauncher ) + myServerLauncher->ShutdownAll(); // shutdown embedded servers + + if ( shutdownAll ) // shutdown standalone servers shutdownServers( _NS ); if ( myServerLauncher ) - myServerLauncher->KillAll(); // kill embedded servers + myServerLauncher->KillAll(); // kill embedded servers + + // Unregister session server + SALOME_Session_i* sessionServant = dynamic_cast( poa->reference_to_servant( session.in() ) ); + if ( sessionServant ) + sessionServant->NSunregister(); delete aGUISession; delete guiThread; delete myServerLauncher; delete _NS; - PyGILState_STATE gstate = PyGILState_Ensure(); - Py_Finalize(); + try { + orb->shutdown(0); + } + catch (...) { + ////////////////////////////////////////////////////////////// + // VSR: silently skip exception: + // CORBA.BAD_INV_ORDER.BAD_INV_ORDER_ORBHasShutdown + // exception is raised when orb->destroy() is called and + // cpp continer is launched in the embedded mode + ////////////////////////////////////////////////////////////// + // std::cerr << "Caught unexpected exception on shutdown : ignored !!" << std::endl; + if ( shutdownAll ) + killOmniNames(); + abort(); //abort program to avoid deadlock in destructors or atexit when shutdown has been interrupted + } - try + //Destroy orb from python (for chasing memory leaks) + //PyRun_SimpleString("from omniORB import CORBA"); + //PyRun_SimpleString("orb=CORBA.ORB_init([''], CORBA.ORB_ID)"); + //PyRun_SimpleString("orb.destroy()"); + + // Destroy the ORB: + sleep(2); + //std::cout << "@@@@@ Explicitely destroying the ORB (hoping to kill omniORB threads ...)\n"; + ORB_INIT * init = SINGLETON_::Instance(); + if (init) + init->explicit_destroy(); + //std::cout << "@@@@@ ORB destroyed\n"; + + // After ORB destruction + if(Py_IsInitialized()) { - orb->destroy(); + PyGILState_Ensure(); + //std::cout << "@@@@@ About to PyFinalize\n"; + Py_Finalize(); + //std::cout << "@@@@@ DONE PyFinalize\n"; } - catch(...) + + if ( shutdownAll ) { - ////////////////////////////////////////////////////////////// - // VSR: silently skip exception: - // CORBA.BAD_INV_ORDER.BAD_INV_ORDER_ORBHasShutdown - // exception is raised when orb->destroy() is called and - // cpp continer is launched in the embedded mode - ////////////////////////////////////////////////////////////// - // std::cerr << "Caught unexpected exception on destroy : ignored !!" << std::endl; + //std::cout << "@@@@@ About to kill omni\n"; + killOmniNames(); + //std::cout << "@@@@@ DONE kill omni\n"; } - if ( shutdown ) - killOmniNames(); - + MESSAGE( "Salome_Session_Server:endofserver" ); return result; }