1 // SALOME SALOMEGUI : implementation of desktop and GUI kernel
3 // Copyright (C) 2003 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.
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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : QAD_ResourceMgr.cxx
30 \class QAD_ResourceMgr QAD_ResourceMgr.h
31 \brief ResourceMgr QAD-based application.
35 #include "QAD_Tools.h"
36 #include "QAD_MessageBox.h"
37 #include "QAD_ResourceMgr.h"
39 #include "utilities.h"
43 #include <qtranslator.h>
44 #include <qapplication.h>
45 #include <qfileinfo.h>
47 #include <Standard.hxx>
50 /* configuration file */
51 static const char* CONFIG_FILE = "config";
54 static const char* RES_DIR = "res";
55 static const char* RES_DOCS = "docs";
56 static const char* RES_PIXMAPS = "icons";
57 static const char* RES_STRINGS = "strings";
58 static const char* RES_LANGUAGE = "language";
59 static const char* RES_FILES = "resources";
61 static const char* SEPARATOR = ":";
66 QAD_ResourceMgr::QAD_ResourceMgr() :
69 myRes.setAutoDelete( true );
75 QAD_ResourceMgr::~QAD_ResourceMgr()
81 Removes icons and messages from 'prefix'_msg_'lang'
82 and 'prefix'_icons' files. Returns 'true' if OK.
83 Each application which has its own resources must
84 have a unique 'prefix' ( prefix "QAD" is reserved )
86 bool QAD_ResourceMgr::removeResources( const char* prefix )
88 return myRes.remove(prefix);
92 Loads icons and messages from 'prefix'_msg_'lang'
93 and 'prefix'_icons' files. Returns 'true' if OK.
94 Each application which has its own resources must
95 have a unique 'prefix' ( prefix "QAD" is reserved )
97 bool QAD_ResourceMgr::loadResources( const char* prefix, QString &msg )
99 bool allLoaded = true;
100 if ( !myRes[ prefix ] ) {
103 /* We read the settings once and keep them.
104 The resources are loaded consequently from the end of directory list
105 which ( see collectDirs() method description ). This allows to override
106 resources when it is necessary.
109 ResourceSettings* settings = new ResourceSettings();
110 StringDict& conf = settings->config();
111 myRes.insert( prefix, settings );
113 // settings->config().insert( RES_DIR, new QString( resDir ) );
115 /* we search language definition : we read it in config file
116 If not found, we use default : English
118 conf.insert( RES_LANGUAGE, new QString( "en" ) );
120 /* Read configuration file */
122 /* WE MUST HAVE ONE CONFIGURATION FILE FOR ALL SALOME !!!
123 I DON'T KNOW WHERE READ IT AND SAVE ITS CONTENTS FOR ALL GUI
124 ALL GUI HAS SAME LANGUAGE AND HAVE DEFAULT (en) IF SPECIFIED
127 QString resDirs = collectDirs( prefix );
128 conf.insert( RES_DIR, new QString( resDirs ) );
129 QString fileConfig = QString( prefix ) + QString( "." ) + QString( CONFIG_FILE );
130 fileConfig = path( fileConfig, prefix, 0 ) ;
131 //MESSAGE("QAD_ResourceMgr::loadresources : config : "<<fileConfig);
132 if ( fileConfig.isEmpty() )
133 fileConfig = path( CONFIG_FILE, prefix, 0 ) ;
134 if ( !fileConfig.isEmpty() ) {
135 QFile configFile( fileConfig );
136 if ( !configFile.exists() || !configFile.open( IO_ReadOnly ) ) {
138 warnMsg.sprintf( "Cannot open configuration file: %s\nDefault settings will be used.",
139 configFile.name().latin1() );
141 // removeResources( prefix );
145 /* read 'config' file */
146 const int MAX_LINE = 512;
147 while ( !configFile.atEnd() ) {
149 if ( configFile.readLine( line, MAX_LINE ) > 0 ) {
151 if ( ( index = line.find( "=" ) ) > 0 ) {
152 QString key = line.left(index).stripWhiteSpace();
153 QString value = line.mid( index+1 ).stripWhiteSpace();
154 conf.replace( key, new QString( value ) );
162 /* Load the resources */
163 QString stFile( prefix );
164 stFile = stFile + "_msg_" + *( conf[ RES_LANGUAGE ] ) + ".qm" ;
165 QString imagesFile( prefix );
166 imagesFile = imagesFile + "_" + RES_PIXMAPS + ".qm";
167 if ( conf[ RES_STRINGS ] && !conf[ RES_STRINGS ]->isEmpty() )
168 stFile = QAD_Tools::addSlash( *conf[ RES_STRINGS ] ) + stFile;
169 if ( conf[ RES_PIXMAPS ] && !conf[ RES_PIXMAPS ]->isEmpty() )
170 imagesFile = QAD_Tools::addSlash( *conf[ RES_PIXMAPS ] ) + imagesFile;
172 bool bLoadString = false;
173 bool bLoadImages = false;
175 QStringList resFiles = conf[ RES_FILES ] ? QStringList::split( SEPARATOR, *( conf[ RES_FILES ] ), false ) : QStringList();
177 // first load main module's resources
178 QString fileString = path( stFile, prefix, 0 );
179 QString fileImage = path( imagesFile, prefix, 0 );
181 if ( !fileString.isEmpty() && settings->load( fileString ) ) {
184 if ( !fileImage.isEmpty() && settings->load( fileImage ) ) {
188 // then load additional module's resources if any are given
189 for ( int j = 0; j < resFiles.count(); j++ ) {
190 QString stFileAdd = resFiles[j] + "_msg_" + *( conf[ RES_LANGUAGE ] ) + ".qm" ;
191 QString imagesFileAdd = resFiles[j] + "_" + RES_PIXMAPS + ".qm";
192 if ( conf[ RES_STRINGS ] && !conf[ RES_STRINGS ]->isEmpty() )
193 stFileAdd = QAD_Tools::addSlash( *conf[ RES_STRINGS ] ) + stFileAdd;
194 if ( conf[ RES_PIXMAPS ] && !conf[ RES_PIXMAPS ]->isEmpty() )
195 imagesFileAdd = QAD_Tools::addSlash( *conf[ RES_PIXMAPS ] ) + imagesFileAdd;
197 QString fileStringAdd = path( stFileAdd, prefix, 0 );
198 QString fileImageAdd = path( imagesFileAdd, prefix, 0 );
200 if ( !fileStringAdd.isEmpty() )
201 settings->load( fileStringAdd );
202 if ( !fileImageAdd.isEmpty() )
203 settings->load( fileImageAdd );
206 if ( !bLoadString ) {
208 warnMsg.sprintf( "String resources for module %s not found.\n"
209 "Please, check your settings.",
212 // removeResources( prefix );
215 if ( !bLoadImages ) {
217 warnMsg.sprintf( "Icons resources for module %s not found.\n"
218 "Please, check your settings.",
221 // removeResources( prefix );
224 allLoaded = bLoadString && bLoadImages;
230 Returns language setting for the module 'prefix' ( e.g. "en" )
232 QString QAD_ResourceMgr::language( const char* prefix ) const
235 ResourceSettings* rs = myRes[ prefix ];
238 StringDict& conf = rs->config();
239 ret = *(conf[RES_LANGUAGE]);
245 Returns list of directories where resources can be located
246 See collectDirs() method description for more detail
248 QString QAD_ResourceMgr::resources( const char* prefix ) const
251 ResourceSettings* rs = myRes[ prefix ];
254 StringDict& conf = rs->config();
255 ret = *(conf[RES_DIR]);
261 Collects list of directories, separated by ';' where resources for module 'prefix'
263 The order is following :
264 - <prefix>_ROOT_DIR/share/salome/resources directory
265 - SALOME_<prefix>Resources env.var directory ( or directory list )
266 - ${HOME}/.salome/resources directory
267 - ${SALOME_SITE_DIR}/share/${SALOME_SITE_NAME}/resources directory (for SALOME-based applications)
268 - ${KERNEL_ROOT_DIR}/share/salome/resources directory
270 QString QAD_ResourceMgr::collectDirs( const QString& prefix ) const
277 if ( !prefix.isEmpty() ) {
278 envVar = prefix.latin1() + QCString( "_ROOT_DIR" );
279 cenv = getenv( ( const char* ) envVar );
281 dir.sprintf( "%s", cenv );
282 if ( !dir.isEmpty() ) {
283 dir = QAD_Tools::addSlash(dir) ;
284 dir = dir + "share" ;
285 dir = QAD_Tools::addSlash(dir) ;
286 dir = dir + "salome" ;
287 dir = QAD_Tools::addSlash(dir) ;
288 dir = dir + "resources" ;
289 dir = QAD_Tools::addSlash(dir) ;
290 dirList.append( dirList.isEmpty() ? dir : ( QString( SEPARATOR ) + dir ) );
295 // Try SALOME_<prefix>Resources env.var directory ( or directory list )
296 if ( !prefix.isEmpty() ) {
297 envVar = QCString( "SALOME_" ) + prefix.latin1() + QCString( "Resources" );
298 cenv = getenv( ( const char* ) envVar );
300 dir.sprintf( "%s", cenv );
301 if ( !dir.isEmpty() )
302 dirList.append( dirList.isEmpty() ? dir : ( QString( SEPARATOR ) + dir ) );
305 // Try ${HOME}/.salome/resources directory
306 cenv = getenv( "HOME" );
308 dir.sprintf( "%s", cenv );
309 if ( !dir.isEmpty() ) {
310 dir = QAD_Tools::addSlash(dir) ;
311 dir = dir + ".salome" ;
312 dir = QAD_Tools::addSlash(dir) ;
313 dir = dir + "resources" ;
314 dir = QAD_Tools::addSlash(dir) ;
315 dirList.append( dirList.isEmpty() ? dir : ( QString( SEPARATOR ) + dir ) );
318 // Try ${SALOME_SITE_DIR}/share/${SALOME_SITE_NAME}/resources directory
319 cenv = getenv( "SALOME_SITE_DIR" );
321 dir.sprintf( "%s", cenv );
322 if ( !dir.isEmpty() ) {
323 dir = QAD_Tools::addSlash(dir) ;
324 dir = dir + "share" ;
325 dir = QAD_Tools::addSlash(dir) ;
326 cenv = getenv( "SALOME_SITE_NAME" );
330 dir = dir + "salome" ;
331 dir = QAD_Tools::addSlash(dir) ;
332 dir = dir + "resources" ;
333 dir = QAD_Tools::addSlash(dir) ;
334 dirList.append( dirList.isEmpty() ? dir : ( QString( SEPARATOR ) + dir ) );
337 // Try ${KERNEL_ROOT_DIR}/share/salome/resources directory
338 cenv = getenv( "KERNEL_ROOT_DIR" );
340 dir.sprintf( "%s", cenv );
341 if ( !dir.isEmpty() ) {
342 dir = QAD_Tools::addSlash(dir) ;
343 dir = dir + "share" ;
344 dir = QAD_Tools::addSlash(dir) ;
345 dir = dir + "salome" ;
346 dir = QAD_Tools::addSlash(dir) ;
347 dir = dir + "resources" ;
348 dir = QAD_Tools::addSlash(dir) ;
349 dirList.append( dirList.isEmpty() ? dir : ( QString( SEPARATOR ) + dir ) );
352 //MESSAGE("QAD_ResourceMgr::collectDirs : "<<dirList.latin1()) ;
357 Returns a directory where 'filename' is located (filename is relative
358 of the application identified by 'prefix' or empty string if file not found
359 Search is processed in different location : see collectDirs() method description
361 QString QAD_ResourceMgr::getFile( const QString& filename, const char* prefix ) const
363 QFileInfo fi( path( filename, prefix, 0 ) );
364 if ( fi.isFile() && fi.exists() )
370 Returns a directory where 'filename' is located (filename is relative
371 of the application identified by 'prefix' or empty string if file not found
372 Search is processed in different location : see collectDirs() method description
373 The difference from above method that this function is used when resources
374 is not yet actually loaded by application.
376 QString QAD_ResourceMgr::findFile( const QString& filename, const char* prefix ) const
378 QString resDirs = collectDirs( prefix );
379 QStringList dirList = QStringList::split( SEPARATOR, resDirs, false ); // skip empty entries
380 for ( int i = 0; i < dirList.count(); i++ ) {
381 QString dir = dirList[ i ];
382 QFileInfo fi( QAD_Tools::addSlash( dir ) + filename );
383 if ( fi.isFile() && fi.exists() )
390 Returns a path to file 'filename' (filename is relative
391 of the application identified by 'prefix' and subdirectory identified by 'key'
392 or empty string if file not found.
393 Search is processed in different location : see collectDirs() method description
395 Returns a directory 'key' resource of the application
396 identified by 'prefix'
398 QString QAD_ResourceMgr::path( const QString& filename, const char* prefix, const char* key ) const
400 ResourceSettings* rs = myRes[ prefix ];
402 StringDict& conf = rs->config();
403 QString resDirs = QString( *( conf[ RES_DIR ] ) );
404 if ( !resDirs.isEmpty() ) {
405 //MESSAGE("QAD_ResourceMgr::resDirs : <"<<resDirs<<">") ;
406 QStringList dirList = QStringList::split( SEPARATOR, resDirs, false ); // skip empty entries
407 for ( int i = 0; i < dirList.count(); i++ ) {
408 QString dir = dirList[ i ];
409 dir = QAD_Tools::addSlash( dir );
410 if ( key && conf[ key ] ) {
411 dir = dir + QString( *( conf[ key ] ) );
412 dir = QAD_Tools::addSlash( dir );
414 dir = dir + filename;
415 QFileInfo fileInfo( dir );
416 if ( fileInfo.isFile() && fileInfo.exists() ) {
417 return fileInfo.filePath();
422 //MESSAGE("QAD_ResourceMgr::path : <"<<filename.latin1()<<"> : "<<filePath.latin1()) ;
423 return QString::null;
427 Loads a pixmap from 'resname' resources
428 and indetified by 'id'
430 QPixmap QAD_ResourceMgr::loadPixmap( const char* resname,
431 const QString& id ) const
433 return QPixmap( path( id, resname, RES_PIXMAPS ) );
437 Loads a doc page from 'resname' resources
438 and indetified by 'id'
440 bool QAD_ResourceMgr::loadDoc( const char* resname,
441 const QString& id ) const
443 QString docPath = path( id, resname, RES_DOCS );
447 /************************************************************************
449 ** Class QAD_ResourceMgr::ResourceSettings ( internal )
451 *************************************************************************/
454 Loads a resource 'file'.
455 Returns 'false' if 'file' can't be loaded( not found etc. ),
456 'true' if loaded or reloaded OK.
458 bool QAD_ResourceMgr::ResourceSettings::load( const QString& file )
460 #if QT_VERSION >= 0x030000 // VSR: workaround - crash on qt3.0.5 ==========
461 static const int magic_length = 16; // length of *.qm file header (qtranslator.cpp)
462 static const uchar magic[magic_length] = { // magic number for the file
463 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
464 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd };
466 if ( !f.exists() || f.size() < magic_length)
468 char buf[magic_length];
469 if ( !f.open(IO_ReadOnly) )
471 bool bOk = ( f.readBlock(buf, magic_length) == magic_length );
475 if ( memcmp( (const void *)buf, magic, magic_length ) )
477 if ( f.size() == magic_length)
479 #endif // VSR =============================================================
480 QTranslator* strTbl = new QTranslator( 0 );
482 if ( !strTbl->load( file, "" ) ) {
490 QAD_ASSERT_DEBUG_ONLY( qApp );
491 qApp->installTranslator( strTbl );