]> SALOME platform Git repositories - modules/kernel.git/blob - src/SALOMEGUI/QAD_ResourceMgr.cxx
Salome HOME
sources v1.2
[modules/kernel.git] / src / SALOMEGUI / QAD_ResourceMgr.cxx
1 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
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. 
10 // 
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. 
15 // 
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 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : QAD_ResourceMgr.cxx
25 //  Author : UI team
26 //  Module : SALOME
27 //  $Header$
28
29 using namespace std;
30 /*!
31   \class QAD_ResourceMgr QAD_ResourceMgr.h
32   \brief ResourceMgr QAD-based application.
33 */
34
35 #include "QAD.h"
36 #include "QAD_Tools.h"
37 #include "QAD_MessageBox.h"
38 #include "QAD_ResourceMgr.h"
39
40 #include "utilities.h"
41
42 #include <qfile.h>
43 #include <stdlib.h>
44 #include <qtranslator.h>
45 #include <qapplication.h>
46 #include <qfileinfo.h>
47
48 #include <Standard.hxx>
49
50 /* configuration file */
51 static const char* CONFIG_FILE = "config";
52
53 /* config keys */
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
60 static const char* SEPARATOR    = ":";
61
62 /*!
63     Constructor
64 */
65 QAD_ResourceMgr::QAD_ResourceMgr() :
66 myRes( 5, false )
67 {    
68     myRes.setAutoDelete( true );    
69 }
70
71 /*!
72     Destructor
73 */
74 QAD_ResourceMgr::~QAD_ResourceMgr()
75 {
76      myRes.clear();
77 }
78
79 /*!
80     Removes icons and messages from 'prefix'_msg_'lang'
81     and 'prefix'_icons' files. Returns 'true' if OK. 
82     Each application which has its own resources must
83     have a unique 'prefix' ( prefix "QAD" is reserved )
84 */
85 bool QAD_ResourceMgr::removeResources( const char* prefix )
86 {    
87   return myRes.remove(prefix);
88 }
89
90 /*!
91     Loads icons and messages from 'prefix'_msg_'lang'
92     and 'prefix'_icons' files. Returns 'true' if OK. 
93     Each application which has its own resources must
94     have a unique 'prefix' ( prefix "QAD" is reserved )
95 */
96 bool QAD_ResourceMgr::loadResources( const char* prefix, QString &msg )
97 {    
98   bool allLoaded = true;    
99   if ( !myRes[ prefix ] ) {
100     QCString dir ;
101     
102     /*  We read the settings once and keep them. 
103         The resources are loaded consequently from the end of directory list
104         which ( see collectDirs() method description ). This allows to override
105         resources when it is necessary.
106     */
107     
108     ResourceSettings* settings = new ResourceSettings();
109     StringDict& conf = settings->config();
110     myRes.insert( prefix, settings );
111     
112     // settings->config().insert( RES_DIR, new QString( resDir ) );
113     
114     /* we search language definition : we read it in config file
115        If not found, we use default : English
116     */
117     conf.insert( RES_LANGUAGE, new QString( "en" ) );
118     
119     /* Read configuration file */
120     
121     /* WE MUST HAVE ONE CONFIGURATION FILE FOR ALL SALOME !!!
122        I DON'T KNOW WHERE READ IT AND SAVE ITS CONTENTS FOR ALL GUI
123        ALL GUI HAS SAME LANGUAGE AND HAVE DEFAULT (en) IF SPECIFIED 
124        IS NOT FOUND !!
125     */
126     QString resDirs = collectDirs( prefix );
127     conf.insert( RES_DIR, new QString( resDirs ) );
128     QString fileConfig = path( CONFIG_FILE, prefix, 0 ) ;
129     //MESSAGE("QAD_ResourceMgr::loadresources : config : "<<fileConfig);
130     if ( !fileConfig.isEmpty() ) {
131       QFile configFile( fileConfig );
132       if ( !configFile.exists() || !configFile.open( IO_ReadOnly ) ) {
133         QString warnMsg;
134         warnMsg.sprintf( "Cannot open configuration file: %s\nDefault settings will be used.",
135                          configFile.name().latin1() );
136         msg = warnMsg;
137 //      removeResources( prefix );
138 //      return false;
139       } 
140       else {     
141         /* read 'config' file */
142         const int MAX_LINE = 512;
143         while ( !configFile.atEnd() ) {
144           QString line;
145           if ( configFile.readLine( line, MAX_LINE ) > 0 ) {
146             int index;
147             if ( ( index = line.find( "=" ) ) > 0 ) {
148               QString key = line.left(index).stripWhiteSpace();
149               QString value = line.mid( index+1 ).stripWhiteSpace();                    
150               conf.replace( key, new QString( value ) );
151             }
152           }
153         }
154         configFile.close();                        
155       }
156     }
157     
158     /* Load the resources */
159     QString stFile( prefix );
160     stFile = stFile + "_msg_" +  *( conf[ RES_LANGUAGE ] ) + ".qm" ;
161     QString imagesFile( prefix );
162     imagesFile = imagesFile + "_" + RES_PIXMAPS + ".qm";
163     if ( conf[ RES_STRINGS ] && !conf[ RES_STRINGS ]->isEmpty() )
164       stFile = QAD_Tools::addSlash( *conf[ RES_STRINGS ] ) + stFile;
165     if ( conf[ RES_PIXMAPS ] && !conf[ RES_PIXMAPS ]->isEmpty() )
166       imagesFile = QAD_Tools::addSlash( *conf[ RES_PIXMAPS ] ) + imagesFile;
167
168     bool bLoadString = false;
169     bool bLoadImages = false;
170
171     QStringList dirList = QStringList::split( SEPARATOR, resDirs, false ); // skip empty entries
172     for ( int i = dirList.count()-1; i >= 0; i-- ) {
173       QString dir = dirList[ i ];
174       QString fileString = QAD_Tools::addSlash( dir ) + stFile;
175       QString fileImage  = QAD_Tools::addSlash( dir ) + imagesFile;
176       
177       if ( settings->load( fileString ) ) {
178         bLoadString = true;
179       }
180       if ( settings->load( fileImage ) ) {
181         bLoadImages = true;
182       }
183     }
184     
185     if ( !bLoadString ) {
186       QString warnMsg;
187       warnMsg.sprintf( "String resources for module %s not found.\n"
188                        "Please, check your settings.", 
189                        prefix );
190       msg = warnMsg;
191 //      removeResources( prefix );
192       return false;
193     }
194     if ( !bLoadImages ) {
195       QString warnMsg;
196       warnMsg.sprintf( "Icons resources for module %s not found.\n"
197                        "Please, check your settings.", 
198                        prefix );
199       msg = warnMsg;
200 //      removeResources( prefix );
201       return false;
202     }
203     allLoaded = bLoadString && bLoadImages;
204   }
205   return allLoaded;
206 }
207
208 /*!
209   Returns language setting for the module 'prefix' ( e.g. "en" )
210 */
211 QString QAD_ResourceMgr::language( const char* prefix ) const
212 {
213   QString ret;
214   ResourceSettings* rs = myRes[ prefix ];
215   if ( rs ) 
216     {
217       StringDict& conf = rs->config();
218       ret = *(conf[RES_LANGUAGE]);
219     }
220   return ret;
221 }
222
223 /*!
224   Returns list of directories where resources can be located
225   See collectDirs() method description for more detail
226 */
227 QString QAD_ResourceMgr::resources( const char* prefix ) const
228 {
229   QString ret;
230   ResourceSettings* rs = myRes[ prefix ];
231   if ( rs ) 
232     {
233       StringDict& conf = rs->config();
234       ret = *(conf[RES_DIR]);
235     }
236   return ret;
237 }
238
239 /*!
240   Collects list of directories, separated by ';' where resources for module 'prefix'
241   can be situated
242   The order is following : 
243   - CSF_<prefix>Resources env.var directory ( or directory list )
244   - CSF_ResourcesDefaults env.var directory ( or directory list )
245   - ${HOME}/.salome/resources directory
246   - ${SALOME_SITE_DIR}/share/salome/resources directory
247   - ${SALOME_ROOT_DIR}/share/salome/resources directory
248 */
249 QString QAD_ResourceMgr::collectDirs( const QString& prefix ) const
250 {
251   QString dirList;
252   QCString envVar( "CSF_" );
253   QString dir;
254   char* cenv;
255   
256   // Try CSF_<prefix>Resources env.var directory ( or directory list )
257   if ( !prefix.isEmpty() ) {
258     envVar = QCString( "CSF_" ) + prefix.latin1() + QCString( "Resources" );
259     cenv = getenv( ( const char* ) envVar );
260     if ( cenv ) {
261       dir.sprintf( "%s", cenv );
262       if ( !dir.isEmpty() )
263         dirList.append( dirList.isEmpty() ? dir : ( QString( SEPARATOR ) + dir ) );
264     }
265   }
266   // Try CSF_ResourcesDefaults env.var directory ( or directory list )
267   cenv = getenv( "CSF_ResourcesDefaults" );
268   if ( cenv ) {
269     dir.sprintf( "%s", cenv );
270     if ( !dir.isEmpty() )
271       dirList.append( dirList.isEmpty() ? dir : ( QString( SEPARATOR ) + dir ) );
272   }
273   // Try ${HOME}/.salome/resources directory
274   cenv = getenv( "HOME" );
275   if ( cenv ) {
276     dir.sprintf( "%s", cenv );
277     if ( !dir.isEmpty() ) {
278       dir = QAD_Tools::addSlash(dir) ;
279       dir = dir + ".salome" ;
280       dir = QAD_Tools::addSlash(dir) ;
281       dir = dir + "resources" ;
282       dir = QAD_Tools::addSlash(dir) ;
283       dirList.append( dirList.isEmpty() ? dir : ( QString( SEPARATOR ) + dir ) );
284     }
285   }
286   // Try ${SALOME_SITE_DIR}/share/salome/resources directory
287   cenv = getenv( "SALOME_SITE_DIR" );
288   if ( cenv ) {
289     dir.sprintf( "%s", cenv );
290     if ( !dir.isEmpty() ) {
291       dir = QAD_Tools::addSlash(dir) ;
292       dir = dir + "share" ;
293       dir = QAD_Tools::addSlash(dir) ;
294       dir = dir + "salome" ;
295       dir = QAD_Tools::addSlash(dir) ;
296       dir = dir + "resources" ;
297       dir = QAD_Tools::addSlash(dir) ;
298       dirList.append( dirList.isEmpty() ? dir : ( QString( SEPARATOR ) + dir ) );
299     }
300   }
301   // Try ${SALOME_ROOT_DIR}/share/salome/resources directory
302   cenv = getenv( "SALOME_ROOT_DIR" );
303   if ( cenv ) {
304     dir.sprintf( "%s", cenv );
305     if ( !dir.isEmpty() ) {
306       dir = QAD_Tools::addSlash(dir) ;
307       dir = dir + "share" ;
308       dir = QAD_Tools::addSlash(dir) ;
309       dir = dir + "salome" ;
310       dir = QAD_Tools::addSlash(dir) ;
311       dir = dir + "resources" ;
312       dir = QAD_Tools::addSlash(dir) ;
313       dirList.append( dirList.isEmpty() ? dir : ( QString( SEPARATOR ) + dir ) );
314     }
315   }
316   //MESSAGE("QAD_ResourceMgr::collectDirs : "<<dirList.latin1()) ;
317   return dirList;
318 }
319
320 /*!
321     Returns a directory where 'filename' is located (filename is relative 
322     of the application identified by 'prefix' or empty string if file not found
323     Search is processed in different location : see collectDirs() method description
324 */
325 QString QAD_ResourceMgr::getFile( const QString& filename, const char* prefix ) const
326 {  
327   QFileInfo fi( path( filename, prefix, 0 ) );
328   if ( fi.isFile() && fi.exists() )
329     return fi.dirPath();
330   return QString();
331 }
332
333 /*!
334     Returns a directory where 'filename' is located (filename is relative 
335     of the application identified by 'prefix' or empty string if file not found
336     Search is processed in different location : see collectDirs() method description
337     The difference from above method that this function is used when resources 
338     is not yet actually loaded by application.
339 */
340 QString QAD_ResourceMgr::findFile( const QString& filename, const char* prefix ) const
341 {  
342   QString resDirs = collectDirs( prefix );
343   QStringList dirList = QStringList::split( SEPARATOR, resDirs, false ); // skip empty entries
344   for ( int i = 0; i < dirList.count(); i++ ) {
345     QString dir = dirList[ i ];
346     QFileInfo fi( QAD_Tools::addSlash( dir ) + filename );
347     if ( fi.isFile() && fi.exists() )
348       return fi.dirPath();
349   }
350   return QString();
351 }
352
353 /*!
354     Returns a path to file 'filename' (filename is relative 
355     of the application identified by 'prefix' and subdirectory identified by 'key'
356     or empty string if file not found.
357     Search is processed in different location : see collectDirs() method description
358
359     Returns a directory 'key' resource of the application 
360     identified by 'prefix'    
361 */
362 QString QAD_ResourceMgr::path( const QString& filename, const char* prefix, const char* key ) const
363 {   
364   QString filePath;
365
366   ResourceSettings* rs = myRes[ prefix ];
367   if ( rs ) {
368     StringDict& conf = rs->config();
369     QString resDirs = QString( *( conf[ RES_DIR ] ) );
370     if ( !resDirs.isEmpty() ) {
371       //MESSAGE("QAD_ResourceMgr::resDirs : <"<<resDirs<<">") ;
372       QStringList dirList = QStringList::split( SEPARATOR, resDirs, false ); // skip empty entries
373       for ( int i = 0; i < dirList.count(); i++ ) {
374         QString dir = dirList[ i ];
375         dir = QAD_Tools::addSlash( dir );
376         if ( key ) {
377           QString* where = conf[ key ];
378           if ( where )
379             dir = dir + QAD_Tools::addSlash( *where );
380         }
381         dir = dir + filename;
382         QFileInfo fileInfo( dir );
383         if ( fileInfo.isFile() && fileInfo.exists() ) {
384           filePath = fileInfo.filePath();
385           break;
386         }
387       }
388     }
389   }
390   //MESSAGE("QAD_ResourceMgr::path : <"<<filename.latin1()<<"> : "<<filePath.latin1()) ;
391   return filePath;
392 }
393
394 /*!
395     Loads a pixmap from 'resname' resources 
396     and indetified by 'id'
397 */
398 QPixmap QAD_ResourceMgr::loadPixmap( const char* resname, 
399                                      const QString& id ) const
400 {
401   return QPixmap( path( id, resname, RES_PIXMAPS ) );
402 }
403
404 /*!
405     Loads a doc page from 'resname' resources
406     and indetified by 'id'
407 */
408 bool QAD_ResourceMgr::loadDoc( const char* resname,
409                                const QString& id ) const
410 {    
411   QString docPath = path( id, resname, RES_DOCS );
412   return true;
413 }
414
415 /************************************************************************
416 **  
417 **  Class QAD_ResourceMgr::ResourceSettings ( internal )
418 **  
419 *************************************************************************/
420
421 /*!
422     Loads a resource 'file'. 
423     Returns 'false' if 'file' can't be loaded( not found etc. ),
424     'true' if loaded or reloaded OK. 
425 */
426 bool QAD_ResourceMgr::ResourceSettings::load( const QString& file )
427 {   
428 #if QT_VERSION >= 0x030000 // VSR: workaround - crash on qt3.0.5 ==========
429   static const int magic_length = 16;        // length of *.qm file header (qtranslator.cpp)
430   static const uchar magic[magic_length] = { // magic number for the file
431     0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
432     0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd };
433   QFile f(file);
434   if ( !f.exists() || f.size() < magic_length)
435     return false;
436   char buf[magic_length];
437   if ( !f.open(IO_ReadOnly) )
438     return false;
439   bool bOk = ( f.readBlock(buf, magic_length) == magic_length );
440   f.close();
441   if (!bOk)
442     return false;
443   if ( memcmp( (const void *)buf, magic, magic_length ) )
444     return false;
445   if ( f.size() == magic_length)
446     return true;
447 #endif // VSR =============================================================
448   QTranslator* strTbl = new QTranslator( 0 );    
449   try {
450     if ( !strTbl->load( file, "" ) ) {
451       delete strTbl;
452       return false;
453     }    
454   }
455   catch (...) {
456     return false;
457   }
458   QAD_ASSERT_DEBUG_ONLY( qApp );
459   qApp->installTranslator( strTbl );    
460   return true;
461 }