From ad7fc8bd40bfd2931eed40c848cea393ddde3490 Mon Sep 17 00:00:00 2001 From: vsr Date: Mon, 10 Feb 2020 10:33:10 +0300 Subject: [PATCH] GUI launcher: systematize run procedure --- bin/runLightSalome.sh | 333 ++++++----- src/LightApp/resources/LightApp.xml | 1 + src/Qtx/Qtx.cxx | 33 +- src/Qtx/Qtx.h | 6 +- src/Qtx/QtxResourceMgr.cxx | 7 +- src/SUIT/SUIT_ResourceMgr.cxx | 16 +- src/SUIT/SUIT_Session.cxx | 27 - src/SUIT/SUIT_Session.h | 5 - src/SUITApp/SUITApp.cxx | 454 ++++++++------- src/SalomeApp/SalomeApp_Application.cxx | 7 +- src/Session/CMakeLists.txt | 10 + src/Session/SALOME_Session_Server.cxx | 716 ++++++++++++------------ src/Session/Session_ServerCheck.cxx | 18 +- src/Session/resources/Session_msg_fr.ts | 75 +++ 14 files changed, 921 insertions(+), 787 deletions(-) create mode 100644 src/Session/resources/Session_msg_fr.ts diff --git a/bin/runLightSalome.sh b/bin/runLightSalome.sh index 024851f7a..ced7e01d9 100755 --- a/bin/runLightSalome.sh +++ b/bin/runLightSalome.sh @@ -22,256 +22,247 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # -# File : runLightSalome.sh -# Author : Vadim SANDLER, Open CASCADE S.A.S, vadim.sandler@opencascade.com - - ### # function show_usage() : print help an exit ### -show_usage() { - local RET=0 - if [ $# -gt 0 ] ; then RET=$1 ; fi - local MOVE1="echo -en \\033[35G" - local MOVE2="echo -en \\033[22G" +show_usage() +{ echo echo "Run standalone SALOME desktop". echo - echo "Usage: $(basename $0) [options]" + echo "Usage: $(basename ${0}) [options]" echo echo "Options:" - echo "-m MODULES, --modules=MODULES List of modules, separated by comma, to be used within SALOME session." - echo "-r RCFILE, --resources=RCFILE Preferences file to be used within SALOME session." - echo "-v, --version Print SALOME version and exit." - echo "-h, --help Print this help and exit." + echo "-h, --help Print this information and exit." + echo "-v, --version Print SALOME version and exit." + echo "-m MODULES, --modules=MODULES Comma-separated list of modules to be used within SALOME session." + echo "-r RCFILE, --resources=RCFILE User preferences file to be used within SALOME session, instead of default one." + echo "-a LANGUAGE, --language=LANGUAGE Language to be used within SALOME session, instead of default one." + echo "-z, --no-splash Do not display splash screeen." + echo "-c, --no-exception-handler Do not install exception handler (allows debugging exceptions)." + echo "-l, --show-license Show license dialog at start-up." echo echo "Example:" - echo " $(basename $0) --modules=LIGHT,PYLIGHT" + echo " $(basename ${0}) --modules=LIGHT,PYLIGHT" echo - exit ${RET} + exit 0 } ### # function show_version() : print SALOME version an exit ### -show_version() { - local RET=0 - local DIR=$(dirname $0) - if [ -z "${DIR}" ] ; then DIR=. ; fi - if [ -f ${DIR}/VERSION ] ; then - cat ${DIR}/VERSION +show_version() +{ + local where=$(readlink -f $(dirname "${0}")) + if [ -f ${where}/VERSION ] + then + cat ${where}/VERSION else echo - echo "Error: can't find VERSION file" > /dev/stderr + echo "Error: can't find VERSION file" > /dev/stderr echo - RET=1 + exit 1 fi - exit ${RET} + exit 0 } ### -# function option_modules() : process --modules / -m command line option +# function long_option() : extract value from long command line option ### -option_modules() { - local MODS - case $1 in - modules\=* ) - MODS=`echo $1 | awk -F "=" '{ if(NF>1) print $2 ; else print "" }'` - ;; - modules* ) - echo - echo "Error: Invalid option format, please use --modules=MODULES" > /dev/stderr - echo - exit 1 - ;; - * ) - MODS=$1 - ;; - esac - if [ "X${MODS}" = "X" ] ; then - echo - echo "Error: Please, specify list of modules" > /dev/stderr - echo +long_option() +{ + local option=${1} + local value=${2} + + if [ $(echo ${value} | grep -e "^${option}=") ] + then + value=$(echo ${value} | sed -e "s%^${option}=%%") + else + value= + fi + + if [ "${value}" = "" ] + then + echo "Error: please, specify value for option '--${option}'" > /dev/stderr exit 1 fi - MODULES=`echo ${MODS} | sed -e "s%,% %g"` - return + + echo ${value} } ### -# function option_resources() : process --resources / -r command line option +# function remove_duplications() : remove duplications ### -option_resources() { - local RCF - case $1 in - resources\=* ) - RCF=`echo $1 | awk -F "=" '{ if(NF>1) print $2 ; else print "" }'` ;; - resources* ) - echo - echo "Error: Invalid option format, please use --resources=RCFILE" > /dev/stderr - echo - exit 1 - ;; - * ) RCF=$1 - esac - if [ "X${RCF}" = "X" ] ; then - echo - echo "Error: Please, specify resource file" > /dev/stderr - echo - exit 1 - fi - RCFILE="--resources=${RCF}" - return +remove_duplications() +{ + local unique + local m + for m in ${@} + do + case ${m} in + KERNEL | GUI ) + ;; + * ) + echo ${unique} | grep -qvE "\<${m}\>" && unique+=" ${m}" + ;; + esac + done + echo ${unique} } + ### # function run_light_salome(): run SALOME ### -run_light_salome(){ - - local MODULES - local RCFILE +run_light_salome() +{ + local modules + local rcfile + local language + local no_splash=0 + local debug_exceptions=0 + local show_license=0 ### # process command line options ### - local OPTION - while getopts ":-:hvm:r:" OPTION "$@" ; do - if [ "${OPTION}" = "-" ] ; then + local option + while getopts ":-:hvzclm:r:a:" option "${@}" + do + if [ "${option}" = "-" ] + then case ${OPTARG} in - help ) show_usage ;; - version ) show_version ;; - modules* ) option_modules "${OPTARG}" ;; - resources* ) option_resources "${OPTARG}" ;; - * ) echo "!!!Wrong option!!!" ; exit 1 ;; + help ) show_usage ;; + version ) show_version ;; + no-splash ) no_splash=1 ;; + no-exception-handler ) debug_exceptions=1 ;; + show-license ) show_license=1 ;; + modules* ) modules=$(long_option modules ${OPTARG}) ;; + resources* ) rcfile=$(long_option resources ${OPTARG}) ;; + language* ) language=$(long_option language ${OPTARG}) ;; + * ) echo "Wrong option: --${OPTARG}" ; return 1 ;; + esac + else + case ${option} in + h ) show_usage ;; + v ) show_version ;; + z ) no_splash=1 ;; + c ) debug_exceptions=1 ;; + l ) show_license=1 ;; + m* ) modules=${OPTARG} ;; + r* ) rcfile=${OPTARG} ;; + a* ) language=${OPTARG} ;; + ? ) echo "Wrong option" ; return 1 ;; esac - else - case ${OPTION} in - h ) show_usage ;; - v ) show_version ;; - m* ) option_modules "${OPTARG}" ;; - r* ) option_resources "${OPTARG}" ;; - ? ) echo "!!!Wrong option!!!" ; exit 1 ;; - esac - fi + fi done shift $((OPTIND - 1)) - ### - # by default try to detect all available modules - ### - - if [ -z "${MODULES}" ] ; then - local ENVVAR - local ROOTDIR - for ENVVAR in `env | awk -F= '{print $1}' | grep _ROOT_DIR` ; do - local MOD=`echo $ENVVAR | awk -F_ '{print $1}'` - local LMOD=`echo ${MOD} | tr 'A-Z' 'a-z'` - ROOTDIR=`printenv ${ENVVAR}` - if [ -f ${ROOTDIR}/share/salome/resources/${LMOD}/LightApp.xml ] || [ -f ${ROOTDIR}/share/salome/resources/LightApp.xml ] ; then - MODULES="${MODULES} ${MOD}" - fi - done - fi + modules=$(echo ${modules} | sed -e "s%,% %g") ### - # initial environment + # if modules aren't given in command line option, try to detect all available modules ### - if [ -z "${LightAppResources}" ] ; then - export LightAppResources=${GUI_ROOT_DIR}/share/salome/resources/gui - else - export LightAppResources=${LightAppResources}:${GUI_ROOT_DIR}/share/salome/resources/gui + if [ "${modules}" = "" ] + then + local envvar + for envvar in $(env | awk -F= '{print $1}' | grep _ROOT_DIR) + do + local mdir=${!envvar} + local mname=$(echo ${envvar} | awk -F_ '{print $1}') + local mname_lc=$(echo ${mname} | tr 'A-Z' 'a-z') + if [ -f ${mdir}/share/salome/resources/${mname_lc}/LightApp.xml ] || [ -f ${mdir}/share/salome/resources/LightApp.xml ] + then + modules+=" ${mname}" + fi + done fi ### - # exclude modules duplication + # remove duplications from modules list ### - local MODS="" - local MOD - for MOD in ${MODULES} ; do - case ${MOD} in - KERNEL | GUI ) - ;; - * ) - echo ${MODS} | grep -E "\<${MOD}\>" >/dev/null 2>&1 - if [ "$?" == "1" ] ; then - MODS="${MODS} ${MOD}" - fi - ;; - esac - done - MODULES=${MODS} + modules=$(remove_duplications ${modules}) ### - # set additional environment + # set-up environment ### - local PVERSION=`python -c "import sys; print(sys.version[:3])" 2>/dev/null` - - local MY_PATH="" - local MY_LD_LIBRARY_PATH="" - local MY_PYTHONPATH="" + if [ "${LightAppResources}" = "" ] + then + export LightAppResources=${GUI_ROOT_DIR}/share/salome/resources/gui + else + export LightAppResources=${LightAppResources}:${GUI_ROOT_DIR}/share/salome/resources/gui + fi + + local pyversion=$(python3 -c "import sys; print(sys.version[:3])" 2>/dev/null) + local my_path + local my_ld_library_path + local my_pythonpath - for MOD in KERNEL GUI ${MODULES} ; do - local ROOTDIR=`printenv ${MOD}_ROOT_DIR` - if [ -z "${ROOTDIR}" ] ; then continue ; fi - local LMOD=`echo ${MOD} | tr 'A-Z' 'a-z'` - if [ -d ${ROOTDIR}/bin/salome ] ; then - MY_PATH=${MY_PATH}:${ROOTDIR}/bin/salome - fi - if [ -d ${ROOTDIR}/lib/salome ] ; then - MY_LD_LIBRARY_PATH=${MY_LD_LIBRARY_PATH}:${ROOTDIR}/lib/salome - fi - if [ "${PVERSION}" != "" ] ; then - if [ -d ${ROOTDIR}/bin/salome ] ; then - MY_PYTHONPATH=${MY_PYTHONPATH}:${ROOTDIR}/bin/salome - fi - if [ -d ${ROOTDIR}/lib/salome ] ; then - MY_PYTHONPATH=${MY_PYTHONPATH}:${ROOTDIR}/lib/salome - fi - if [ -d ${ROOTDIR}/lib/python${PVERSION}/site-packages/salome ] ; then - MY_PYTHONPATH=${MY_PYTHONPATH}:${ROOTDIR}/lib/python${PVERSION}/site-packages/salome - fi - fi - if [ -f ${ROOTDIR}/share/salome/resources/${LMOD}/LightApp.xml ] ; then - export LightAppConfig=${LightAppConfig}:${ROOTDIR}/share/salome/resources/${LMOD} - elif [ -f ${ROOTDIR}/share/salome/resources/LightApp.xml ] ; then - export LightAppConfig=${LightAppConfig}:${ROOTDIR}/share/salome/resources - fi - export SALOMEPATH=${SALOMEPATH}:${ROOTDIR} + local m + for m in KERNEL GUI ${modules} + do + local root=${m}_ROOT_DIR + root=${!root} + if [ "${root}" != "" ] + then + local m_lc=$(echo ${m} | tr 'A-Z' 'a-z') + test -d ${root}/bin/salome && my_path+=:${root}/bin/salome + test -d ${root}/lib/salome && my_ld_library_path+=:${root}/lib/salome + if [ "${pyversion}" != "" ] + then + test -d ${root}/bin/salome && my_pythonpath+=:${root}/bin/salome + test -d ${root}/lib/salome && my_pythonpath+=:${root}/lib/salome + test -d ${root}/lib/python${pyversion}/site-packages/salome && my_pythonpath+=:${root}/lib/python${pyversion}/site-packages/salome + fi + if [ -f ${root}/share/salome/resources/${m_lc}/LightApp.xml ] + then + export LightAppConfig+=:${root}/share/salome/resources/${m_lc} + elif [ -f ${root}/share/salome/resources/LightApp.xml ] + then + export LightAppConfig+=:${root}/share/salome/resources + fi + export SALOMEPATH+=:${root} + fi done - PATH=${MY_PATH}:${PATH} - PATH=`echo ${PATH} | sed -e "s,^:,,;s,:$,,;s,::\+,:,g"` + PATH=${my_path}:${PATH} + PATH=$(echo ${PATH} | sed -e "s,^:,,;s,:$,,;s,::\+,:,g") export PATH - LD_LIBRARY_PATH=${MY_LD_LIBRARY_PATH}:${LD_LIBRARY_PATH} - LD_LIBRARY_PATH=`echo ${LD_LIBRARY_PATH} | sed -e "s,^:,,;s,:$,,;s,::\+,:,g"` + LD_LIBRARY_PATH=${my_ld_library_path}:${LD_LIBRARY_PATH} + LD_LIBRARY_PATH=$(echo ${LD_LIBRARY_PATH} | sed -e "s,^:,,;s,:$,,;s,::\+,:,g") export LD_LIBRARY_PATH - PYTHONPATH=${MY_PYTHONPATH}:${PYTHONPATH} - PYTHONPATH=`echo ${PYTHONPATH} | sed -e "s,^:,,;s,:$,,;s,::\+,:,g"` + PYTHONPATH=${my_pythonpath}:${PYTHONPATH} + PYTHONPATH=$(echo ${PYTHONPATH} | sed -e "s,^:,,;s,:$,,;s,::\+,:,g") export PYTHONPATH - LightAppConfig=`echo ${LightAppConfig} | sed -e "s,^:,,;s,:$,,;s,::\+,:,g"` + LightAppConfig=$(echo ${LightAppConfig} | sed -e "s,^:,,;s,:$,,;s,::\+,:,g") export LightAppConfig - SALOMEPATH=`echo ${SALOMEPATH} | sed -e "s,^:,,;s,:$,,;s,::\+,:,g"` + SALOMEPATH=$(echo ${SALOMEPATH} | sed -e "s,^:,,;s,:$,,;s,::\+,:,g") export SALOMEPATH ### # start application ### - suitexe LightApp --modules=`echo $MODULES | tr " " ","` "${RCFILE}" "$@" & + local options="--modules=$(echo ${modules} | tr ' ' ',')" + test "${rcfile}" != "" && options+=" --resources=${rcfile}" + test "${language}" != "" && options+=" --language=${language}" + test "${no_splash}" = "1" && options+=" --no-splash" + test "${debug_exceptions}" = "1" && options+=" --no-exception-handler" + test "${show_license}" = "1" && options+=" --show-license" + suitexe LightApp ${options} "${@}" } ### # call wrapper function (entry point) ### -run_light_salome "$@" \ No newline at end of file +run_light_salome "${@}" diff --git a/src/LightApp/resources/LightApp.xml b/src/LightApp/resources/LightApp.xml index ae448ffb2..3371eec9f 100644 --- a/src/LightApp/resources/LightApp.xml +++ b/src/LightApp/resources/LightApp.xml @@ -57,6 +57,7 @@ +
diff --git a/src/Qtx/Qtx.cxx b/src/Qtx/Qtx.cxx index b2dc37dac..b7a173f37 100644 --- a/src/Qtx/Qtx.cxx +++ b/src/Qtx/Qtx.cxx @@ -1739,9 +1739,14 @@ Qtx::BackgroundData Qtx::stringToBackground( const QString& str ) To use the Localizer class, just create a local variable in the beginning of the code where you need to read / write data from textual file(s). - The constructor of the class forces setting "C" locale temporariy. + The constructor of the class forces setting "C" locale temporarily. The destructor switches back to the initial locale. + There are two ways to create a localizer. + First constructor accepts category and locale value to be forced as parameters. + The second constructor does not take parameters, and is just a shortcut to the + first one, setting LC_NUMERIC as a category and "C" as a locale to force. + \code Qtx::Localizer loc; readSomething(); @@ -1750,12 +1755,30 @@ Qtx::BackgroundData Qtx::stringToBackground( const QString& str ) */ /*! - \brief Constructor. Forces "C" locale to be set. + \brief Default constructor. Forces "C" locale to be set as LC_NUMERIC. */ Qtx::Localizer::Localizer() { - myCurLocale = setlocale( LC_NUMERIC, 0 ); - setlocale( LC_NUMERIC, "C" ); + init( LC_NUMERIC, "C" ); +} + +/*! + \brief Default constructor. Forces "C" locale to be set as LC_NUMERIC. +*/ +Qtx::Localizer::Localizer( int category, const char* locale ) +{ + init( category, locale ); +} + +/*! + \brief Internal initialization + \internal +*/ +void Qtx::Localizer::init( int category, const char* locale ) +{ + myCategory = category; + myOriginalLocale = setlocale( category, NULL ); + setlocale( category, locale ); } /*! @@ -1763,7 +1786,7 @@ Qtx::Localizer::Localizer() */ Qtx::Localizer::~Localizer() { - setlocale( LC_NUMERIC, myCurLocale.toLatin1().constData() ); + setlocale( LC_NUMERIC, myOriginalLocale.toLatin1().constData() ); } /*! diff --git a/src/Qtx/Qtx.h b/src/Qtx/Qtx.h index 042ca830b..5204c09bf 100644 --- a/src/Qtx/Qtx.h +++ b/src/Qtx/Qtx.h @@ -150,9 +150,13 @@ public: { public: Localizer(); + Localizer( int, const char* ); ~Localizer(); private: - QString myCurLocale; + void init( int, const char* ); + private: + int myCategory; + QString myOriginalLocale; }; class QTX_EXPORT CmdLineArgs diff --git a/src/Qtx/QtxResourceMgr.cxx b/src/Qtx/QtxResourceMgr.cxx index e415d024f..82202410d 100644 --- a/src/Qtx/QtxResourceMgr.cxx +++ b/src/Qtx/QtxResourceMgr.cxx @@ -1344,8 +1344,9 @@ void QtxResourceMgr::initialize( const bool autoLoad ) const QtxResourceMgr* that = (QtxResourceMgr*)this; - if ( !userFileName( appName() ).isEmpty() ) - that->myResources.append( new Resources( that, userFileName( appName() ) ) ); + QString userFile = userFileName( appName() ); + if ( !userFile.isEmpty() ) + that->myResources.append( new Resources( that, userFile ) ); that->myHasUserValues = myResources.count() > 0; @@ -2987,7 +2988,7 @@ QString QtxResourceMgr::userFileName( const QString& appName, const bool /*for_l { QString fileName; QString pathName = QDir::homePath(); - QString cfgAppName = QApplication::applicationName(); + QString cfgAppName = QApplication::organizationName(); if ( !cfgAppName.isEmpty() ) pathName = Qtx::addSlash( Qtx::addSlash( pathName ) + QString( ".config" ) ) + cfgAppName; diff --git a/src/SUIT/SUIT_ResourceMgr.cxx b/src/SUIT/SUIT_ResourceMgr.cxx index 2e127d376..6da123a54 100644 --- a/src/SUIT/SUIT_ResourceMgr.cxx +++ b/src/SUIT/SUIT_ResourceMgr.cxx @@ -82,12 +82,11 @@ QString SUIT_ResourceMgr::userFileName( const QString& appName, const bool for_l { QString pathName; - QStringList arguments; - if ( SUIT_Session::session() ) arguments = SUIT_Session::session()->arguments(); // Try config file, given in arguments - for (int i = 1; i < arguments.count(); i++) { + QStringList args = QApplication::arguments(); + for (int i = 1; i < args.count(); i++) { QRegExp rx ("--resources=(.+)"); - if ( rx.indexIn( arguments[i] ) >= 0 && rx.captureCount() > 0 ) { + if ( rx.indexIn( args[i] ) >= 0 && rx.captureCount() > 0 ) { QString file = rx.cap(1); QFileInfo fi (file); pathName = fi.absoluteFilePath(); @@ -185,15 +184,16 @@ long SUIT_ResourceMgr::userFileId( const QString& ) const */ QString SUIT_ResourceMgr::defaultLanguage() const { - QStringList arguments; QString language; - if ( SUIT_Session::session() ) arguments = SUIT_Session::session()->arguments(); + // Try language, given in arguments - for (int i = 1; i < arguments.count(); i++) { + QStringList args = QApplication::arguments(); + for (int i = 1; i < args.count(); i++) { QRegExp rx ("--language=(.+)"); - if ( rx.indexIn( arguments[i] ) >= 0 && rx.captureCount() > 0 ) { + if ( rx.indexIn( args[i] ) >= 0 && rx.captureCount() > 0 ) { language = rx.cap(1); } } + return language; } diff --git a/src/SUIT/SUIT_Session.cxx b/src/SUIT/SUIT_Session.cxx index da453a29a..630d97387 100644 --- a/src/SUIT/SUIT_Session.cxx +++ b/src/SUIT/SUIT_Session.cxx @@ -53,22 +53,6 @@ SUIT_Session::SUIT_Session() mySession = this; } -SUIT_Session::SUIT_Session( int argc, char** argv ) -: QObject(), - myResMgr( 0 ), - myActiveApp( 0 ), - myHandler( 0 ), - myExitStatus( NORMAL ), - myExitFlags ( 0 ) -{ - SUIT_ASSERT( !mySession ) - - mySession = this; - - for ( int i = 0; i < argc; i++ ) - myArguments << QString( argv[i] ); -} - /*!destructor. Clear applications list and set mySession to zero.*/ SUIT_Session::~SUIT_Session() { @@ -85,17 +69,6 @@ SUIT_Session::~SUIT_Session() mySession = 0; } -/*! - Get arguments of the current session - */ -QStringList SUIT_Session::arguments() -{ - QStringList r; - if ( !myArguments.isEmpty() ) r = myArguments; - else if ( QApplication::instance() ) r = QApplication::arguments(); - return r; -} - /*! \retval return mySession */ SUIT_Session* SUIT_Session::session() { diff --git a/src/SUIT/SUIT_Session.h b/src/SUIT/SUIT_Session.h index 643b85931..8e244acfb 100644 --- a/src/SUIT/SUIT_Session.h +++ b/src/SUIT/SUIT_Session.h @@ -64,13 +64,10 @@ public: public: SUIT_Session(); - SUIT_Session( int, char** ); virtual ~SUIT_Session(); static SUIT_Session* session(); - QStringList arguments(); - SUIT_Application* startApplication( const QString&, int = 0, char** = 0 ); QList applications() const; @@ -105,8 +102,6 @@ private: QString applicationName( const QString& ) const; private: - QStringList myArguments; - SUIT_ResourceMgr* myResMgr; AppList myAppList; AppLibMap myAppLibs; diff --git a/src/SUITApp/SUITApp.cxx b/src/SUITApp/SUITApp.cxx index cc8c3cfb6..a2bdfb411 100644 --- a/src/SUITApp/SUITApp.cxx +++ b/src/SUITApp/SUITApp.cxx @@ -20,26 +20,10 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -//#ifdefined WIN32 -//#ifndef DISABLE_PYCONSOLE -//#define DISABLE_PYCONSOLE -//#endif -//#else //#if defined WIN32 -//#ifdef DISABLE_PYCONSOLE -// NOTE: DO NOT DELETE THIS DEFINITION ON LINUX -// or make sure Python is initialized in main() in any case -// Otherwise, application based on light SALOME and using Python -// are unlikely to work properly. -//#undef DISABLE_PYCONSOLE -//#include -//#endif -// #ifndef DISABLE_PYCONSOLE #include "SUITApp_init_python.hxx" #endif -//#endif //#if defined WIN32 - #include "GUI_version.h" #include "SUITApp_Application.h" #include "SUIT_Desktop.h" @@ -60,240 +44,296 @@ #include -#ifdef WIN32 -#include -#endif - -static QString salomeVersion() +namespace { - return GUI_VERSION_STR; -} - -static QString getAppName( const QString& libName ) -{ - QString appName = QFileInfo( libName ).baseName(); - if ( appName.startsWith( "lib" ) ) appName = appName.mid( 3 ); - return appName; -} + //! Get version of SALOME GUI module + static QString salomeVersion() + { + return GUI_VERSION_STR; + } -// static void MessageOutput( QtMsgType type, const char* msg ) -// { -// switch ( type ) -// { -// case QtDebugMsg: -// #ifdef _DEBUG_ -// printf( "Debug: %s\n", msg ); -// #endif -// break; -// case QtWarningMsg: -// #ifdef _DEBUG_ -// printf( "Warning: %s\n", msg ); -// #endif -// break; -// case QtFatalMsg: -// #ifdef _DEBUG_ -// printf( "Fatal: %s\n", msg ); -// #endif -// break; -// default: -// break; -// } -// } - -class SUITApp_Session: public SUIT_Session -{ -public: - SUITApp_Session( bool theIniFormat, int argc, char** argv ) : SUIT_Session( argc, argv ), myIniFormat ( theIniFormat ) {} - virtual ~SUITApp_Session() {} + //! Extract application name from the library filename + static QString getAppName( const QString& libName ) + { + QString appName = QFileInfo( libName ).baseName(); + if ( appName.startsWith( "lib" ) ) + appName = appName.mid( 3 ); + return appName; + } - virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const + //! Custom resources manager, that allows customization of application name/version + // via configuration/translation files. + class ResourceMgr : public SUIT_ResourceMgr { - SUIT_ResourceMgr* resMgr = 0; - if ( myIniFormat ) + public: + ResourceMgr( bool iniFormat = false, const QString& appName = "LightApp" ) + : SUIT_ResourceMgr( appName, "%1Config" ) { - resMgr = new SUIT_ResourceMgr( appName, QString( "%1Config" ) ); - resMgr->setCurrentFormat( "ini" ); + customize( iniFormat, appName ); // activate customization + setCurrentFormat( iniFormat ? "ini" : "xml" ); + setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) ); } - else + + QString customName() const { return myCustomAppName; } + QString version() const { return myCustomAppVersion; } + + private: + static void customize( bool iniFormat, const QString& appName ) { - resMgr = new SUIT_ResourceMgr( appName, QString( "%1Config" ) ); - resMgr->setVersion( salomeVersion() ); - resMgr->setCurrentFormat( "xml" ); + // Try to retrieve actual application name and version from translation files. + // We create temporary resource manager and load translations. + // This procedure is supposed to be done only once, at first call. + if ( myCustomAppName.isNull() ) { + SUIT_ResourceMgr mgr( appName, "%1Config" ); + mgr.setCurrentFormat( iniFormat ? "ini" : "xml" ); + mgr.setWorkingMode( IgnoreUserValues ); // prevent reading data from user's file + mgr.loadLanguage( appName, "en" ); + + // actual application name can be customized via APP_NAME resource key + myCustomAppName = QObject::tr( "APP_NAME" ).trimmed(); + if ( myCustomAppName == "APP_NAME" || myCustomAppName.toLower() == "salome" ) + myCustomAppName = appName; // fallback name + + // actual application name can be customized via APP_VERSION resource key + myCustomAppVersion = QObject::tr( "APP_VERSION" ).trimmed(); + if ( myCustomAppVersion == "APP_VERSION" ) + myCustomAppVersion = myCustomAppName == appName ? salomeVersion() : ""; // fallback version + } } - if ( resMgr ) + protected: + QString userFileName( const QString& appName, const bool forLoad ) const { - resMgr->setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) ); + if ( version().isEmpty() ) return ""; + return SUIT_ResourceMgr::userFileName( myCustomAppName, forLoad ); } - return resMgr; - } -private: - bool myIniFormat; -}; + 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, defaults to LightApp. Can be customized in SALOME-based + // applications, see ResourceMgr above for more details. + // * AppVersion is application version, defaults to current version of SALOME GUI module + // if AppName is not customize, otherwise empty. Can be customized in SALOME-based + // applications, see ResourceMgr above for more details. + // + // Since version 6.5.0 of SALOME, user file is stored 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 stored in the hidden ~/.config/salome directory. However, dot-prefixed + // files are also 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, and ResourceMgr class above in this file. + ////////////////////////////////////////////////////////////////////////////////////////////// + + long id = -1; + if ( !myCustomAppName.isEmpty() ) { +#ifdef WIN32 + // On Windows, user file name is something like LightApp.xml.6.5.0 where + // - LightApp 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( myCustomAppName ).arg( currentFormat() ) ); +#else + // On Linux, user file name is something like LightApprc.6.5.0 where + // - LightApp 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( myCustomAppName ) ); +#endif + QString fname = QFileInfo( _fname ).fileName(); + if ( exp.exactMatch( fname ) ) { + long fid = Qtx::versionToId( exp.cap( 1 ) ); + if ( fid > 0 ) id = fid; + } + } + return id; + } + + private: + static QString myCustomAppName; + static QString myCustomAppVersion; + }; + QString ResourceMgr::myCustomAppName; + QString ResourceMgr::myCustomAppVersion; + + //! Custom session, to use custom resource manager class. + class Session : public SUIT_Session + { + public: + Session( bool theIniFormat = false ) : SUIT_Session(), myIniFormat( theIniFormat ) {} + virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const + { + return new ResourceMgr( myIniFormat, appName ); + } + private: + bool myIniFormat; + }; +} // end of anonymous namespace int main( int argc, char* argv[] ) { - //#ifndef DISABLE_PYCONSOLE - // // First of all initialize Python, as in complex multi-component applications - // // someone else might initialize it some way unsuitable for light SALOME! - // Py_SetProgramName( argv[0] ); - // Py_Initialize(); // Initialize the interpreter - // PySys_SetArgv( argc, argv ); - // PyEval_InitThreads(); // Create (and acquire) the interpreter lock - // PyEval_ReleaseLock(); // Let the others use Python API until we need it again - //#endif - - //qInstallMsgHandler( MessageOutput ); - - QStringList argList; - bool noExceptHandling = false; + // Set-up application settings configuration (as for QSettings) + // Note: these are default settings which can be customized (see below) + QApplication::setOrganizationName( "salome" ); + QApplication::setApplicationName( "salome" ); + QApplication::setApplicationVersion( salomeVersion() ); + + // Add /plugins dir to the pluins search path for image plugins + QString qtdir = Qtx::qtDir( "plugins" ); + if ( !qtdir.isEmpty() ) + QApplication::addLibraryPath( qtdir ); + + // Add application library path (to search style plugin etc...) + QString path = Qtx::addSlash( Qtx::getenv( "GUI_ROOT_DIR" ) ) + "bin/salome"; + QApplication::addLibraryPath( QDir::toNativeSeparators( path ) ); + + // QSurfaceFormat should be set before creation of QApplication, + // so to avoid conflicts beetween SALOME and ParaView QSurfaceFormats we should merge theirs formats + // (see void Qtx::initDefaultSurfaceFormat()) and set the resultant format here. + Qtx::initDefaultSurfaceFormat(); + + // Create Qt application instance: this should be done as early as possible! + // Note: QApplication forces setting locale LC_ALL to system one: setlocale(LC_ALL, ""). + SUITApp_Application app( argc, argv ); + + // Initialize Python (if necessary) + // Note: Python forces setting locale LC_CTYPE to system one: setlocale(LC_CTYPE, ""). +#ifndef DISABLE_PYCONSOLE + char* py_argv[] = {(char*)""}; + SUIT_PYTHON::init_python( 1, py_argv ); +#endif + + // Treat command line arguments + bool debugExceptions = false; bool iniFormat = false; bool noSplash = false; bool useLicense = false; - for ( int i = 1; i < argc; i++ ) + QStringList args; + foreach( QString arg, QApplication::arguments().mid(1) ) // omit 1st argument: app executable { - if ( !strcmp( argv[i], "--noexcepthandling" ) ) - noExceptHandling = true; - else if ( !strcmp( argv[i], "--format=ini") ) + if ( arg == "--no-exception-handler" ) + debugExceptions = true; + else if ( arg == "--format=ini" ) iniFormat = true; - else if ( !strcmp( argv[i], "--nosplash") ) + else if ( arg == "--no-splash" ) noSplash = true; - else if ( !strcmp( argv[i], "--uselicense" ) ) + else if ( arg == "--show-license" ) useLicense = true; - else - argList.append( QString( argv[i] ) ); - } - - // set "C" locale if requested via preferences - { - SUITApp_Session stmp( iniFormat, argc, argv ); - QApplication::setApplicationName( "salome" ); - SUIT_ResourceMgr* resMgr = stmp.createResourceMgr( "LightApp" ); - bool isCloc = resMgr->booleanValue( "language", "locale", true ); - if ( isCloc ) { - QLocale::setDefault( QLocale::c() ); - } - else { - QLocale::setDefault( QLocale::system() ); - } + else if ( !arg.startsWith( "-" ) ) + args << arg; } + if ( args.empty() ) + args << "LightApp"; // fallback application library + QString appName = getAppName( args.first() ); - // RNV: setup the default format: - // QSurfaceFormat should be set before creation of QApplication, - // so to avoid conflicts beetween SALOME and ParaView QSurfaceFormats we should merge theirs formats - // (see void Qtx::initDefaultSurfaceFormat()) and set the resultant format here. - Qtx::initDefaultSurfaceFormat(); + // Create auxiliary resource manager to access application settings + ResourceMgr resMgr( iniFormat, appName ); + resMgr.setWorkingMode( ResourceMgr::IgnoreUserValues ); + resMgr.loadLanguage( appName, "en" ); - // add /plugins directory to the pluins search path for image plugins - QString qtdir = Qtx::qtDir( "plugins" ); - if ( !qtdir.isEmpty() ) - QApplication::addLibraryPath( qtdir ); - - SUITApp_Application app( argc, argv ); - QString cfgAppName = getAppName( argList.isEmpty() ? QString() : argList.first() ); - // hard-coding for LightApp :( no other way to this for the moment - if ( cfgAppName == "LightApp" ) { - app.setOrganizationName( "salome" ); - app.setApplicationName( "salome" ); - app.setApplicationVersion( salomeVersion() ); + // Set-up application settings configuration possible customized via resources + if ( resMgr.customName() != "LightApp" ) { + QApplication::setApplicationName( resMgr.customName() ); + QApplication::setApplicationVersion( resMgr.version() ); } - int result = -1; - + // Force default "C" locale if requested via user's preferences + // Note: this does not change whole application locale (changed via setlocale() function), + // but only affects GUI behavior + resMgr.setWorkingMode( ResourceMgr::AllowUserValues ); // we must take into account user preferences + if ( resMgr.booleanValue( "language", "locale", true ) ) + QLocale::setDefault( QLocale::c() ); + resMgr.setWorkingMode( ResourceMgr::IgnoreUserValues ); + + if ( !debugExceptions ) + debugExceptions = resMgr.booleanValue( "launch", "noexcepthandler", false ); + if ( !noSplash ) + noSplash = !resMgr.booleanValue( "launch", "splash", true ); + if ( !useLicense ) + useLicense = resMgr.booleanValue( "launch", "license", false ); + + // If asked, read the text from a file show a license dialog + // TODO: path to license file, and option to check license, may be defined in XML cfg file. if ( useLicense ) { - QString env; - -#ifdef WIN32 - DWORD aLen=1024; - TCHAR aStr[1024]; - HANDLE aToken=0; - HANDLE hProcess = GetCurrentProcess(); - OpenProcessToken(hProcess,TOKEN_QUERY,&aToken); - if( GetUserProfileDirectory( aToken, aStr, &aLen ) ) { -#ifdef UNICODE - env = QString::fromWCharArray(aStr); -#else - env = aStr; -#endif - } - -#else - if ( ::getenv( "HOME" ) ) - env = ::getenv( "HOME" ); -#endif - - QFile file( env + "/ReadLicense.log" ); // Read the text from a file - if( !file.exists() ) { + QFile file( QDir::home().filePath( "ReadLicense.log" ) ); + if ( !file.exists() ) { SUIT_LicenseDlg aLicense; if ( aLicense.exec() != QDialog::Accepted ) - return result; + return 1; // license is not accepted! } } - if ( !argList.isEmpty() ) + // If not disabled, show splash screen + QtxSplash* splash = 0; + if ( !noSplash ) { - SUITApp_Session aSession( iniFormat, argc, argv ); - QtxSplash* splash = 0; - SUIT_ResourceMgr* resMgr = aSession.createResourceMgr( argList.first() ); - if ( !noSplash ) - { - if ( resMgr ) - { - resMgr->loadLanguage(); - - splash = QtxSplash::splash( QPixmap() ); - splash->readSettings( resMgr ); - if ( splash->pixmap().isNull() ) { - delete splash; - splash = 0; - } - else { - QString appName = QObject::tr( "APP_NAME" ).trimmed(); - QString appVersion = QObject::tr( "APP_VERSION" ).trimmed(); - if ( appVersion == "APP_VERSION" ) - { - if ( appName == "APP_NAME" || appName.toLower() == "salome" ) - appVersion = salomeVersion(); - else - appVersion = ""; - } - splash->setOption( "%A", appName ); - splash->setOption( "%V", QObject::tr( "ABOUT_VERSION" ).arg( appVersion ) ); - splash->setOption( "%L", QObject::tr( "ABOUT_LICENSE" ) ); - splash->setOption( "%C", QObject::tr( "ABOUT_COPYRIGHT" ) ); - splash->show(); - QApplication::instance()->processEvents(); - } - } + splash = QtxSplash::splash( QPixmap() ); + splash->readSettings( &resMgr ); + if ( splash->pixmap().isNull() ) + splash->setPixmap( resMgr.loadPixmap( appName, QObject::tr( "ABOUT_SPLASH" ) ) ); + 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( resMgr.version() ) ); + splash->setOption( "%L", QObject::tr( "ABOUT_LICENSE" ) ); + splash->setOption( "%C", QObject::tr( "ABOUT_COPYRIGHT" ) ); + splash->show(); + QApplication::instance()->processEvents(); } + } -#ifndef DISABLE_PYCONSOLE - //...Initialize python - int _argc = 1; - char* _argv[] = {(char*)""}; - SUIT_PYTHON::init_python(_argc,_argv); -#endif + // Create session + Session session( iniFormat ); - SUIT_Application* theApp = aSession.startApplication( argList.first() ); - if ( theApp ) - { + // Initialize and start application supplied by the library specified via the parameter + SUIT_Application* sessionApp = session.startApplication( appName ); + if ( sessionApp ) + { #ifdef USE_SALOME_STYLE - Style_Salome::initialize( theApp->resourceMgr() ); - if ( theApp->resourceMgr()->booleanValue( "Style", "use_salome_style", true ) ) - Style_Salome::apply(); + Style_Salome::initialize( session->resourceMgr() ); + if ( session->resourceMgr()->booleanValue( "Style", "use_salome_style", true ) ) + Style_Salome::apply(); #endif // USE_SALOME_STYLE - if ( !noExceptHandling ) - app.setHandler( aSession.handler() ); + if ( !debugExceptions ) + app.setHandler( session.handler() ); - if ( splash ) - splash->finish( theApp->desktop() ); + if ( splash ) + splash->finish( sessionApp->desktop() ); - result = app.exec(); - } + return app.exec(); } - return result; + return 1; } diff --git a/src/SalomeApp/SalomeApp_Application.cxx b/src/SalomeApp/SalomeApp_Application.cxx index d24daf374..db4f12447 100644 --- a/src/SalomeApp/SalomeApp_Application.cxx +++ b/src/SalomeApp/SalomeApp_Application.cxx @@ -226,9 +226,10 @@ void SalomeApp_Application::start() QString hdffile; QStringList pyfiles; - for (int i = 1; i < qApp->arguments().size(); i++) { + QStringList args = QApplication::arguments(); + for (int i = 1; i < args.count(); i++) { QRegExp rxs ("--study-hdf=(.+)"); - if ( rxs.indexIn( qApp->arguments()[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) { + if ( rxs.indexIn( args[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) { QString file = rxs.capturedTexts()[1]; QFileInfo fi ( file ); QString extension = fi.suffix().toLower(); @@ -237,7 +238,7 @@ void SalomeApp_Application::start() } else { QRegExp rxp ("--pyscript=\\[(.+)\\]"); - if ( rxp.indexIn( qApp->arguments()[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) { + if ( rxp.indexIn( args[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) { // pyscript QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts); for (int k = 0; k < dictList.count(); ++k) { diff --git a/src/Session/CMakeLists.txt b/src/Session/CMakeLists.txt index 2020450eb..3a7076e3c 100644 --- a/src/Session/CMakeLists.txt +++ b/src/Session/CMakeLists.txt @@ -17,6 +17,8 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # +INCLUDE(UseQtExt) + # --- options --- # additional include directories @@ -81,6 +83,13 @@ SET(SalomeSession_HEADERS Session_Session_i.hxx ) +# --- resources --- + +# resource files / to be processed by lrelease +SET(_ts_RESOURCES + resources/Session_msg_fr.ts +) + # --- sources --- # sources / to compile @@ -102,3 +111,4 @@ TARGET_LINK_LIBRARIES(SALOME_Session_Server ${_link_LIBRARIES} SalomeSession) INSTALL(TARGETS SALOME_Session_Server EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_BINS}) INSTALL(FILES ${SalomeSession_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS}) +QT_INSTALL_TS_RESOURCES("${_ts_RESOURCES}" "${SALOME_GUI_INSTALL_RES_DATA}") diff --git a/src/Session/SALOME_Session_Server.cxx b/src/Session/SALOME_Session_Server.cxx index 28092c9a9..a73426a5d 100644 --- a/src/Session/SALOME_Session_Server.cxx +++ b/src/Session/SALOME_Session_Server.cxx @@ -20,46 +20,38 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// SALOME Session : implementation of Session.idl -// File : SALOME_Session_Server.cxx -// Author : Paul RASCLE, EDF -// Module : SALOME - -#include -#include -#include -#include -#include - +#include // this include must be the first one as it includes Python.h +#include #include -#include - #include +#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 "Session_Session_i.hxx" +#include "Session_ServerCheck.hxx" +#include "Session_ServerLauncher.hxx" +#include "GUI_version.h" +#include "Qtx.h" +#include "QtxMsgHandler.h" +#include "QtxSplash.h" +#include "SALOME_Event.h" #ifdef USE_SALOME_STYLE -#include +#include "Style_Salome.h" #endif // USE_SALOME_STYLE - -#include "GUI_version.h" -#include -#include -#include -#include -#include -#include +#include "SUIT_Application.h" +#include "SUIT_Desktop.h" +#include "SUIT_ExceptionHandler.h" +#include "SUIT_ResourceMgr.h" +#include "SUIT_Session.h" +#include "SUIT_Tools.h" #include #include CORBA_SERVER_HEADER(SALOME_Session) @@ -71,334 +63,374 @@ #include #include #endif - #include +#include #include #include -#include #include -#include #include #include +#include -#include - -/*! - read arguments, define list of server to launch with their arguments. - * - wait for naming service - * - create and run a thread for launch of all servers - * -*/ - -//! CORBA server for SALOME Session +//! CORBA server for SALOME GUI session /*! - * SALOME_Session Server launches a SALOME session servant. + * SALOME_Session_Server launches a SALOME session servant. * The servant registers to the Naming Service. * See SALOME_Session.idl for interface specification. - * * Main services offered by the servant are: * - launch GUI * - stop Session ( must be idle ) * - get session state + * + * Also, session server: + * - reads arguments, + * - defines list of embedded services to launch with their arguments, + * - defines list of standalone services to connect/wait, + * - waits for naming service to finish its initalization, + * - creates and runs a separate thread to launch/initialize all services. */ -class SessionMsgHandler: public QtxMsgHandlerCallback +namespace { -public: - SessionMsgHandler() {} - void qtMessage(QtMsgType type, const QMessageLogContext& context, const QString& message) + std::string handleCorbaException( const CORBA::Exception& e ) { - switch ( type ) + std::string message; + CORBA::Any tmp; + tmp <<= e; + CORBA::TypeCode_var tc = tmp.type(); + message += tc->name(); + return message; + } + + //! Custom handler to manage Qt messages + class MsgHandler: public QtxMsgHandlerCallback + { + public: + MsgHandler() {} + void qtMessage( QtMsgType type, const QMessageLogContext& context, const QString& message ) { - case QtDebugMsg: + switch ( type ) + { + case QtDebugMsg: #ifdef QT_DEBUG_MESSAGE - MESSAGE( "Debug: " << qPrintable( message ) ); + MESSAGE( "Debug: " << qPrintable( message ) ); #endif - break; - case QtWarningMsg: - MESSAGE( "Warning: " << qPrintable( message ) ); - break; - case QtCriticalMsg: - MESSAGE( "Critical: " << qPrintable( message ) ); - break; - case QtFatalMsg: - MESSAGE( "Fatal: " << qPrintable( message ) ); - break; - case QtInfoMsg: - default: - MESSAGE( "Information: " << qPrintable( message ) ); - break; + break; + case QtWarningMsg: + MESSAGE( "Warning: " << qPrintable( message ) ); + break; + case QtCriticalMsg: + MESSAGE( "Critical: " << qPrintable( message ) ); + break; + case QtFatalMsg: + MESSAGE( "Fatal: " << qPrintable( message ) ); + break; + case QtInfoMsg: + default: + MESSAGE( "Information: " << qPrintable( message ) ); + break; + } } - } -}; + }; -QString salomeVersion() -{ - return GUI_VERSION_STR; -} - -class SALOME_ResourceMgr : public SUIT_ResourceMgr -{ -public: - SALOME_ResourceMgr( const QString& app, const QString& resVarTemplate ) : SUIT_ResourceMgr( app, resVarTemplate ) + //! Get version of SALOME GUI module + QString salomeVersion() { - setCurrentFormat( "xml" ); - setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) ); + return GUI_VERSION_STR; } - static void initResourceMgr() + + //! Custom resources manager, that allows customization of application name/version + // via configuration/translation files. + class ResourceMgr : public SUIT_ResourceMgr { - if ( myExtAppName.isNull() || myExtAppVersion.isNull() ) { - SALOME_ResourceMgr resMgr( "SalomeApp", QString( "%1Config" ) ); - resMgr.loadLanguage( "LightApp", "en" ); - resMgr.loadLanguage( "SalomeApp", "en" ); - - 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(); + public: + ResourceMgr( const QString& appName = "SalomeApp" ) : SUIT_ResourceMgr( appName, "%1Config" ) + { + customize(); // activate customization + setCurrentFormat( "xml" ); + setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) ); + } + + QString customName() const { return myCustomAppName; } + QString version() const { return myCustomAppVersion; } + + private: + static void customize() + { + // Try to retrieve actual application name and version from translation files. + // We create temporary resource manager and load LightApp and SalomeApp translations. + // This procedure is supposed to be done only once, at first call. + if ( myCustomAppName.isNull() ) { + SUIT_ResourceMgr mgr( "SalomeApp", "%1Config" ); + mgr.setCurrentFormat( "xml" ); + mgr.setWorkingMode( IgnoreUserValues ); // prevent reading data from user's file + mgr.loadLanguage( "LightApp", "en" ); + mgr.loadLanguage( "SalomeApp", "en" ); + + // actual application name can be customized via APP_NAME resource key + myCustomAppName = QObject::tr( "APP_NAME" ).trimmed(); + if ( myCustomAppName == "APP_NAME" || myCustomAppName.toLower() == "salome" ) + myCustomAppName = "SalomeApp"; // fallback name + + // actual application name can be customized via APP_VERSION resource key + myCustomAppVersion = QObject::tr( "APP_VERSION" ).trimmed(); + if ( myCustomAppVersion == "APP_VERSION" ) + myCustomAppVersion = myCustomAppName == "SalomeApp" ? salomeVersion() : ""; // fallback version } } - } - QString version() const { return myExtAppVersion; } -protected: - QString userFileName( const QString& appName, const bool for_load ) const - { - if ( version().isEmpty() ) return ""; - return SUIT_ResourceMgr::userFileName( myExtAppName, for_load ); - } + protected: + QString userFileName( const QString& appName, const bool forLoad ) const + { + if ( version().isEmpty() ) return ""; + return SUIT_ResourceMgr::userFileName( myCustomAppName, forLoad ); + } - 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() ) { + 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, defaults to SalomeApp. Can be customized in SALOME-based + // applications, see ResourceMgr above for more details. + // * AppVersion is application version, defaults to current version of SALOME GUI module + // if AppName is not customize, otherwise empty. Can be customized in SALOME-based + // applications, see ResourceMgr above for more details. + // + // Since version 6.5.0 of SALOME, user file is stored 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 stored in the hidden ~/.config/salome directory. However, dot-prefixed + // files are also 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, and ResourceMgr class above in this file. + ////////////////////////////////////////////////////////////////////////////////////////////// + + long id = -1; + if ( !myCustomAppName.isEmpty() ) { #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() ) ); + // 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( myCustomAppName ).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 ) ); + // 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( myCustomAppName ) ); #endif - QString fname = QFileInfo( _fname ).fileName(); - if ( exp.exactMatch( fname ) ) { - long fid = Qtx::versionToId( exp.cap( 1 ) ); - if ( fid > 0 ) id = fid; + QString fname = QFileInfo( _fname ).fileName(); + if ( exp.exactMatch( fname ) ) { + long fid = Qtx::versionToId( exp.cap( 1 ) ); + if ( fid > 0 ) id = fid; + } } + return id; } - return id; - } -public: - static QString myExtAppName; - static QString myExtAppVersion; -}; + private: + static QString myCustomAppName; + static QString myCustomAppVersion; + }; + QString ResourceMgr::myCustomAppName; + QString ResourceMgr::myCustomAppVersion; -QString SALOME_ResourceMgr::myExtAppName = QString(); -QString SALOME_ResourceMgr::myExtAppVersion = QString(); - -class SALOME_Session : public SUIT_Session -{ -public: - SALOME_Session( int argc, char** argv ) : SUIT_Session( argc, argv ) {} - virtual ~SALOME_Session() {} - -public: - virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const + //! Custom session, to use custom resource manager class. + class Session : public SUIT_Session { - SALOME_ResourceMgr::initResourceMgr(); - SALOME_ResourceMgr* resMgr = new SALOME_ResourceMgr( appName, QString( "%1Config" ) ); - return resMgr; - } -}; - -class SALOME_QApplication : public QApplication -{ -public: - SALOME_QApplication( int& argc, char** argv ) -// TODO (QT5 PORTING) Below is a temporary solution, to allow compiling with Qt 5 - : QApplication( argc, argv ), - myHandler ( 0 ) {} + public: + virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const + { + return new ResourceMgr( appName ); + } + }; - virtual bool notify( QObject* receiver, QEvent* e ) + //! Custom QApplication class, redefines notify() method, to transfer all events + // via centralized exception handling mechanism. + class Application : public QApplication { - QString debug_exceptions = ::getenv("SALOME_DEBUG_EXCEPTIONS"); - if ( debug_exceptions.length() > 0 ) { - return QApplication::notify( receiver, e ); + public: + Application( int& argc, char** argv ) + : QApplication( argc, argv ), + myHandler ( 0 ) + { + myDebug = !Qtx::getenv( "SALOME_DEBUG_EXCEPTIONS" ).isEmpty(); } - 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; + + virtual bool notify( QObject* receiver, QEvent* e ) + { + if ( myDebug || !myHandler ) { + return QApplication::notify( receiver, e ); } - catch (...) { - std::cerr << "Unknown exception caught in Qt handler: it's probably a bug in SALOME platform" << std::endl; + else { + try { + return myHandler->handle( receiver, e ); + } + catch ( std::exception& e ) { + std::cerr << "notify(): Caught exception : " << e.what() << std::endl; + } + catch ( CORBA::Exception& e ) { + std::cerr << "notify(): Caught CORBA exception : " << handleCorbaException( e ) << std::endl; + } + catch (...) { + std::cerr << "notify(): Caught unknown exception : there's probably a bug in SALOME platform" << std::endl; + } + return false; // return false when exception is caught } - return false; // return false when exception is caught } - } - SUIT_ExceptionHandler* handler() const { return myHandler; } - void setHandler( SUIT_ExceptionHandler* h ) { myHandler = h; } -private: - SUIT_ExceptionHandler* myHandler; -}; + SUIT_ExceptionHandler* handler() const { return myHandler; } + void setHandler( SUIT_ExceptionHandler* h ) { myHandler = h; } -// 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 ) + private: + SUIT_ExceptionHandler* myHandler; + bool myDebug; + }; + + //! 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 { - start(); - } -protected: - virtual void run() + public: + GetInterfaceThread( SALOME::Session_var s ) : session ( s ) + { + start(); + } + + protected: + virtual void run() + { + if ( !CORBA::is_nil( session ) ) + session->GetInterface(); + else + std::cerr << "FATAL ERROR: SALOME::Session object is nil! Cannot display GUI" << std::endl; + } + + private: + SALOME::Session_var session; + }; + + //! Checks command line for presense of given option(s). + // Option that results to \c true is specified via \a trueOption parameter. + // Option that results to \c false is specified via \a falseOption parameter (empty for default). + // Default value for the result (returned if both \a trueOption \a falseOption are not given) is specified via \c defValue parameter. + bool boolCmdOption( const QString trueOption, const QString falseOption = QString(), bool defValue = false ) { - 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; -}; + bool value = defValue; -// 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; -} + QStringList args = QApplication::arguments(); + foreach ( QString arg, args ) + { + if ( arg == trueOption ) + value = true; + else if ( arg == falseOption ) + value = false; + } + return value; + } -void killOmniNames() -{ - SALOME_LifeCycleCORBA::killOmniNames(); -} + // Kill omniNames process + void killOmniNames() + { + SALOME_LifeCycleCORBA::killOmniNames(); + } -// shutdown standalone servers -void shutdownServers( SALOME_NamingService* theNS, bool remoteLauncher ) -{ - SALOME_LifeCycleCORBA lcc(theNS); - lcc.shutdownServers(!remoteLauncher); -} + // Shutdown standalone servers + void shutdownServers( SALOME_NamingService* theNS, bool remoteLauncher ) + { + SALOME_LifeCycleCORBA lcc( theNS ); + lcc.shutdownServers( !remoteLauncher ); + } +} // end of anonymous namespace // ---------------------------- MAIN ----------------------- int main( int argc, char **argv ) { + // Set-up application settings configuration (as for QSettings) + // Note: these are default settings which can be customized (see below) + QApplication::setOrganizationName( "salome" ); + QApplication::setApplicationName( "salome" ); + QApplication::setApplicationVersion( salomeVersion() ); + // Install Qt debug messages handler - SessionMsgHandler msgHandler; - qInstallMessageHandler(QtxMsgHandler); + MsgHandler msgHandler; + qInstallMessageHandler( QtxMsgHandler ); - // add /plugins dir to the pluins search path for image plugins + // Add /plugins dir to the pluins search path for image plugins QString qtdir = Qtx::qtDir( "plugins" ); if ( !qtdir.isEmpty() ) QApplication::addLibraryPath( qtdir ); - - // set "C" locale if requested via preferences - { - SALOME_Session stmp( argc, argv ); - QApplication::setApplicationName( "salome" ); - SUIT_ResourceMgr* resMgr = stmp.createResourceMgr( "SalomeApp" ); - bool isCloc = resMgr->booleanValue( "language", "locale", true ); - if ( isCloc ) { - QLocale::setDefault( QLocale::c() ); - } - else { - QLocale::setDefault( QLocale::system() ); - } - } - - // RNV: setup the default format: + + // Add application library path (to search style plugin etc...) + QString path = SUIT_Tools::addSlash( Qtx::getenv( "GUI_ROOT_DIR" ) ) + "bin/salome"; + QApplication::addLibraryPath( QDir::toNativeSeparators( path ) ); + // QSurfaceFormat should be set before creation of QApplication, // so to avoid conflicts beetween SALOME and ParaView QSurfaceFormats we should merge theirs formats // (see void Qtx::initDefaultSurfaceFormat()) and set the resultant format here. Qtx::initDefaultSurfaceFormat(); + // Create Qt application instance: this should be done as early as possible! + // Note: QApplication forces setting locale LC_ALL to system one: setlocale(LC_ALL, ""). + Application app( argc, argv ); + + // Initialize Python (only once) + // Note: Python forces setting locale LC_CTYPE to system one: setlocale(LC_CTYPE, ""). + char* py_argv[] = {(char*)""}; + KERNEL_PYTHON::init_python( 1, py_argv ); + + // Create auxiliary resource manager to access application settings + ResourceMgr resMgr; + resMgr.setWorkingMode( ResourceMgr::IgnoreUserValues ); + resMgr.loadLanguage( "LightApp", "en" ); + resMgr.loadLanguage( "SalomeApp", "en" ); + resMgr.loadLanguage( "Session" ); + + // Set-up application settings configuration possible customized via resources + if ( resMgr.customName() != "SalomeApp" ) { + QApplication::setApplicationName( resMgr.customName() ); + QApplication::setApplicationVersion( resMgr.version() ); + } - // Create Qt application instance; - // this should be done the very first! - SALOME_QApplication _qappl( argc, argv ); - _qappl.setOrganizationName( "salome" ); - _qappl.setApplicationName( "salome" ); - _qappl.setApplicationVersion( salomeVersion() ); + // Force default "C" locale if requested via user's preferences + // Note: this does not change whole application locale (changed via setlocale() function), + // but only affects GUI behavior + resMgr.setWorkingMode( ResourceMgr::AllowUserValues ); // we must take into account user preferences + if ( resMgr.booleanValue( "language", "locale", true ) ) + QLocale::setDefault( QLocale::c() ); + resMgr.setWorkingMode( ResourceMgr::IgnoreUserValues ); - // Add application library path (to search style plugin etc...) - QString path = QDir::toNativeSeparators( SUIT_Tools::addSlash( QString( Qtx::getenv( "GUI_ROOT_DIR" ) ) ) + QString( "bin/salome" ) ); - _qappl.addLibraryPath( path ); - - 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! + bool isGUI = boolCmdOption( "--show-desktop", "--hide-desktop", true ); // true by default + bool isSplash = boolCmdOption( "--show-splash", "--hide-splash", true ); // true by default + + // Show splash screen (only if both the "GUI" and "SPLASH" options are true) QtxSplash* splash = 0; if ( isGUI && isSplash ) { - // ...create resource manager - SUIT_ResourceMgr resMgr( "SalomeApp", QString( "%1Config" ) ); - resMgr.setCurrentFormat( "xml" ); - resMgr.setWorkingMode( QtxResourceMgr::IgnoreUserValues ); - resMgr.loadLanguage( "LightApp" ); - // splash = QtxSplash::splash( QPixmap() ); splash->readSettings( &resMgr ); if ( splash->pixmap().isNull() ) @@ -409,7 +441,7 @@ int main( int argc, char **argv ) } else { splash->setOption( "%A", QObject::tr( "APP_NAME" ) ); - splash->setOption( "%V", QObject::tr( "ABOUT_VERSION" ).arg( salomeVersion() ) ); + splash->setOption( "%V", QObject::tr( "ABOUT_VERSION" ).arg( resMgr.version() ) ); splash->setOption( "%L", QObject::tr( "ABOUT_LICENSE" ) ); splash->setOption( "%C", QObject::tr( "ABOUT_COPYRIGHT" ) ); splash->show(); @@ -417,7 +449,6 @@ int main( int argc, char **argv ) } } - // Initialization int result = -1; @@ -436,11 +467,6 @@ int main( int argc, char **argv ) bool remoteLauncher = false; try { - // ...initialize Python (only once) - int _argc = 1; - char* _argv[] = {(char*)""}; - KERNEL_PYTHON::init_python( _argc,_argv ); - // ...create ORB, get RootPOA object, NamingService, etc. ORB_INIT &init = *SINGLETON_::Instance(); ASSERT( SINGLETON_::IsAlreadyExisting() ); @@ -456,31 +482,26 @@ int main( int argc, char **argv ) PortableServer::POAManager_var pman = poa->the_POAManager(); pman->activate() ; - MESSAGE( "pman->activate()" ); + MESSAGE( "POA manager activated" ); _NS = new SALOME_NamingService( orb ); result = 0; } catch ( SALOME_Exception& e ) { - INFOS( "run(): SALOME::SALOME_Exception is caught: "<name(); - INFOS ( "run(): CORBA exception of the kind : "<setStatus( QApplication::translate( "", "Activating desktop..." ) ); + splash->setStatus( QObject::tr( "Activating desktop..." ) ); // ...create GUI launcher MESSAGE( "Session activated, Launch IAPP..." ); guiThread = new GetInterfaceThread( session ); @@ -587,7 +611,7 @@ int main( int argc, char **argv ) } // SUIT_Session creation - aGUISession = new SALOME_Session( argc, argv ); + aGUISession = new Session(); // Load SalomeApp dynamic library MESSAGE( "creation SUIT_Application" ); @@ -600,23 +624,24 @@ int main( int argc, char **argv ) Style_Salome::apply(); #endif // USE_SALOME_STYLE - if ( !isFound( "noexcepthandler", argc, argv ) ) - _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application - // aGUISession contains SalomeApp_ExceptionHandler + if ( !debugExceptions ) + app.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(); - + result = app.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 + // 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 { @@ -639,7 +664,7 @@ int main( int argc, char **argv ) delete aGUISession; aGUISession = 0; - + // Prepare _GUIMutex for a new GUI activation _SessionMutex.lock(); } @@ -647,18 +672,22 @@ int main( int argc, char **argv ) // unlock Session mutex _SessionMutex.unlock(); - + + // Shutdown embedded servers if ( myServerLauncher ) - myServerLauncher->ShutdownAll(); // shutdown embedded servers + myServerLauncher->ShutdownAll(); - if ( shutdownAll ) // shutdown standalone servers + // Shutdown standalone servers + if ( shutdownAll ) shutdownServers( _NS, remoteLauncher ); + // Kill embedded servers if ( myServerLauncher ) - myServerLauncher->KillAll(); // kill embedded servers + myServerLauncher->KillAll(); // Unregister session server - SALOME_Session_i* sessionServant = dynamic_cast( poa->reference_to_servant( session.in() ) ); + SALOME_Session_i* sessionServant = + dynamic_cast( poa->reference_to_servant( session.in() ) ); if ( sessionServant ) sessionServant->NSunregister(); @@ -670,7 +699,7 @@ int main( int argc, char **argv ) delete[] new_argv; #endif - try { + try { orb->shutdown(0); } catch (...) { @@ -680,40 +709,29 @@ int main( int argc, char **argv ) // 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 } - //Destroy orb from python (for chasing msrc/Session/SALOME_Session_Server.cxxemory leaks) - //PyRun_SimpleString("from omniORB import CORBA"); - //PyRun_SimpleString("orb=CORBA.ORB_init([''], CORBA.ORB_ID)"); - //PyRun_SimpleString("orb.destroy()"); - - // Destroy the ORB: + // Destroy ORB sleep(2); - //std::cout << "@@@@@ Explicitely destroying the ORB (hoping to kill omniORB threads ...)\n"; - ORB_INIT * init = SINGLETON_::Instance(); - if (init) + ORB_INIT* init = SINGLETON_::Instance(); + if ( init ) init->explicit_destroy(); - //std::cout << "@@@@@ ORB destroyed\n"; - // After ORB destruction - if(Py_IsInitialized()) - { - PyGILState_Ensure(); - //std::cout << "@@@@@ About to PyFinalize\n"; - Py_Finalize(); - //std::cout << "@@@@@ DONE PyFinalize\n"; - } + // Finalize Python + if ( Py_IsInitialized() ) + { + PyGILState_Ensure(); + Py_Finalize(); + } + // Kill omniNames process if ( shutdownAll ) - { - //std::cout << "@@@@@ About to kill omni\n"; - killOmniNames(); - //std::cout << "@@@@@ DONE kill omni\n"; - } + { + killOmniNames(); + } MESSAGE( "Salome_Session_Server:endofserver" ); return result; diff --git a/src/Session/Session_ServerCheck.cxx b/src/Session/Session_ServerCheck.cxx index a819caf71..502458918 100644 --- a/src/Session/Session_ServerCheck.cxx +++ b/src/Session/Session_ServerCheck.cxx @@ -288,11 +288,13 @@ void Session_ServerCheck::run() } if ( i == myAttempts-1 ) { - setError( tr( "Unable to contact the naming service.\n" ) ); + setError( tr( "Unable to contact the naming service." ) + "\n" ); return; } } + QString errfmt = "\n%1"; + // 2. Check registry server for ( int i = 0; i < myAttempts ; i++ ) { Locker locker( this ); @@ -337,7 +339,7 @@ void Session_ServerCheck::run() } if ( i == myAttempts-1 ) { - setError( tr( "Registry server is not found.\n%1" ).arg ( error ) ); + setError( tr( "Registry server is not found." ) + errfmt.arg( error ) ); return; } } @@ -386,7 +388,7 @@ void Session_ServerCheck::run() } if ( i == myAttempts-1 ) { - setError( tr( "Study server is not found.\n%1" ).arg ( error ) ); + setError( tr( "Study server is not found." ) + errfmt.arg( error ) ); return; } } @@ -435,7 +437,7 @@ void Session_ServerCheck::run() } if ( i == myAttempts-1 ) { - setError( tr( "Module catalogue server is not found.\n%1" ).arg ( error ) ); + setError( tr( "Module catalogue server is not found." ) + errfmt.arg( error ) ); return; } } @@ -484,7 +486,7 @@ void Session_ServerCheck::run() } if ( i == myAttempts-1 ) { - setError( tr( "Session server is not found.\n%1" ).arg ( error ) ); + setError( tr( "Session server is not found." ) + errfmt.arg( error ) ); return; } } @@ -535,7 +537,7 @@ void Session_ServerCheck::run() } if ( i == myAttempts-1 ) { - setError( tr( "C++ container is not found.\n%1" ).arg ( error ) ); + setError( tr( "C++ container is not found." ) + errfmt.arg( error ) ); return; } } @@ -587,7 +589,7 @@ void Session_ServerCheck::run() } if ( i == myAttempts-1 ) { - setError( tr( "Python container is not found.\n%1" ).arg ( error ) ); + setError( tr( "Python container is not found." ) + errfmt.arg( error ) ); return; } } @@ -639,7 +641,7 @@ void Session_ServerCheck::run() } if ( i == myAttempts-1 ) { - setError( tr( "Supervision container is not found.\n%1" ).arg ( error ) ); + setError( tr( "Supervision container is not found." ) + errfmt.arg( error ) ); return; } } diff --git a/src/Session/resources/Session_msg_fr.ts b/src/Session/resources/Session_msg_fr.ts new file mode 100644 index 000000000..5fad5eb5c --- /dev/null +++ b/src/Session/resources/Session_msg_fr.ts @@ -0,0 +1,75 @@ + + + + + @default + + Waiting for naming service... + En attente du service de nommage... + + + Waiting for registry server... + En attente du serveur de registre... + + + Waiting for study server... + En attente du serveur d'étude... + + + Waiting for module catalogue server... + En attente du serveur de catalogue de modules... + + + Waiting for session server... + En attente du serveur de session... + + + Waiting for C++ container... + En attente du conteneur C++... + + + Waiting for Python container... + En attente du conteneur Python... + + + Waiting for Supervision container... + En attente du conteneur Supervision... + + + Unable to contact the naming service. + Impossible de contacter le service de nommage. + + + Registry server is not found. + Le serveur de registre est introuvable. + + + Study server is not found. + Le serveur d'étude est introuvable. + + + Module catalogue server is not found. + Le serveur de catalogue de modules est introuvable. + + + Session server is not found. + Le serveur de session est introuvable. + + + C++ container is not found. + Le conteneur C++ est introuvable. + + + Python container is not found. + Le conteneur Python est introuvable. + + + Supervision container is not found. + Le conteneur Supervision est introuvable. + + + Activating desktop... + Activation de la fenêtre principale... + + + -- 2.39.2