1 // Copyright (C) 2007-2021 CEA/DEN, EDF R&D, 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 #ifndef DISABLE_PYCONSOLE
24 #include "SUITApp_init_python.hxx"
27 #include "GUI_version.h"
28 #include "SUITApp_Application.h"
29 #include "SUIT_Desktop.h"
30 #include "SUIT_LicenseDlg.h"
31 #include "SUIT_ResourceMgr.h"
32 #include "SUIT_Session.h"
33 #ifdef USE_SALOME_STYLE
34 #include "Style_Salome.h"
35 #endif // USE_SALOME_STYLE
36 #include "QtxSplash.h"
43 #include <QStringList>
49 //! Get version of SALOME GUI module
50 static QString salomeVersion()
52 return GUI_VERSION_STR;
55 //! Extract application name from the library filename
56 static QString getAppName( const QString& libName )
58 QString appName = QFileInfo( libName ).baseName();
59 if ( appName.startsWith( "lib" ) )
60 appName = appName.mid( 3 );
64 //! Custom resources manager, that allows customization of application name/version
65 // via configuration/translation files.
66 class ResourceMgr : public SUIT_ResourceMgr
69 ResourceMgr( bool iniFormat = false, const QString& appName = "LightApp" )
70 : SUIT_ResourceMgr( appName, "%1Config" )
72 customize( iniFormat, appName ); // activate customization
73 setCurrentFormat( iniFormat ? "ini" : "xml" );
74 setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) );
77 QString customName() const { return myCustomAppName; }
78 QString version() const { return myCustomAppVersion; }
81 static void customize( bool iniFormat, const QString& appName )
83 // Try to retrieve actual application name and version from translation files.
84 // We create temporary resource manager and load translations.
85 // This procedure is supposed to be done only once, at first call.
86 if ( myCustomAppName.isNull() ) {
87 SUIT_ResourceMgr mgr( appName, "%1Config" );
88 mgr.setCurrentFormat( iniFormat ? "ini" : "xml" );
89 mgr.setWorkingMode( IgnoreUserValues ); // prevent reading data from user's file
90 mgr.loadLanguage( appName, "en" );
92 // actual application name can be customized via APP_NAME resource key
93 myCustomAppName = QObject::tr( "APP_NAME" ).trimmed();
94 if ( myCustomAppName == "APP_NAME" || myCustomAppName.toLower() == "salome" )
95 myCustomAppName = appName; // fallback name
97 // actual application name can be customized via APP_VERSION resource key
98 myCustomAppVersion = QObject::tr( "APP_VERSION" ).trimmed();
99 if ( myCustomAppVersion == "APP_VERSION" )
100 myCustomAppVersion = myCustomAppName == appName ? salomeVersion() : ""; // fallback version
105 QString userFileName( const QString& /*appName*/, const bool forLoad ) const
107 if ( version().isEmpty() ) return "";
108 return SUIT_ResourceMgr::userFileName( myCustomAppName, forLoad );
111 virtual long userFileId( const QString& _fname ) const
113 //////////////////////////////////////////////////////////////////////////////////////////////
114 // In SALOME and SALOME-based applications the user preferences file is named as
115 // - <AppName>.xml.<AppVersion> on Windows
116 // - <AppName>rc.<AppVersion> on Linux
118 // * AppName is application name, defaults to LightApp. Can be customized in SALOME-based
119 // applications, see ResourceMgr above for more details.
120 // * AppVersion is application version, defaults to current version of SALOME GUI module
121 // if AppName is not customize, otherwise empty. Can be customized in SALOME-based
122 // applications, see ResourceMgr above for more details.
124 // Since version 6.5.0 of SALOME, user file is stored in the ~/.config/salome
125 // directory. For backward compatibility, when user preferences from nearest
126 // version of application is searched, user home directory is also looked through,
127 // with lower priority.
129 // Since version 6.6.0 of SALOME, user file name on Linux is no more prefixed by dot
130 // symbol since it is stored in the hidden ~/.config/salome directory. However, dot-prefixed
131 // files are also taken into account (with lower priority) for backward compatibility.
134 // - Currently the following format of version number is supported:
135 // <major>[.<minor>[.<release>[<type><dev>]]]
136 // Parts in square brackets are considered optional. Here:
137 // * major - major version id
138 // * minor - minor version id
139 // * release - maintenance version id
140 // * type - dev or patch marker; it can be either one alphabetical symbol (from 'a' to 'z')
141 // or 'rc' to point release candidate (case-insensitive)
142 // * dev - dev version or patch number
143 // All numerical values must be of range [1-99].
144 // Examples: 1.0, 6.5.0, 1.2.0a1, 3.3.3rc3 (release candidate 3), 11.0.0p1 (patch 1)
146 // - Versioning approach can be customized by implementing and using own resource manager class,
147 // see QtxResurceMgr, SUIT_ResourceMgr classes, and ResourceMgr class above in this file.
148 //////////////////////////////////////////////////////////////////////////////////////////////
151 if ( !myCustomAppName.isEmpty() ) {
153 // On Windows, user file name is something like LightApp.xml.6.5.0 where
154 // - LightApp is an application name (can be customized)
155 // - xml is a file format (xml or ini)
156 // - 6.5.0 is an application version, can include alfa/beta/rc marks, e.g. 6.5.0a3, 6.5.0rc1
157 QRegExp exp( QString( "%1\\.%2\\.([a-zA-Z0-9.]+)" ).arg( myCustomAppName ).arg( currentFormat() ) );
159 // On Linux, user file name is something like LightApprc.6.5.0 where
160 // - LightApp is an application name (can be customized)
161 // - 6.5.0 is an application version, can include alfa/beta/rc marks, e.g. 6.5.0a3, 6.5.0rc1
163 // VSR 24/09/2012: issue 0021781: since version 6.6.0 user filename is not prepended with "."
164 // when it is stored in the ~/.config/<appname> directory;
165 // for backward compatibility we also check files prepended with "." with lower priority
166 QRegExp exp( QString( "\\.?%1rc\\.([a-zA-Z0-9.]+)" ).arg( myCustomAppName ) );
168 QString fname = QFileInfo( _fname ).fileName();
169 if ( exp.exactMatch( fname ) ) {
170 long fid = Qtx::versionToId( exp.cap( 1 ) );
171 if ( fid > 0 ) id = fid;
178 static QString myCustomAppName;
179 static QString myCustomAppVersion;
181 QString ResourceMgr::myCustomAppName;
182 QString ResourceMgr::myCustomAppVersion;
184 //! Custom session, to use custom resource manager class.
185 class Session : public SUIT_Session
188 Session( bool theIniFormat = false ) : SUIT_Session(), myIniFormat( theIniFormat ) {}
189 virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const
191 return new ResourceMgr( myIniFormat, appName );
196 } // end of anonymous namespace
198 int main( int argc, char* argv[] )
200 // Set-up application settings configuration (as for QSettings)
201 // Note: these are default settings which can be customized (see below)
202 QApplication::setOrganizationName( "salome" );
203 QApplication::setApplicationName( "salome" );
204 QApplication::setApplicationVersion( salomeVersion() );
206 // Add <qtdir>/plugins dir to the pluins search path for image plugins
207 QString qtdir = Qtx::qtDir( "plugins" );
208 if ( !qtdir.isEmpty() )
209 QApplication::addLibraryPath( qtdir );
211 // Add application library path (to search style plugin etc...)
212 QString path = Qtx::addSlash( Qtx::getenv( "GUI_ROOT_DIR" ) ) + "bin/salome";
213 QApplication::addLibraryPath( QDir::toNativeSeparators( path ) );
215 // QSurfaceFormat should be set before creation of QApplication,
216 // so to avoid conflicts beetween SALOME and ParaView QSurfaceFormats we should merge theirs formats
217 // (see void Qtx::initDefaultSurfaceFormat()) and set the resultant format here.
218 Qtx::initDefaultSurfaceFormat();
220 // Create Qt application instance: this should be done as early as possible!
221 // Note: QApplication forces setting locale LC_ALL to system one: setlocale(LC_ALL, "").
222 SUITApp_Application app( argc, argv );
224 // Initialize Python (if necessary)
225 // Note: Python forces setting locale LC_CTYPE to system one: setlocale(LC_CTYPE, "").
226 #ifndef DISABLE_PYCONSOLE
227 char* py_argv[] = {(char*)""};
228 SUIT_PYTHON::init_python( 1, py_argv );
231 // Treat command line arguments
232 bool debugExceptions = false;
233 bool iniFormat = false;
234 bool noSplash = false;
235 bool useLicense = false;
237 foreach( QString arg, QApplication::arguments().mid(1) ) // omit 1st argument: app executable
239 if ( arg == "--no-exception-handler" )
240 debugExceptions = true;
241 else if ( arg == "--format=ini" )
243 else if ( arg == "--no-splash" )
245 else if ( arg == "--show-license" )
247 else if ( !arg.startsWith( "-" ) )
251 args << "LightApp"; // fallback application library
253 QString appName = getAppName( args.first() );
255 // Create auxiliary resource manager to access application settings
256 ResourceMgr resMgr( iniFormat, appName );
257 resMgr.setWorkingMode( ResourceMgr::IgnoreUserValues );
258 resMgr.loadLanguage( appName, "en" );
260 // Set-up application settings configuration possible customized via resources
261 if ( resMgr.customName() != "LightApp" ) {
262 QApplication::setApplicationName( resMgr.customName() );
263 QApplication::setApplicationVersion( resMgr.version() );
266 // Force default "C" locale if requested via user's preferences
267 // Note: this does not change whole application locale (changed via setlocale() function),
268 // but only affects GUI behavior
269 resMgr.setWorkingMode( ResourceMgr::AllowUserValues ); // we must take into account user preferences
270 if ( resMgr.booleanValue( "language", "locale", true ) )
271 QLocale::setDefault( QLocale::c() );
272 resMgr.setWorkingMode( ResourceMgr::IgnoreUserValues );
274 #if defined(GLOBAL_DOUBLE_CONVERSION)
275 // VSR 30/03/2021: moved here from QtxDoubleSpinBox/QtxIntSpinBox because of crash on Qt 5.12.
276 // Disable thousands separator for spin box
277 // see issue 14540 (old id 21219)
279 locale.setNumberOptions(locale.numberOptions() | QLocale::OmitGroupSeparator | QLocale::RejectGroupSeparator);
280 QLocale::setDefault(locale);
283 if ( !debugExceptions )
284 debugExceptions = resMgr.booleanValue( "launch", "noexcepthandler", false );
286 noSplash = !resMgr.booleanValue( "launch", "splash", true );
288 useLicense = resMgr.booleanValue( "launch", "license", false );
290 // If asked, read the text from a file show a license dialog
291 // TODO: path to license file, and option to check license, may be defined in XML cfg file.
293 QFile file( QDir::home().filePath( "ReadLicense.log" ) );
294 if ( !file.exists() ) {
295 SUIT_LicenseDlg aLicense;
296 if ( aLicense.exec() != QDialog::Accepted )
297 return 1; // license is not accepted!
301 // If not disabled, show splash screen
302 QtxSplash* splash = 0;
305 splash = QtxSplash::splash( QPixmap() );
306 splash->readSettings( &resMgr );
307 if ( splash->pixmap().isNull() )
308 splash->setPixmap( resMgr.loadPixmap( appName, QObject::tr( "ABOUT_SPLASH" ) ) );
309 if ( splash->pixmap().isNull() )
310 splash->setPixmap( resMgr.loadPixmap( "LightApp", QObject::tr( "ABOUT_SPLASH" ) ) );
311 if ( splash->pixmap().isNull() ) {
316 splash->setOption( "%A", QObject::tr( "APP_NAME" ) );
317 splash->setOption( "%V", QObject::tr( "ABOUT_VERSION" ).arg( resMgr.version() ) );
318 splash->setOption( "%L", QObject::tr( "ABOUT_LICENSE" ) );
319 splash->setOption( "%C", QObject::tr( "ABOUT_COPYRIGHT" ) );
321 QApplication::instance()->processEvents();
326 Session session( iniFormat );
328 // Initialize and start application supplied by the library specified via the parameter
329 SUIT_Application* sessionApp = session.startApplication( appName );
332 #ifdef USE_SALOME_STYLE
333 Style_Salome::initialize( session->resourceMgr() );
334 if ( session->resourceMgr()->booleanValue( "Style", "use_salome_style", true ) )
335 Style_Salome::apply();
336 #endif // USE_SALOME_STYLE
338 if ( !debugExceptions )
339 app.setHandler( session.handler() );
342 splash->finish( sessionApp->desktop() );