1 // Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include <ArgvKeeper.hxx>
24 #include <Container_init_python.hxx> // this include must be the first one as it includes Python.h
25 #include <Basics_Utils.hxx>
27 #include <RegistryService.hxx>
28 #include <SALOME_LifeCycleCORBA.hxx>
29 #include <SALOME_ModuleCatalog_impl.hxx>
30 #include <SALOME_NamingService.hxx>
31 #include <Utils_CorbaException.hxx>
32 #include <Utils_ORB_INIT.hxx>
33 #include <Utils_SALOME_Exception.hxx>
34 #include <Utils_SINGLETON.hxx>
35 #include <utilities.h>
36 #include "KernelBasis.hxx"
38 #include "Session_Session_i.hxx"
39 #include "Session_ServerCheck.hxx"
40 #include "Session_ServerLauncher.hxx"
41 #include "Session_Promises.hxx"
42 #include "Session_NS_wrapper.hxx"
44 #include "GUI_version.h"
46 #include "QtxMsgHandler.h"
47 #include "QtxSplash.h"
48 #include "SALOME_Event.h"
49 #ifdef USE_SALOME_STYLE
50 #include "Style_Salome.h"
51 #endif // USE_SALOME_STYLE
52 #include "SUIT_Application.h"
53 #include "SUIT_Desktop.h"
54 #include "SUIT_ExceptionHandler.h"
55 #include "SUIT_ResourceMgr.h"
56 #include "SUIT_Session.h"
57 #include "SUIT_Tools.h"
59 #include <SALOMEconfig.h>
60 #include CORBA_SERVER_HEADER(SALOME_Session)
61 #include CORBA_SERVER_HEADER(SALOMEDS)
69 #include <QStyleFactory>
74 #include <QApplication>
79 #include <QTextStream>
80 #include <QWaitCondition>
84 // For DWORD (see end of file)
86 // Force high-performance graphics on dual-GPU systems
87 // http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf
88 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
89 // https://community.amd.com/thread/169965
90 __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
94 //! CORBA server for SALOME GUI session
96 * SALOME_Session_Server launches a SALOME session servant.
97 * The servant registers to the Naming Service.
98 * See SALOME_Session.idl for interface specification.
99 * Main services offered by the servant are:
101 * - stop Session ( must be idle )
102 * - get session state
104 * Also, session server:
106 * - defines list of embedded services to launch with their arguments,
107 * - defines list of standalone services to connect/wait,
108 * - waits for naming service to finish its initalization,
109 * - creates and runs a separate thread to launch/initialize all services.
114 std::string handleCorbaException(const CORBA::Exception &e)
119 CORBA::TypeCode_var tc = tmp.type();
120 message += tc->name();
124 //! Custom handler to manage Qt messages
125 class MsgHandler : public QtxMsgHandlerCallback
129 void qtMessage(QtMsgType type, const QMessageLogContext & /*context*/, const QString &message)
131 (void)message; // unused in debug mode
135 #ifdef QT_DEBUG_MESSAGE
136 MESSAGE("Debug: " << qPrintable(message));
140 MESSAGE("Warning: " << qPrintable(message));
143 MESSAGE("Critical: " << qPrintable(message));
146 MESSAGE("Fatal: " << qPrintable(message));
150 MESSAGE("Information: " << qPrintable(message));
156 //! Get version of SALOME GUI module
157 QString salomeVersion()
159 return GUI_VERSION_STR;
162 //! Custom resources manager, that allows customization of application name/version
163 // via configuration/translation files.
164 class ResourceMgr : public SUIT_ResourceMgr
167 ResourceMgr(const QString &appName = "SalomeApp") : SUIT_ResourceMgr(appName, "%1Config")
169 customize(); // activate customization
170 setCurrentFormat("xml");
171 setOption("translators", QString("%P_msg_%L.qm|%P_icons.qm|%P_images.qm"));
174 QString customName() const { return myCustomAppName; }
175 QString version() const { return myCustomAppVersion; }
178 static void customize()
180 // Try to retrieve actual application name and version from translation files.
181 // We create temporary resource manager and load LightApp and SalomeApp translations.
182 // This procedure is supposed to be done only once, at first call.
183 if (myCustomAppName.isNull())
185 SUIT_ResourceMgr mgr("SalomeApp", "%1Config");
186 mgr.setCurrentFormat("xml");
187 mgr.setWorkingMode(IgnoreUserValues); // prevent reading data from user's file
188 mgr.loadLanguage("LightApp", "en");
189 mgr.loadLanguage("SalomeApp", "en");
191 // actual application name can be customized via APP_NAME resource key
192 myCustomAppName = QObject::tr("APP_NAME").trimmed();
193 if (myCustomAppName == "APP_NAME" || myCustomAppName.toLower() == "salome")
194 myCustomAppName = "SalomeApp"; // fallback name
196 // actual application name can be customized via APP_VERSION resource key
197 myCustomAppVersion = QObject::tr("APP_VERSION").trimmed();
198 if (myCustomAppVersion == "APP_VERSION")
199 myCustomAppVersion = myCustomAppName == "SalomeApp" ? salomeVersion() : ""; // fallback version
204 QString userFileName(const QString & /*appName*/, const bool forLoad) const
206 if (version().isEmpty())
208 return SUIT_ResourceMgr::userFileName(myCustomAppName, forLoad);
211 virtual long userFileId(const QString &_fname) const
213 //////////////////////////////////////////////////////////////////////////////////////////////
214 // In SALOME and SALOME-based applications the user preferences file is named as
215 // - <AppName>.xml.<AppVersion> on Windows
216 // - <AppName>rc.<AppVersion> on Linux
218 // * AppName is application name, defaults to SalomeApp. Can be customized in SALOME-based
219 // applications, see ResourceMgr above for more details.
220 // * AppVersion is application version, defaults to current version of SALOME GUI module
221 // if AppName is not customize, otherwise empty. Can be customized in SALOME-based
222 // applications, see ResourceMgr above for more details.
224 // Since version 6.5.0 of SALOME, user file is stored in the ~/.config/salome
225 // directory. For backward compatibility, when user preferences from nearest
226 // version of application is searched, user home directory is also looked through,
227 // with lower priority.
229 // Since version 6.6.0 of SALOME, user file name on Linux is no more prefixed by dot
230 // symbol since it is stored in the hidden ~/.config/salome directory. However, dot-prefixed
231 // files are also taken into account (with lower priority) for backward compatibility.
234 // - Currently the following format of version number is supported:
235 // <major>[.<minor>[.<release>[<type><dev>]]]
236 // Parts in square brackets are considered optional. Here:
237 // * major - major version id
238 // * minor - minor version id
239 // * release - maintenance version id
240 // * type - dev or patch marker; it can be either one alphabetical symbol (from 'a' to 'z')
241 // or 'rc' to point release candidate (case-insensitive)
242 // * dev - dev version or patch number
243 // All numerical values must be of range [1-99].
244 // Examples: 1.0, 6.5.0, 1.2.0a1, 3.3.3rc3 (release candidate 3), 11.0.0p1 (patch 1)
246 // - Versioning approach can be customized by implementing and using own resource manager class,
247 // see QtxResurceMgr, SUIT_ResourceMgr classes, and ResourceMgr class above in this file.
248 //////////////////////////////////////////////////////////////////////////////////////////////
251 if (!myCustomAppName.isEmpty())
254 // On Windows, user file name is something like SalomeApp.xml.6.5.0 where
255 // - SalomeApp is an application name (can be customized)
256 // - xml is a file format (xml or ini)
257 // - 6.5.0 is an application version, can include alfa/beta/rc marks, e.g. 6.5.0a3, 6.5.0rc1
258 QRegExp exp(QString("%1\\.%2\\.([a-zA-Z0-9.]+)").arg(myCustomAppName).arg(currentFormat()));
260 // On Linux, user file name is something like SalomeApprc.6.5.0 where
261 // - SalomeApp is an application name (can be customized)
262 // - 6.5.0 is an application version, can include alfa/beta/rc marks, e.g. 6.5.0a3, 6.5.0rc1
264 // VSR 24/09/2012: issue 0021781: since version 6.6.0 user filename is not prepended with "."
265 // when it is stored in the ~/.config/<appname> directory;
266 // for backward compatibility we also check files prepended with "." with lower priority
267 QRegExp exp(QString("\\.?%1rc\\.([a-zA-Z0-9.]+)").arg(myCustomAppName));
269 QString fname = QFileInfo(_fname).fileName();
270 if (exp.exactMatch(fname))
272 long fid = Qtx::versionToId(exp.cap(1));
281 static QString myCustomAppName;
282 static QString myCustomAppVersion;
284 QString ResourceMgr::myCustomAppName;
285 QString ResourceMgr::myCustomAppVersion;
287 //! Custom session, to use custom resource manager class.
288 class Session : public SUIT_Session
291 virtual SUIT_ResourceMgr *createResourceMgr(const QString &appName) const
293 return new ResourceMgr(appName);
297 //! Custom QApplication class, redefines notify() method, to transfer all events
298 // via centralized exception handling mechanism.
299 class Application : public QApplication
302 Application(int &argc, char **argv)
303 : QApplication(argc, argv),
306 myDebug = !Qtx::getenv("SALOME_DEBUG_EXCEPTIONS").isEmpty();
309 virtual bool notify(QObject *receiver, QEvent *e)
311 if (myDebug || !myHandler)
313 return QApplication::notify(receiver, e);
319 return myHandler->handle(receiver, e);
321 catch (std::exception &e)
323 std::cerr << "notify(): Caught exception : " << e.what() << std::endl;
325 catch (CORBA::Exception &e)
327 std::cerr << "notify(): Caught CORBA exception : " << handleCorbaException(e) << std::endl;
331 std::cerr << "notify(): Caught unknown exception : there's probably a bug in SALOME platform" << std::endl;
333 return false; // return false when exception is caught
337 SUIT_ExceptionHandler *handler() const { return myHandler; }
338 void setHandler(SUIT_ExceptionHandler *h) { myHandler = h; }
341 SUIT_ExceptionHandler *myHandler;
345 //! Class which calls SALOME::Session::GetInterface() from another thread
346 // to avoid mutual lock if called from the same thread as main()
347 class GetInterfaceThread : public QThread
350 GetInterfaceThread(SALOME::Session_var s) : session(s)
358 if (!CORBA::is_nil(session))
359 session->GetInterface();
361 std::cerr << "FATAL ERROR: SALOME::Session object is nil! Cannot display GUI" << std::endl;
365 SALOME::Session_var session;
368 //! Checks command line for presense of given option(s).
369 // Option that results to \c true is specified via \a trueOption parameter.
370 // Option that results to \c false is specified via \a falseOption parameter (empty for default).
371 // Default value for the result (returned if both \a trueOption \a falseOption are not given) is specified via \c defValue parameter.
372 bool boolCmdOption(const QString trueOption, const QString falseOption = QString(), bool defValue = false)
374 bool value = defValue;
376 QStringList args = QApplication::arguments();
377 foreach (QString arg, args)
379 if (arg == trueOption)
381 else if (arg == falseOption)
387 // Shutdown standalone servers
388 void shutdownServers(SALOME_NamingService *theNS, bool remoteLauncher)
390 SALOME_LifeCycleCORBA lcc(theNS);
391 lcc.shutdownServers(!remoteLauncher);
393 } // end of anonymous namespace
395 template<class GUI_APP_STYLE>
396 int AbstractGUIAppMain(int argc, char **argv);
401 static constexpr bool SSL_MODE = false;
402 using NamingServiceImplementation = OldStyleNS;
403 void connectToNSIfNeeded(CORBA::ORB_ptr orb) { _NS.reset(new SALOME_NamingService(orb)); }
404 void shutdownCORBAStufIfNeeded(bool shutdownAll, CORBA::ORB_ptr orb);
405 void killOtherServersIfNeeded() { SALOME_LifeCycleCORBA::killOmniNames(); }
406 SALOME::Session_var getSession();
407 void shutdownRemoteServersIfNeeded(bool remoteLauncher);
409 std::unique_ptr<SALOME_NamingService> _NS;
415 static constexpr bool SSL_MODE = true;
416 using NamingServiceImplementation = NewStyleNS;
417 void connectToNSIfNeeded(CORBA::ORB_ptr orb) { /*! nothing */ }
418 void shutdownCORBAStufIfNeeded(bool shutdownAll, CORBA::ORB_ptr orb) { /*! nothing */ }
419 void killOtherServersIfNeeded() { /*! nothing */ }
420 SALOME::Session_var getSession();
421 void shutdownRemoteServersIfNeeded(bool remoteLauncher) { /*! nothing */ }
424 void GUIAppOldStyle::shutdownCORBAStufIfNeeded(bool shutdownAll, CORBA::ORB_ptr orb)
432 //////////////////////////////////////////////////////////////
433 // VSR: silently skip exception:
434 // CORBA.BAD_INV_ORDER.BAD_INV_ORDER_ORBHasShutdown
435 // exception is raised when orb->destroy() is called and
436 // cpp continer is launched in the embedded mode
437 //////////////////////////////////////////////////////////////
439 SALOME_LifeCycleCORBA::killOmniNames();
440 abort(); //abort program to avoid deadlock in destructors or atexit when shutdown has been interrupted
444 ORB_INIT *init = SINGLETON_<ORB_INIT>::Instance();
446 init->explicit_destroy();
449 SALOME::Session_var GUIAppOldStyle::getSession()
451 CORBA::Object_var obj = _NS->Resolve("/Kernel/Session");
452 SALOME::Session_var session = SALOME::Session::_narrow(obj);
455 void GUIAppOldStyle::shutdownRemoteServersIfNeeded(bool remoteLauncher)
457 shutdownServers(_NS.get(), remoteLauncher);
460 SALOME::Session_var GUIAppNewStyle::getSession()
462 SALOME::Session_var session = GetSessionRefSingleton()->get_future().get();
466 // ---------------------------- MAIN -----------------------
467 template<class GUI_APP_STYLE>
468 int AbstractGUIAppMain(int argc, char **argv)
470 using NamingServiceImplementation = typename GUI_APP_STYLE::NamingServiceImplementation;
471 setSSLMode(GUI_APP_STYLE::SSL_MODE);
474 // Set-up application settings configuration (as for QSettings)
475 // Note: these are default settings which can be customized (see below)
476 QApplication::setOrganizationName("salome");
477 QApplication::setApplicationName("salome");
478 QApplication::setApplicationVersion(salomeVersion());
481 MESSAGE("Set QApplication attributes to supports HDPI...");
483 // Make QIcon::pixmap() generate high-dpi pixmaps that can be larger than the requested size.
484 // Such pixmaps will have devicePixelRatio() set to a value higher than 1.
485 // After setting this attribute, application code that uses pixmap sizes in layout geometry calculations
486 // should typically divide by devicePixelRatio() to get device-independent layout geometry.
487 QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
489 // The lines below do the same - enables automatic scaling, based on the monitor's pixel density.
490 // This won't change the size of point-sized fonts, since point is a physical measurement unit.
491 // Using them can make an impression of large icons among small fonts.
492 // qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
493 // QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // Doesn't scale fonts
495 // Keep this line as an example of using explicit scale factor.
496 // Defines a global scale factor for the whole application, including point-sized fonts.
497 // qputenv("QT_SCALE_FACTOR", "1.5"); // Scales everything
499 // Install Qt debug messages handler
500 MsgHandler msgHandler;
501 qInstallMessageHandler(QtxMsgHandler);
503 // Add <qtdir>/plugins dir to the pluins search path for image plugins
504 QString qtdir = Qtx::qtDir("plugins");
505 if (!qtdir.isEmpty())
506 QApplication::addLibraryPath(qtdir);
508 // Add application library path (to search style plugin etc...)
509 QString path = SUIT_Tools::addSlash(Qtx::getenv("GUI_ROOT_DIR")) + "bin/salome";
510 QApplication::addLibraryPath(QDir::toNativeSeparators(path));
512 // QSurfaceFormat should be set before creation of QApplication,
513 // so to avoid conflicts beetween SALOME and ParaView QSurfaceFormats we should merge theirs formats
514 // (see void Qtx::initDefaultSurfaceFormat()) and set the resultant format here.
515 Qtx::initDefaultSurfaceFormat();
517 // Create Qt application instance: this should be done as early as possible!
518 // Note: QApplication forces setting locale LC_ALL to system one: setlocale(LC_ALL, "").
519 SetArgcArgv(argc,argv);
520 Application app(argc, argv);
523 QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
524 QSettings::NativeFormat);
525 if(settings.value("AppsUseLightTheme")==0){
526 app.setStyle(QStyleFactory::create("Fusion"));
527 QPalette darkPalette;
528 QColor darkColor = QColor(45,45,45);
529 QColor disabledColor = QColor(127,127,127);
530 darkPalette.setColor(QPalette::Window, darkColor);
531 darkPalette.setColor(QPalette::WindowText, Qt::white);
532 darkPalette.setColor(QPalette::Base, QColor(18,18,18));
533 darkPalette.setColor(QPalette::AlternateBase, darkColor);
534 darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
535 darkPalette.setColor(QPalette::ToolTipText, Qt::white);
536 darkPalette.setColor(QPalette::Text, Qt::white);
537 darkPalette.setColor(QPalette::Disabled, QPalette::Text, disabledColor);
538 darkPalette.setColor(QPalette::Button, darkColor);
539 darkPalette.setColor(QPalette::ButtonText, Qt::white);
540 darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, disabledColor);
541 darkPalette.setColor(QPalette::BrightText, Qt::red);
542 darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
543 darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
544 darkPalette.setColor(QPalette::HighlightedText, Qt::black);
545 darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, disabledColor);
546 darkPalette.setColor(QPalette::PlaceholderText, Qt::white);
547 darkPalette.setColor(QPalette::NoRole, Qt::white);
549 app.setPalette(darkPalette);
550 app.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
553 // Initialize Python (only once)
554 // Note: Python forces setting locale LC_CTYPE to system one: setlocale(LC_CTYPE, "").
555 char *py_argv[] = {(char *)""};
556 KERNEL_PYTHON::init_python(1, py_argv);
558 // Create auxiliary resource manager to access application settings
560 resMgr.setWorkingMode(ResourceMgr::IgnoreUserValues);
561 resMgr.loadLanguage("LightApp", "en");
562 resMgr.loadLanguage("SalomeApp", "en");
563 resMgr.loadLanguage("Session");
565 // Set-up application settings configuration possible customized via resources
566 if (resMgr.customName() != "SalomeApp")
568 QApplication::setApplicationName(resMgr.customName());
569 QApplication::setApplicationVersion(resMgr.version());
572 // Force default "C" locale if requested via user's preferences
573 // Note: this does not change whole application locale (changed via setlocale() function),
574 // but only affects GUI behavior
575 resMgr.setWorkingMode(ResourceMgr::AllowUserValues); // we must take into account user preferences
576 if (resMgr.booleanValue("language", "locale", true))
577 QLocale::setDefault(QLocale::c());
578 resMgr.setWorkingMode(ResourceMgr::IgnoreUserValues);
580 #if defined(GLOBAL_DOUBLE_CONVERSION)
581 // VSR 30/03/2021: moved here from QtxDoubleSpinBox/QtxIntSpinBox because of crash on Qt 5.12.
582 // Disable thousands separator for spin box
583 // see issue 14540 (old id 21219)
585 locale.setNumberOptions(locale.numberOptions() | QLocale::OmitGroupSeparator | QLocale::RejectGroupSeparator);
586 QLocale::setDefault(locale);
589 bool isGUI = boolCmdOption("--show-desktop", "--hide-desktop", true); // true by default
590 bool isSplash = boolCmdOption("--show-splash", "--hide-splash", true); // true by default
592 // Show splash screen (only if both the "GUI" and "SPLASH" options are true)
593 QtxSplash *splash = 0;
594 if (isGUI && isSplash)
596 splash = QtxSplash::splash(QPixmap());
597 splash->readSettings(&resMgr);
598 if (splash->pixmap().isNull())
599 splash->setPixmap(resMgr.loadPixmap("LightApp", QObject::tr("ABOUT_SPLASH")));
600 if (splash->pixmap().isNull())
607 splash->setOption("%A", QObject::tr("APP_NAME"));
608 splash->setOption("%V", QObject::tr("ABOUT_VERSION").arg(resMgr.version()));
609 splash->setOption("%L", QObject::tr("ABOUT_LICENSE"));
610 splash->setOption("%C", QObject::tr("ABOUT_COPYRIGHT"));
612 QApplication::instance()->processEvents();
620 PortableServer::POA_var poa;
622 SUIT_Session *aGUISession = 0;
623 GetInterfaceThread *guiThread = 0;
624 Session_ServerLauncher<NamingServiceImplementation> *myServerLauncher = nullptr;
626 #if defined(WIN32) && defined(UNICODE)
627 char **new_argv = NULL;
630 bool remoteLauncher = false;
634 // ...create ORB, get RootPOA object, NamingService, etc.
636 if (std::string(argv[1]).find("-ORBInitRef") != std::string::npos)
639 remoteLauncher = true;
641 SetArgcArgv(orbArgc, argv);
642 orb = KERNEL::GetRefToORB();
644 CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
645 poa = PortableServer::POA::_narrow(obj);
647 PortableServer::POAManager_var pman = poa->the_POAManager();
649 MESSAGE("POA manager activated");
651 self.connectToNSIfNeeded(orb);
655 catch (SALOME_Exception &e)
657 INFOS("run(): Caught SALOME_Exception : " << e.what());
659 catch (CORBA::SystemException &e)
661 INFOS("run(): Caught CORBA::SystemException : " << handleCorbaException(e));
663 catch (CORBA::Exception &e)
665 INFOS("run(): Caught CORBA::Exception : " << handleCorbaException(e));
667 catch (std::exception &e)
669 INFOS("run(): Caught exception : " << e.what());
673 INFOS("run(): Caught unknown exception");
676 QMutex _GUIMutex, _SessionMutex, _SplashMutex;
677 QWaitCondition _ServerLaunch, _SessionStarted, _SplashStarted;
679 // lock session mutex to ensure that GetInterface is not called
680 // until all initialization is done
681 _SessionMutex.lock();
685 // Start embedded servers launcher (Registry, SALOMEDS, etc.)
686 // ...lock mutex to block embedded servers launching thread until wait( mutex )
688 // ...create launcher
689 #if defined(WIN32) && defined(UNICODE)
690 LPWSTR *szArglist = NULL;
693 szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
694 new_argv = new char *[nArgs];
695 for (i = 0; i < nArgs; i++)
697 new_argv[i] = (char *)Kernel_Utils::utf8_encode(szArglist[i]);
699 // Free memory allocated for CommandLineToArgvW arguments.
700 LocalFree(szArglist);
701 myServerLauncher = new Session_ServerLauncher<NamingServiceImplementation>(nArgs, new_argv, orb, poa, &_GUIMutex, &_ServerLaunch, &_SessionMutex, &_SessionStarted);
703 myServerLauncher = new Session_ServerLauncher<NamingServiceImplementation>(argc, argv, orb, poa, &_GUIMutex, &_ServerLaunch, &_SessionMutex, &_SessionStarted);
705 // ...block this thread until launcher is ready
706 _ServerLaunch.wait(&_GUIMutex);
708 // Start servers check thread (splash)
711 // ...lock mutex to block splash thread until wait( mutex )
713 // ...create servers checking thread
714 Session_ServerCheck<NamingServiceImplementation> sc(&_SplashMutex, &_SplashStarted);
715 // ... set initial progress
716 splash->setProgress(0, sc.totalSteps());
720 int step = sc.currentStep();
721 int total = sc.totalSteps();
722 QString msg = sc.currentMessage();
723 QString err = sc.error();
726 QtxSplash::setError(err);
727 QApplication::instance()->processEvents();
731 QtxSplash::setStatus(msg, step);
732 QApplication::instance()->processEvents();
735 // ...block this thread until servers checking is finished
736 _SplashStarted.wait(&_SplashMutex);
738 // ...unlock mutex 'cause it is no more needed
739 _SplashMutex.unlock();
742 // Finalize embedded servers launcher
743 // ...block this thread until launcher is finished
744 _ServerLaunch.wait(&_GUIMutex);
745 // ...unlock mutex 'cause it is no more needed
749 // Obtain Session interface reference
750 SALOME::Session_var session = self.getSession();
752 bool shutdownAll = false;
753 bool shutdownSession = false;
754 bool debugExceptions = boolCmdOption("--no-exception-handler") ||
755 resMgr.booleanValue("launch", "noexcepthandler", false);
759 // Launch GUI activator
763 splash->setStatus(QObject::tr("Activating desktop..."));
764 // ...create GUI launcher
765 MESSAGE("Session activated, Launch IAPP...");
766 guiThread = new GetInterfaceThread(session);
770 // Allow multiple activation/deactivation of GUI
773 MESSAGE("waiting wakeAll()");
774 _SessionStarted.wait(&_SessionMutex); // to be reseased by Launch server thread when ready:
775 // atomic operation lock - unlock on mutex
776 // unlock mutex: serverThread runs, calls _ServerLaunch->wakeAll()
777 // this thread wakes up, and lock mutex
779 _SessionMutex.unlock();
781 // Session might be shutdowning here, check status
782 SALOME::StatSession stat = session->GetStatSession();
783 shutdownSession = stat.state == SALOME::shutdown;
786 _SessionMutex.lock(); // lock mutex before leaving loop - it will be unlocked later
790 // SUIT_Session creation
791 aGUISession = new Session();
793 // Load SalomeApp dynamic library
794 MESSAGE("creation SUIT_Application");
795 SUIT_Application *aGUIApp = aGUISession->startApplication(NamingServiceImplementation::LibName, 0, 0);
798 #ifdef USE_SALOME_STYLE
799 Style_Salome::initialize(aGUIApp->resourceMgr());
800 if (aGUIApp->resourceMgr()->booleanValue("Style", "use_salome_style", true))
801 Style_Salome::apply();
802 #endif // USE_SALOME_STYLE
804 if (!debugExceptions)
805 app.setHandler(aGUISession->handler()); // after loading SalomeApp application
806 // aGUISession contains SalomeApp_ExceptionHandler
809 MESSAGE("run(): starting the main event loop");
812 splash->finish(aGUIApp->desktop());
818 if (result == SUIT_Session::NORMAL)
820 // desktop is explicitly closed by user from GUI
821 // exit flags says if it's necessary to shutdown all servers
822 // all session server only
823 shutdownAll = aGUISession->exitFlags();
827 // desktop might be closed from:
828 // - StopSesion() (temporarily) or
829 // - Shutdown() (permanently)
830 stat = session->GetStatSession();
831 shutdownSession = stat.state == SALOME::shutdown;
832 // normally "shutdown standalone servers" flag should be false here, if we come from
833 // StopSesion() or from Shutdown();
834 // but we also have to check if somebody explicitly programmatically closed session,
835 // asking to kill servers also
836 shutdownAll = aGUISession->exitFlags();
838 if (shutdownAll || shutdownSession)
840 _SessionMutex.lock(); // lock mutex before leaving loop - it will be unlocked later
848 // Prepare _GUIMutex for a new GUI activation
849 _SessionMutex.lock();
853 // unlock Session mutex
854 _SessionMutex.unlock();
856 // Shutdown embedded servers
857 if (myServerLauncher)
858 myServerLauncher->ShutdownAll();
860 // Shutdown standalone servers
862 self.shutdownRemoteServersIfNeeded(remoteLauncher);
864 // Kill embedded servers
865 if (myServerLauncher)
866 myServerLauncher->KillAll();
868 // Unregister session server
869 SALOME_Session_i *sessionServant =
870 dynamic_cast<SALOME_Session_i *>(poa->reference_to_servant(session.in()));
872 sessionServant->NSunregister();
876 delete myServerLauncher;
877 #if defined(WIN32) && defined(UNICODE)
880 self.shutdownCORBAStufIfNeeded(shutdownAll,orb);
882 if (Py_IsInitialized())
887 // Kill omniNames process
889 self.killOtherServersIfNeeded();
891 MESSAGE("Salome_Session_Server:endofserver");