]> SALOME platform Git repositories - modules/gui.git/blob - src/Qtx/QtxResourceMgr.cxx
Salome HOME
Update copyrights 2014.
[modules/gui.git] / src / Qtx / QtxResourceMgr.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  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, or (at your option) any later version.
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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:      QtxResourceMgr.cxx
24 // Author:    Alexander SOLOVYOV, Sergey TELKOV
25 //
26 #include "QtxResourceMgr.h"
27 #include "QtxTranslator.h"
28
29 #include <QSet>
30 #include <QDir>
31 #include <QFile>
32 #include <QFileInfo>
33 #include <QRegExp>
34 #include <QTextStream>
35 #include <QApplication>
36 #include <QLibraryInfo>
37 #include <QtDebug>
38 #ifndef QT_NO_DOM
39 #include <QDomDocument>
40 #include <QDomElement>
41 #include <QDomNode>
42 #endif
43
44 #include <stdlib.h>
45
46 /*!
47   \class QtxResourceMgr::Resources
48   \internal
49   \brief Represents container for settings read from the resource file.
50 */
51
52 class QtxResourceMgr::Resources
53 {
54 public:
55   Resources( QtxResourceMgr*, const QString& );
56   virtual ~Resources();
57
58   QString                file() const;
59   void                   setFile( const QString& );
60
61   QString                value( const QString&, const QString&, const bool ) const;
62   void                   setValue( const QString&, const QString&, const QString& );
63
64   bool                   hasSection( const QString& ) const;
65   bool                   hasValue( const QString&, const QString& ) const;
66
67   void                   removeSection( const QString& );
68   void                   removeValue( const QString&, const QString& );
69
70   QPixmap                loadPixmap( const QString&, const QString&, const QString& ) const;
71   QTranslator*           loadTranslator( const QString&, const QString&, const QString& ) const;
72
73   QString                makeSubstitution( const QString&, const QString&, const QString& ) const;
74
75   void                   clear();
76
77   QStringList            sections() const;
78   QStringList            parameters( const QString& ) const;
79
80   QString                path( const QString&, const QString&, const QString& ) const;
81
82 protected:
83   QtxResourceMgr*        resMgr() const;
84
85 private:
86   Section                section( const QString& );
87   const Section          section( const QString& ) const;
88
89   QString                fileName( const QString&, const QString&, const QString& ) const;
90
91 private:
92   typedef QMap<QString, Section> SectionMap;
93
94 private:
95   QtxResourceMgr*        myMgr;             //!< resources manager
96   SectionMap             mySections;        //!< sections map
97   QString                myFileName;        //!< resources file name
98   QMap<QString,QPixmap>  myPixmapCache;     //!< pixmaps cache
99
100   friend class QtxResourceMgr::Format;
101 };
102
103 /*!
104   \brief Constructor.
105   \param mgr parent resources manager
106   \param fileName resources file name
107 */
108 QtxResourceMgr::Resources::Resources( QtxResourceMgr* mgr, const QString& fileName )
109 : myMgr( mgr ),
110   myFileName( fileName )
111 {
112 }
113
114 /*!
115   \brief Destructor.
116 */
117 QtxResourceMgr::Resources::~Resources()
118 {
119 }
120
121 /*!
122   \brief Get resources file name.
123
124   This file is used to load/save operations.
125
126   \return file name
127   \sa setFile()
128 */
129 QString QtxResourceMgr::Resources::file() const
130 {
131   return myFileName;
132 }
133
134 /*!
135   \brief Set resources file name.
136   \param fn file name
137   \sa file()
138 */
139 void QtxResourceMgr::Resources::setFile( const QString& fn )
140 {
141   myFileName = fn;
142 }
143
144 /*!
145   \brief Get string representation of parameter value.
146   \param sect section name
147   \param name parameter name
148   \param subst if \c true, perform variables substitution
149   \return parameter value or null QString if there is no such parameter
150   \sa setValue(), makeSubstitution()
151 */
152 QString QtxResourceMgr::Resources::value( const QString& sect, const QString& name, const bool subst ) const
153 {
154   QString val;
155
156   if ( hasValue( sect, name ) )
157   {
158     val = section( sect )[name];
159     if ( subst )
160       val = makeSubstitution( val, sect, name );
161   }
162   return val;
163 }
164
165 /*!
166   \brief Set parameter value.
167   \param sect section name
168   \param name parameter name
169   \param val parameter value
170   \sa value(), makeSubstitution()
171 */
172 void QtxResourceMgr::Resources::setValue( const QString& sect, const QString& name, const QString& val )
173 {
174   if ( !mySections.contains( sect ) )
175     mySections.insert( sect, Section() );
176
177   mySections[sect].insert( name, val );
178 }
179
180 /*!
181   \brief Check section existence.
182   \param sect section name
183   \return \c true if section exists
184 */
185 bool QtxResourceMgr::Resources::hasSection( const QString& sect ) const
186 {
187   return mySections.contains( sect );
188 }
189
190 /*!
191   \brief Check parameter existence.
192   \param sect section name
193   \param name parameter name
194   \return \c true if parameter exists in specified section
195 */
196 bool QtxResourceMgr::Resources::hasValue( const QString& sect, const QString& name ) const
197 {
198   return hasSection( sect ) && section( sect ).contains( name );
199 }
200
201 /*!
202   \brief Remove resourcs section.
203   \param sect secton name
204 */
205 void QtxResourceMgr::Resources::removeSection( const QString& sect )
206 {
207   mySections.remove( sect );
208 }
209
210 /*!
211   \brief Remove parameter from the section.
212   \param sect section name
213   \param name parameter name
214 */
215 void QtxResourceMgr::Resources::removeValue( const QString& sect, const QString& name )
216 {
217   if ( !mySections.contains( sect ) )
218     return;
219
220   mySections[sect].remove( name );
221
222   if ( mySections[sect].isEmpty() )
223     mySections.remove( sect );
224 }
225
226 /*!
227   \brief Remove all sections.
228 */
229 void QtxResourceMgr::Resources::clear()
230 {
231   mySections.clear();
232 }
233
234 /*!
235   \brief Get all sections names.
236   \return list of section names
237 */
238 QStringList QtxResourceMgr::Resources::sections() const
239 {
240   return mySections.keys();
241 }
242
243 /*!
244   \brief Get all parameters name in specified section.
245   \param sec section name
246   \return list of settings names
247 */
248 QStringList QtxResourceMgr::Resources::parameters( const QString& sec ) const
249 {
250   if ( !hasSection( sec ) )
251     return QStringList();
252
253   return section( sec ).keys();
254 }
255
256 /*!
257   \brief Get absolute path to the file which name is defined by the parameter.
258
259   The file name is defined by \a name argument, while directory name is retrieved
260   from resources parameter \a prefix of section \a sec. Both directory and file name
261   can be relative. If the directory is relative, it is calculated from the initial
262   resources file name (see file()). Directory parameter can contain environment 
263   variables, which are substituted automatically.
264
265   \param sec section name
266   \param prefix parameter containing directory name
267   \param name file name
268   \return absolute file path or null QString if file does not exist
269   \sa fileName(), file(), makeSubstitution()
270 */
271 QString QtxResourceMgr::Resources::path( const QString& sec, const QString& prefix, const QString& name ) const
272 {
273   QString filePath = fileName( sec, prefix, name );
274   if ( !filePath.isEmpty() )
275   {
276     if ( !QFileInfo( filePath ).exists() )
277       filePath = QString();
278   }
279   return filePath;
280 }
281
282 /*!
283   \brief Get resource manager
284   \return resource manager pointer
285 */
286 QtxResourceMgr* QtxResourceMgr::Resources::resMgr() const
287 {
288   return myMgr;
289 }
290
291 /*!
292   \brief Get resources section by specified name.
293
294   If section does not exist it is created (empty).
295
296   \param sn section name
297   \return resources section
298 */
299 QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn )
300 {
301   if ( !mySections.contains( sn ) )
302     mySections.insert( sn, Section() );
303
304   return mySections[sn];
305 }
306
307 /*!
308   \brief Get resources section by specified name.
309   \param sn section name
310   \return resources section
311 */
312 const QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn ) const
313 {
314   return mySections[sn];
315 }
316
317 /*!
318   \brief Get file path.
319
320   The file name is defined by \a name argument, while directory name is retrieved
321   from resources parameter \a prefix of section \a sec. Both directory and file name
322   can be relative. If the directory is relative, it is calculated from the initial
323   resources file name (see file()). Directory parameter can contain environment 
324   variables, which are substituted automatically.
325   File existence is not checked.
326
327   \param sec section name
328   \param prefix parameter containing directory name
329   \param name file name
330   \return absolute file path or null QString if \a prefix parameter
331           does not exist in section \sec
332   \sa path(), file(), makeSubstitution()
333 */
334 QString QtxResourceMgr::Resources::fileName( const QString& sect, const QString& prefix, const QString& name ) const
335 {
336   QString path;
337   if ( !QFileInfo( name ).isRelative() )
338   {
339     path = name;
340   }
341   else
342   {
343     if ( hasValue( sect, prefix ) )
344     {
345       path = value( sect, prefix, true );
346       if ( !path.isEmpty() )
347       {
348         if ( QFileInfo( path ).isRelative() )
349           path = Qtx::addSlash( Qtx::dir( myFileName, true ) ) + path;
350         
351         path = Qtx::addSlash( path ) + name;
352       }
353     }
354   }
355   if( !path.isEmpty() )
356   {
357     QString fname = QDir::convertSeparators( path );
358     QFileInfo inf( fname );
359     fname = inf.absoluteFilePath();
360     return fname;
361   }
362   return QString();
363 }
364
365 /*!
366   \brief Load and return pixmap from external file.
367   
368   If QtxResourceMgr::isPixmapCached() is \c true then cached pixmap is returned
369   (if it is already loaded), otherwise it is loaded from file.
370   If the file name is invalid, null pixmap is returned.
371
372   \param sect section name
373   \param prefix parameter containing resources directory name
374   \param name pixmap file name
375   \return pixmap loaded from file
376 */
377 QPixmap QtxResourceMgr::Resources::loadPixmap( const QString& sect, const QString& prefix, const QString& name ) const
378 {
379   QString fname = fileName( sect, prefix, name );
380   bool toCache = resMgr() ? resMgr()->isPixmapCached() : false;
381   QPixmap p;
382   if( toCache && myPixmapCache.contains( fname ) )
383     p = myPixmapCache[fname];
384   else
385   {
386     p.load( fname );
387     if( toCache )
388       ( ( QMap<QString,QPixmap>& )myPixmapCache ).insert( fname, p );
389   }
390   return p;
391 }
392
393 /*!
394   \brief Load translator.
395   \param sect section name
396   \param prefix parameter containing resources directory
397   \param name translation file name
398   \return just created and loaded translator or 0 in case of error
399 */
400 QTranslator* QtxResourceMgr::Resources::loadTranslator( const QString& sect, const QString& prefix, const QString& name ) const
401 {
402   QTranslator* trans = new QtxTranslator( 0 );
403   QString fname = QDir::convertSeparators( fileName( sect, prefix, name ) );
404   if ( !trans->load( Qtx::file( fname, false ), Qtx::dir( fname ) ) )
405   {
406     delete trans;
407     trans = 0;
408   }
409   return trans;
410 }
411
412 /*!
413   \brief Substitute variables by their values.
414
415   Environment variable is substituted by its value. For other variables resource
416   manager tries to find value among defined resources parameters.
417
418   \param str string to be processed
419   \param sect section, where variables are searched
420   \param name name of variable which must be ignored during substitution
421   \return processed string (with all substitutions made)
422 */
423 QString QtxResourceMgr::Resources::makeSubstitution( const QString& str, const QString& sect, const QString& name ) const
424 {
425   QString res = str;
426
427   QMap<QString, int> ignoreMap;
428   ignoreMap.insert( name, 0 );
429
430   int start( 0 ), len( 0 );
431   while ( true )
432   {
433     QString envName = Qtx::findEnvVar( res, start, len );
434     if ( envName.isNull() )
435       break;
436
437     QString newStr;
438     if ( ::getenv( envName.toLatin1() ) )
439       newStr = QString( ::getenv( envName.toLatin1() ) );
440
441     if ( newStr.isNull() )
442     {
443       if ( ignoreMap.contains( envName ) )
444       {
445         start += len;
446         continue;
447       }
448
449       if ( hasValue( sect, envName ) )
450         newStr = value( sect, envName, false );
451       ignoreMap.insert( envName, 0 );
452     }
453     res.replace( start, len, newStr );
454   }
455
456   res.replace( "$$", "$" );
457   res.replace( "%%", "%" );
458
459   return res;
460 }
461
462 /*!
463   \class QtxResourceMgr::IniFormat
464   \internal
465   \brief Reader/writer for .ini resources files.
466 */
467
468 class QtxResourceMgr::IniFormat : public Format
469 {
470 public:
471   IniFormat();
472   ~IniFormat();
473
474 protected:
475   virtual bool load( const QString&, QMap<QString, Section>& );
476   virtual bool save( const QString&, const QMap<QString, Section>& );
477
478 private:
479   bool         load( const QString&, QMap<QString, Section>&, QSet<QString>& );
480 };
481
482 /*!
483   \brief Constructor.
484 */
485 QtxResourceMgr::IniFormat::IniFormat()
486 : Format( "ini" )
487 {
488 }
489
490 /*!
491   \brief Destructor.
492 */
493 QtxResourceMgr::IniFormat::~IniFormat()
494 {
495 }
496
497 /*!
498   \brief Load resources from ini-file.
499   \param fname resources file name
500   \param secMap resources map to be filled in
501   \return \c true on success and \c false on error
502 */
503 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap )
504 {
505   QSet<QString> importHistory;
506   return load( fname, secMap, importHistory );
507 }
508
509
510 /*!
511   \brief Load resources from xml-file.
512   \param fname resources file name
513   \param secMap resources map to be filled in
514   \param importHistory list of already imported resources files (to prevent import loops)
515   \return \c true on success or \c false on error
516 */
517 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap, QSet<QString>& importHistory )
518 {
519   QString aFName = fname.trimmed();
520   if ( !QFileInfo( aFName ).exists() )
521   {
522     if ( QFileInfo( aFName + ".ini" ).exists() )
523       aFName += ".ini";
524     else if ( QFileInfo( aFName + ".INI" ).exists() )
525       aFName += ".INI";
526     else
527       return false; // file does not exist
528   }
529   QFileInfo aFinfo( aFName );
530   aFName = aFinfo.canonicalFilePath();
531
532   if ( !importHistory.contains( aFName ) )
533     importHistory.insert( aFName );
534   else
535     return true;   // already imported (prevent import loops)
536
537   QFile file( aFName );
538   if ( !file.open( QFile::ReadOnly ) )
539     return false;  // file is not accessible
540
541   QTextStream ts( &file );
542
543   QString data;
544   int line = 0;
545   bool res = true;
546   QString section;
547
548   QString separator = option( "separator" );
549   if ( separator.isNull() )
550     separator = QString( "=" );
551
552   QString comment = option( "comment" );
553   if ( comment.isNull() )
554     comment = QString( "#" );
555
556   while ( true )
557   {
558     data = ts.readLine();
559     line++;
560
561     if ( data.isNull() )
562       break;
563
564     data = data.trimmed();
565     if ( data.isEmpty() )
566       continue;
567
568     if ( data.startsWith( comment ) )
569       continue;
570
571     QRegExp rx( "^\\[([\\w\\s\\._]*)\\]$" );
572     if ( rx.indexIn( data ) != -1 )
573     {
574       section = rx.cap( 1 );
575       if ( section.isEmpty() )
576       {
577         res = false;
578         qWarning() << "QtxResourceMgr: Empty section in line:" << line;
579       }
580     }
581     else if ( data.contains( separator ) && !section.isEmpty() )
582     {
583       int pos = data.indexOf( separator );
584       QString key = data.left( pos ).trimmed();
585       QString val = data.mid( pos + 1 ).trimmed();
586       secMap[section].insert( key, val );
587     }
588     else if ( section == "import" )
589     {
590       QString impFile = QDir::convertSeparators( Qtx::makeEnvVarSubst( data, Qtx::Always ) );
591       QFileInfo impFInfo( impFile );
592       if ( impFInfo.isRelative() )
593               impFInfo.setFile( aFinfo.absoluteDir(), impFile );
594     
595       QMap<QString, Section> impMap;
596       if ( !load( impFInfo.absoluteFilePath(), impMap, importHistory ) )
597       {
598         qDebug() << "QtxResourceMgr: Error with importing file:" << data;
599       }
600       else 
601       {
602               QMap<QString, Section>::const_iterator it = impMap.constBegin();
603               for ( ; it != impMap.constEnd() ; ++it )
604               { 
605                  if ( !secMap.contains( it.key() ) )
606                  {
607                     // insert full section
608                     secMap.insert( it.key(), it.value() );
609                  }
610                  else
611                  {
612                     // insert all parameters from the section
613                     Section::ConstIterator paramIt = it.value().begin();
614                     for ( ; paramIt != it.value().end() ; ++paramIt )
615                     {
616                        if ( !secMap[it.key()].contains( paramIt.key() ) )
617                                secMap[it.key()].insert( paramIt.key(), paramIt.value() );
618                     }
619                  }
620               }
621       }
622     }
623     else
624     {
625       res = false;
626       if ( section.isEmpty() )
627               qWarning() << "QtxResourceMgr: Current section is empty";
628       else
629               qWarning() << "QtxResourceMgr: Error in line:" << line;
630     }
631   }
632
633   file.close();
634
635   return res; 
636 }
637
638 /*!
639   \brief Save resources to the ini-file.
640   \param fname resources file name
641   \param secMap resources map
642   \return \c true on success and \c false on error
643 */
644 bool QtxResourceMgr::IniFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
645 {
646   if ( !Qtx::mkDir( QFileInfo( fname ).absolutePath() ) )
647     return false;
648
649   QFile file( fname );
650   if ( !file.open( QFile::WriteOnly ) )
651     return false;
652
653   QTextStream ts( &file );
654
655   ts << "# This file is automatically created by SALOME application." << endl;
656   ts << "# Changes made in this file can be lost!" << endl;
657   ts << endl;
658
659   bool res = true;
660   for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end() && res; ++it )
661   {
662     QStringList data( QString( "[%1]" ).arg( it.key() ) );
663     for ( Section::ConstIterator iter = it.value().begin(); iter != it.value().end(); ++iter )
664       data.append( iter.key() + " = " + iter.value() );
665     data.append( "" );
666
667     for ( QStringList::ConstIterator itr = data.begin(); itr != data.end(); ++itr )
668       ts << *itr << endl;
669   }
670
671   file.close();
672
673   return res;
674 }
675
676 /*!
677   \class QtxResourceMgr::XmlFormat
678   \internal
679   \brief Reader/writer for .xml resources files.
680 */
681
682 class QtxResourceMgr::XmlFormat : public Format
683 {
684 public:
685   XmlFormat();
686   ~XmlFormat();
687
688 protected:
689   virtual bool load( const QString&, QMap<QString, Section>& );
690   virtual bool save( const QString&, const QMap<QString, Section>& );
691
692 private:
693   QString      docTag() const;
694   QString      sectionTag() const;
695   QString      parameterTag() const;
696   QString      importTag() const;
697   QString      nameAttribute() const;
698   QString      valueAttribute() const;
699
700   bool         load( const QString&, QMap<QString, Section>&, QSet<QString>& );
701 };
702
703 /*!
704   \brief Constructor.
705 */
706 QtxResourceMgr::XmlFormat::XmlFormat()
707 : Format( "xml" )
708 {
709 }
710
711 /*!
712   \brief Destructor.
713 */
714 QtxResourceMgr::XmlFormat::~XmlFormat()
715 {
716 }
717
718 /*!
719   \brief Load resources from xml-file.
720   \param fname resources file name
721   \param secMap resources map to be filled in
722   \return \c true on success and \c false on error
723 */
724 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap )
725 {
726   QSet<QString> importHistory;
727   return load( fname, secMap, importHistory );
728 }
729
730 /*!
731   \brief Load resources from xml-file.
732   \param fname resources file name
733   \param secMap resources map to be filled in
734   \param importHistory list of already imported resources files (to prevent import loops)
735   \return \c true on success and \c false on error
736 */
737 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap, QSet<QString>& importHistory )
738 {
739   QString aFName = fname.trimmed();
740   if ( !QFileInfo( aFName ).exists() )
741   {
742     if ( QFileInfo( aFName + ".xml" ).exists() )
743       aFName += ".xml";
744     else if ( QFileInfo( aFName + ".XML" ).exists() )
745       aFName += ".XML";
746     else
747       return false; // file does not exist
748   }
749   QFileInfo aFinfo( aFName );
750   aFName = aFinfo.canonicalFilePath();
751
752   if ( !importHistory.contains(  aFName ) )
753     importHistory.insert( aFName );
754   else
755     return true;   // already imported (prevent import loops)
756
757   bool res = false;
758
759 #ifndef QT_NO_DOM
760
761   QFile file( aFName );
762   if ( !file.open( QFile::ReadOnly ) )
763   {
764     qDebug() << "QtxResourceMgr: File is not accessible:" << aFName;
765     return false;
766   }
767
768   QDomDocument doc;
769
770   res = doc.setContent( &file );
771   file.close();
772
773   if ( !res )
774   {
775     qDebug() << "QtxResourceMgr: File is empty:" << aFName;
776     return false;
777   }
778
779   QDomElement root = doc.documentElement();
780   if ( root.isNull() || root.tagName() != docTag() )
781   {
782     qDebug() << "QtxResourceMgr: Invalid root in file:" << aFName;
783     return false;
784   }
785
786   QDomNode sectNode = root.firstChild();
787   while ( res && !sectNode.isNull() )
788   {
789     res = sectNode.isElement();
790     if ( res )
791     {
792       QDomElement sectElem = sectNode.toElement();
793       if ( sectElem.tagName() == sectionTag() && sectElem.hasAttribute( nameAttribute() ) )
794       {
795         QString section = sectElem.attribute( nameAttribute() );
796         QDomNode paramNode = sectNode.firstChild();
797         while ( res && !paramNode.isNull() )
798         {
799           res = paramNode.isElement();
800           if ( res )
801           {
802             QDomElement paramElem = paramNode.toElement();
803             if ( paramElem.tagName() == parameterTag() &&
804                  paramElem.hasAttribute( nameAttribute() ) && paramElem.hasAttribute( valueAttribute() ) )
805             {
806               QString paramName = paramElem.attribute( nameAttribute() );
807               QString paramValue = paramElem.attribute( valueAttribute() );
808               secMap[section].insert( paramName, paramValue );
809             }
810             else
811             {
812               qDebug() << "QtxResourceMgr: Invalid parameter element in file:" << aFName;
813               res = false;
814             }
815           }
816           else
817           {
818             res = paramNode.isComment();
819             if ( !res )
820               qDebug() << "QtxResourceMgr: Node is neither element nor comment in file:" << aFName;
821           }
822
823           paramNode = paramNode.nextSibling();
824         }
825       }
826       else if ( sectElem.tagName() == importTag() && sectElem.hasAttribute( nameAttribute() ) )
827       {
828          QString impFile = QDir::convertSeparators( Qtx::makeEnvVarSubst( sectElem.attribute( nameAttribute() ), Qtx::Always ) );
829               QFileInfo impFInfo( impFile );
830               if ( impFInfo.isRelative() )
831                  impFInfo.setFile( aFinfo.absoluteDir(), impFile );
832
833         QMap<QString, Section> impMap;
834         if ( !load( impFInfo.absoluteFilePath(), impMap, importHistory ) )
835              {
836             qDebug() << "QtxResourceMgr: Error with importing file:" << sectElem.attribute( nameAttribute() );
837              }
838              else
839              {
840                  QMap<QString, Section>::const_iterator it = impMap.constBegin();
841                  for ( ; it != impMap.constEnd() ; ++it )
842                  {
843                     if ( !secMap.contains( it.key() ) )
844                     {
845                        // insert full section
846                        secMap.insert( it.key(), it.value() );
847                     }
848                     else
849                     {
850                        // insert all parameters from the section
851                        Section::ConstIterator paramIt = it.value().begin();
852                        for ( ; paramIt != it.value().end() ; ++paramIt )
853                        {
854                                if ( !secMap[it.key()].contains( paramIt.key() ) )
855                                   secMap[it.key()].insert( paramIt.key(), paramIt.value() );
856                        }
857                     }
858                  }
859          }
860       }
861       else
862       {
863          qDebug() << "QtxResourceMgr: Invalid section in file:" << aFName;
864          res = false;
865       }
866     }
867     else
868     {
869       res = sectNode.isComment(); // if it's a comment -- let it be, pass it..
870       if ( !res )
871         qDebug() << "QtxResourceMgr: Node is neither element nor comment in file:" << aFName;
872     }
873
874     sectNode = sectNode.nextSibling();
875   }
876
877 #endif
878   
879   if ( res )
880     qDebug() << "QtxResourceMgr: File" << fname << "is loaded successfully";
881   return res;
882 }
883
884 /*!
885   \brief Save resources to the xml-file.
886   \param fname resources file name
887   \param secMap resources map
888   \return \c true on success and \c false on error
889 */
890 bool QtxResourceMgr::XmlFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
891 {
892   bool res = false;
893
894 #ifndef QT_NO_DOM
895
896   if ( !Qtx::mkDir( QFileInfo( fname ).absolutePath() ) )
897     return false;
898
899   QFile file( fname );
900   if ( !file.open( QFile::WriteOnly ) )
901     return false;
902
903   QDomDocument doc( docTag() );
904   QDomComment comment = doc.createComment( "\nThis file is automatically created by SALOME application.\nChanges made in this file can be lost!\n" );
905   doc.appendChild( comment );
906   QDomElement root = doc.createElement( docTag() );
907   doc.appendChild( root );
908
909   for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end(); ++it )
910   {
911     QDomElement sect = doc.createElement( sectionTag() );
912     sect.setAttribute( nameAttribute(), it.key() );
913     root.appendChild( sect );
914     for ( Section::ConstIterator iter = it.value().begin(); iter != it.value().end(); ++iter )
915     {
916       QDomElement val = doc.createElement( parameterTag() );
917       val.setAttribute( nameAttribute(), iter.key() );
918       val.setAttribute( valueAttribute(), iter.value() );
919       sect.appendChild( val );
920     }
921   }
922
923   QTextStream ts( &file );
924   QStringList docStr = doc.toString().split( "\n" );
925   for ( QStringList::ConstIterator itr = docStr.begin(); itr != docStr.end(); ++itr )
926     ts << *itr << endl;
927
928   file.close();
929
930 #endif
931
932   return res;
933 }
934
935 /*!
936   \brief Get document tag name
937   \return XML document tag name
938 */
939 QString QtxResourceMgr::XmlFormat::docTag() const
940 {
941   QString tag = option( "doc_tag" );
942   if ( tag.isEmpty() )
943     tag = QString( "document" );
944   return tag;
945 }
946
947 /*!
948   \brief Get section tag name
949   \return XML section tag name
950 */
951 QString QtxResourceMgr::XmlFormat::sectionTag() const
952 {
953   QString tag = option( "section_tag" );
954   if ( tag.isEmpty() )
955     tag = QString( "section" );
956   return tag;
957 }
958
959 /*!
960   \brief Get parameter tag name
961   \return XML parameter tag name
962 */
963 QString QtxResourceMgr::XmlFormat::parameterTag() const
964 {
965   QString tag = option( "parameter_tag" );
966   if ( tag.isEmpty() )
967     tag = QString( "parameter" );
968   return tag;
969 }
970
971 /*!
972   \brief Get import tag name
973   \return XML import tag name
974 */
975 QString QtxResourceMgr::XmlFormat::importTag() const
976 {
977   QString tag = option( "import_tag" );
978   if ( tag.isEmpty() )
979    tag = QString( "import" );
980   return tag;
981 }
982
983 /*!
984   \brief Get parameter tag's "name" attribute name
985   \return XML parameter tag's "name" attribute name
986 */
987 QString QtxResourceMgr::XmlFormat::nameAttribute() const
988 {
989   QString str = option( "name_attribute" );
990   if ( str.isEmpty() )
991     str = QString( "name" );
992   return str;
993 }
994
995 /*!
996   \brief Get parameter tag's "value" attribute name
997   \return XML parameter tag's "value" attribute name
998 */
999 QString QtxResourceMgr::XmlFormat::valueAttribute() const
1000 {
1001   QString str = option( "value_attribute" );
1002   if ( str.isEmpty() )
1003     str = QString( "value" );
1004   return str;
1005 }
1006
1007 /*!
1008   \class QtxResourceMgr::Format
1009   \brief Generic resources files reader/writer class.
1010 */
1011
1012 /*!
1013   \brief Constructor.
1014   \param fmt format name (for example, "xml" or "ini")
1015 */
1016 QtxResourceMgr::Format::Format( const QString& fmt )
1017 : myFmt( fmt )
1018 {
1019 }
1020
1021 /*!
1022   \brief Destructor
1023 */
1024 QtxResourceMgr::Format::~Format()
1025 {
1026 }
1027
1028 /*!
1029   \brief Get the format name.
1030   \return format name
1031 */
1032 QString QtxResourceMgr::Format::format() const
1033 {
1034   return myFmt;
1035 }
1036
1037 /*!
1038   \brief Get options names.
1039   \return list of the format options
1040 */
1041 QStringList QtxResourceMgr::Format::options() const
1042 {
1043   return myOpt.keys();
1044 }
1045
1046 /*!
1047   \brief Get the value of the option with specified name.
1048
1049   If option doesn't exist then null QString is returned.
1050          
1051   \param opt option name
1052   \return option value
1053 */
1054 QString QtxResourceMgr::Format::option( const QString& opt ) const
1055 {
1056   QString val;
1057   if ( myOpt.contains( opt ) )
1058     val = myOpt[opt];
1059   return val;
1060 }
1061
1062 /*!
1063   \brief Set the value of the option with specified name.
1064   \param opt option name
1065   \param val option value
1066 */
1067 void QtxResourceMgr::Format::setOption( const QString& opt, const QString& val )
1068 {
1069   myOpt.insert( opt, val );
1070 }
1071
1072 /*!
1073   \brief Load resources from the resource file.
1074   \param res resources object
1075   \return \c true on success and \c false on error
1076 */
1077 bool QtxResourceMgr::Format::load( Resources* res )
1078 {
1079   if ( !res )
1080     return false;
1081
1082   QMap<QString, Section> sections;
1083   bool status = load( res->myFileName, sections );
1084   if ( status )
1085     res->mySections = sections;
1086   else
1087     qDebug() << "QtxResourceMgr: Can't load resource file:" << res->myFileName;
1088
1089   return status;
1090 }
1091
1092 /*!
1093   \brief Save resources to the resource file.
1094   \param res resources object
1095   \return \c true on success and \c false on error
1096 */
1097 bool QtxResourceMgr::Format::save( Resources* res )
1098 {
1099   if ( !res )
1100     return false;
1101
1102   Qtx::mkDir( Qtx::dir( res->myFileName ) );
1103
1104   QtxResourceMgr* mgr = res->resMgr();
1105   QString name = mgr ? mgr->userFileName( mgr->appName(), false ) : res->myFileName;
1106   return save( name, res->mySections );
1107 }
1108
1109 /*!
1110   \fn virtual bool QtxResourceMgr::Format::load( const QString& fname,
1111                                                  QMap<QString, Section>& secMap )
1112   \brief Load resources from the specified resources file.
1113
1114   Should be implemented in the successors.
1115
1116   \param fname resources file name
1117   \param secMap resources map to be filled in
1118   \return \c true on success and \c false on error
1119 */
1120
1121 /*!
1122  \fn virtual bool QtxResourceMgr::Format::save( const QString& fname, 
1123                                                 const QMap<QString, Section>& secMap )
1124
1125   \brief Save resources to the specified resources file.
1126
1127   Should be implemented in the successors.
1128
1129   \param fname resources file name
1130   \param secMap resources map
1131   \return \c true on success and \c false on error
1132 */
1133
1134 /*!
1135   \class QtxResourceMgr
1136   \brief Application resources manager.
1137
1138   This class can be used to define settings, save/load settings and 
1139   application preferences to the resource file(s), load translation files
1140   (internationalization mechanism), load pixmaps and other resources from
1141   external files, etc.
1142
1143   Currently it supports .ini and .xml resources file formats. To implement
1144   own resources file format, inherit from the Format class and implement virtual
1145   Format::load() and Format::save() methods.
1146
1147   Resources manager is initialized by the (symbolic) name of the application.
1148   The parameter \a resVarTemplate specifies the template for the environment
1149   variable which should point to the resource directory or list of directories.
1150   Environment variable  name is calculated by substitution of "%1" substring in
1151   the \a resVarTemplate parameter (if it contains such substring) by the 
1152   application name (\a appName).
1153   By default, \a resVarTemplate is set to "%1Resources". For example, if the application name
1154   is "MyApp", the environment variable "MyAppResources" will be inspected in this case.
1155   
1156   Resource manager can handle several global application configuration files and
1157   one user configuration file. Location of global configuration files is defined
1158   by the environment variable (see above) and these files are always read-only.
1159   The name of the global configuration files is retrieved by calling virtual method
1160   globalFileName() which can be redefined in the QtxResourceMgr class successors.
1161   User configuration file always situated in the user's home directory. It's name
1162   is defined by calling virtual method userFileName() which can be also redefined
1163   in the QtxResourceMgr class successors. This is the only file which the preferences
1164   changed by the user during the application session are written to (usually 
1165   when the application closes).
1166
1167   Resources environment variable should contain one or several resource directories
1168   (separated by ";" symbol on Windows and ":" or ";" on Linux). Each resource directory 
1169   can contain application global configuration file. The user configuration file has
1170   the highest priority, for the global configuration files the priority is decreasing from
1171   left to right, i.e. the first directory in the directoris list, defined by the 
1172   resources environment variable has higher priority. Priority has the meaning when
1173   searching requested resources (application preference, pixmap file name, translation
1174   file, etc).
1175
1176   When retrieving preferences, it is sometimes helpful to ignore values coming from the
1177   user preference file and take into account only global preferences.
1178   To do this, use setWorkingMode() method passing QtxResourceMgr::IgnoreUserValues enumerator
1179   as parameter.
1180
1181   Resources manager operates with such terms like options, sections and parameters. 
1182   Parametets are named application resources, for example, application preferences like
1183   integer, double, boolean or string values, pictures, font and color definitions, etc.
1184   Parameters are organized inside the resources files into the named groups - sections.
1185   Options are special kind of resoures which allow customizing resource files interpreting.
1186   For example, by default language settings are defined in the resource file in the
1187   section "language". It is possible to change this section name by setting "language" 
1188   option to another value (see setOption()).
1189   
1190   Retrieving preferences values can be done by using one of value() methods, each returns
1191   \c true if the corresponding preference is found. Another way is to use integerValue(),
1192   doubleValue(), etc methods, which allow specifying default value which is used if the
1193   specified preference is not found. Removing of preferences or sections can be done using
1194   remove(const QString& sect) or remove(const QString& sect, const QString& name) methods.
1195   To add the preference or to change exiting preference value use setValue() methods family.
1196   Methods hasSection() and hasValue() can be used to check existence of section or
1197   preference (in the specified section). List of all sections can be retrieved with the
1198   sections() method, and list of all settings names in some specified section can be 
1199   obtained with parameters() method.
1200
1201   Pixmaps can be loaded with the loadPixmap() methods. If the specified pixmap is not found,
1202   the default one is returned. Default pixmap can be set by setDefaultPixmap().
1203
1204   One of the key feature of the resources manager is support of application 
1205   internationalization mechanism. Translation files for the specified language can be loaded
1206   with loadLanguage() method.
1207 */
1208
1209 /*!
1210   \brief Constructs the resource manager.
1211   \param appName application name
1212   \param resVarTemplate resource environment variable pattern
1213 */
1214 QtxResourceMgr::QtxResourceMgr( const QString& appName, const QString& resVarTemplate )
1215 : myAppName( appName ),
1216   myCheckExist( true ),
1217   myDefaultPix( 0 ),
1218   myIsPixmapCached( true ),
1219   myHasUserValues( true ),
1220   myWorkingMode( AllowUserValues )
1221 {
1222   QString envVar = !resVarTemplate.isEmpty() ? resVarTemplate : QString( "%1Resources" );
1223   if ( envVar.contains( "%1" ) )
1224     envVar = envVar.arg( appName );
1225
1226   QString dirs;
1227   if ( ::getenv( envVar.toLatin1() ) )
1228     dirs = ::getenv( envVar.toLatin1() );
1229 #ifdef WIN32
1230   QString dirsep = ";";      // for Windows: ";" is used as directories separator
1231 #else
1232   QString dirsep = "[:|;]";  // for Linux: both ":" and ";" can be used
1233 #endif
1234   setDirList( dirs.split( QRegExp( dirsep ), QString::SkipEmptyParts ) );
1235
1236   installFormat( new XmlFormat() );
1237   installFormat( new IniFormat() );
1238
1239   setOption( "translators", QString( "%P_msg_%L.qm|%P_images.qm" ) );
1240 }
1241
1242 /*!
1243   \brief Destructor.
1244   
1245   Destroy the resource manager and free allocated memory.
1246 */
1247 QtxResourceMgr::~QtxResourceMgr()
1248 {
1249   QStringList prefList = myTranslator.keys();
1250   for ( QStringList::ConstIterator it = prefList.begin(); it != prefList.end(); ++it )
1251     removeTranslators( *it );
1252
1253   qDeleteAll( myResources );
1254   qDeleteAll( myFormats );
1255
1256   delete myDefaultPix;
1257 }
1258
1259 /*!
1260   \brief Get the application name.
1261   \return application name
1262 */
1263 QString QtxResourceMgr::appName() const
1264 {
1265   return myAppName;
1266 }
1267
1268 /*!
1269   \brief Get the "check existance" flag
1270
1271   If this flag is \c true then preference can be set (with setValue() method) 
1272   only if it doesn't exist or if the value is changed.
1273
1274   \return \c true if "check existance" flag is set
1275 */
1276 bool QtxResourceMgr::checkExisting() const
1277 {
1278   return myCheckExist;
1279 }
1280
1281 /*!
1282   \brief Set the "check existance" flag.
1283   \param on new flag value
1284 */
1285 void QtxResourceMgr::setCheckExisting( const bool on )
1286 {
1287   myCheckExist = on;
1288 }
1289
1290 /*!
1291   \brief Get the resource directories list.
1292
1293   Home user directory (where the user application configuration file is situated)
1294   is not included. This is that directories list defined by the application
1295   resources environment variable.
1296
1297   \return list of directories names
1298 */
1299 QStringList QtxResourceMgr::dirList() const
1300 {
1301   return myDirList;
1302 }
1303
1304 /*!
1305   \brief Initialise resources manager.
1306
1307   Prepare the resources containers and load resources (if \a autoLoad is \c true).
1308
1309   \param autoLoad if \c true (default) then all resources are loaded
1310 */
1311 void QtxResourceMgr::initialize( const bool autoLoad ) const
1312 {
1313   if ( !myResources.isEmpty() )
1314     return;
1315
1316   QtxResourceMgr* that = (QtxResourceMgr*)this;
1317
1318   if ( !userFileName( appName() ).isEmpty() )
1319     that->myResources.append( new Resources( that, userFileName( appName() ) ) );
1320
1321   that->myHasUserValues = myResources.count() > 0;
1322
1323   for ( QStringList::ConstIterator it = myDirList.begin(); it != myDirList.end(); ++it )
1324   {
1325     QString path = Qtx::addSlash( *it ) + globalFileName( appName() );
1326     that->myResources.append( new Resources( that, path ) );
1327   }
1328
1329   if ( autoLoad )
1330     that->load();
1331 }
1332
1333 /*!
1334   \brief Get "cached pixmaps" option value.
1335
1336   Resources manager allows possibility to cache loaded pixmaps that allow to
1337   improve application performance. This feature is turned on by default - all 
1338   loaded pixmaps are stored in the internal map. Switching of this feature on/off
1339   can be done by setIsPixmapCached() method.
1340
1341   \return \c true if pixmap cache is turned on
1342   \sa setIsPixmapCached()
1343 */
1344 bool QtxResourceMgr::isPixmapCached() const
1345 {
1346   return myIsPixmapCached;
1347 }
1348
1349 /*!
1350   \brief Switch "cached pixmaps" option on/off.
1351   \param on enable pixmap cache if \c true and disable it if \c false
1352   \sa isPixmapCached()
1353 */
1354 void QtxResourceMgr::setIsPixmapCached( const bool on )
1355 {
1356   myIsPixmapCached = on;
1357 }
1358
1359 /*!
1360   \brief Remove all resources from the resources manager.
1361 */
1362 void QtxResourceMgr::clear()
1363 {
1364   for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
1365     (*it)->clear();
1366 }
1367
1368 /*!
1369   \brief Get current working mode.
1370   
1371   \return current working mode
1372   \sa setWorkingMode(), value(), hasValue(), hasSection(), setValue()
1373 */
1374 QtxResourceMgr::WorkingMode QtxResourceMgr::workingMode() const
1375 {
1376   return myWorkingMode;
1377 }
1378
1379 /*!
1380   \brief Set resource manager's working mode.
1381
1382   The resource manager can operate in the following working modes:
1383   * AllowUserValues  : methods values(), hasValue(), hasSection() take into account user values (default)
1384   * IgnoreUserValues : methods values(), hasValue(), hasSection() do not take into account user values
1385
1386   Note, that setValue() method always put the value to the user settings file.
1387   
1388   \param mode new working mode
1389   \sa workingMode(), value(), hasValue(), hasSection(), setValue()
1390 */
1391 void QtxResourceMgr::setWorkingMode( WorkingMode mode )
1392 {
1393   myWorkingMode = mode;
1394 }
1395
1396 /*!
1397   \brief Get interger parameter value.
1398   \param sect section name
1399   \param name parameter name
1400   \param iVal parameter to return resulting integer value
1401   \return \c true if parameter is found and \c false if parameter is not found
1402           (in this case \a iVal value is undefined)
1403 */
1404 bool QtxResourceMgr::value( const QString& sect, const QString& name, int& iVal ) const
1405 {
1406   QString val;
1407   if ( !value( sect, name, val, true ) )
1408     return false;
1409
1410   bool ok;
1411   iVal = val.toInt( &ok );
1412
1413   return ok;
1414 }
1415
1416 /*!
1417   \brief Get double parameter value.
1418   \param sect section name
1419   \param name parameter name
1420   \param dVal parameter to return resulting double value
1421   \return \c true if parameter is found and \c false if parameter is not found
1422           (in this case \a dVal value is undefined)
1423 */
1424 bool QtxResourceMgr::value( const QString& sect, const QString& name, double& dVal ) const
1425 {
1426   QString val;
1427   if ( !value( sect, name, val, true ) )
1428     return false;
1429
1430   bool ok;
1431   dVal = val.toDouble( &ok );
1432
1433   return ok;
1434 }
1435
1436 /*!
1437   \brief Get boolean parameter value.
1438   \param sect section name
1439   \param name parameter name
1440   \param bVal parameter to return resulting boolean value
1441   \return \c true if parameter is found and \c false if parameter is not found
1442           (in this case \a bVal value is undefined)
1443 */
1444 bool QtxResourceMgr::value( const QString& sect, const QString& name, bool& bVal ) const
1445 {
1446   QString val;
1447   if ( !value( sect, name, val, true ) )
1448     return false;
1449
1450   static QMap<QString, bool> boolMap;
1451   if ( boolMap.isEmpty() )
1452   {
1453     boolMap["true"]  = boolMap["yes"] = boolMap["on"]  = true;
1454     boolMap["false"] = boolMap["no"]  = boolMap["off"] = false;
1455   }
1456
1457   val = val.toLower();
1458   bool res = boolMap.contains( val );
1459   if ( res )
1460     bVal = boolMap[val];
1461   else
1462   {
1463     double num = val.toDouble( &res );
1464     if ( res )
1465       bVal = num != 0;
1466   }
1467
1468   return res;
1469 }
1470
1471 /*!
1472   \brief Get color parameter value.
1473   \param sect section name
1474   \param name parameter name
1475   \param cVal parameter to return resulting color value
1476   \return \c true if parameter is found and \c false if parameter is not found
1477           (in this case \a cVal value is undefined)
1478 */
1479 bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cVal ) const
1480 {
1481   QString val;
1482   if ( !value( sect, name, val, true ) )
1483     return false;
1484
1485   return Qtx::stringToColor( val, cVal );
1486 }
1487
1488 /*!
1489   \brief Get font parameter value.
1490   \param sect section name
1491   \param name parameter name
1492   \param fVal parameter to return resulting font value
1493   \return \c true if parameter is found and \c false if parameter is not found
1494           (in this case \a fVal value is undefined)
1495 */
1496 bool QtxResourceMgr::value( const QString& sect, const QString& name, QFont& fVal ) const
1497 {
1498   QString val;
1499   if ( !value( sect, name, val, true ) )
1500     return false;
1501
1502   QStringList fontDescr = val.split( ",", QString::SkipEmptyParts );
1503
1504   if ( fontDescr.count() < 2 )
1505     return false;
1506
1507   QString family = fontDescr[0];
1508   if ( family.isEmpty() )
1509     return false;
1510
1511   fVal = QFont( family );
1512
1513   for ( int i = 1; i < (int)fontDescr.count(); i++ )
1514   {
1515     QString curval = fontDescr[i].trimmed().toLower();
1516     if ( curval == QString( "bold" ) )
1517       fVal.setBold( true );
1518     else if ( curval == QString( "italic" ) )
1519       fVal.setItalic( true );
1520     else if ( curval == QString( "underline" ) )
1521       fVal.setUnderline( true );
1522     else if ( curval == QString( "shadow" ) || curval == QString( "overline" ) )
1523       fVal.setOverline( true );
1524     else
1525     {
1526       bool isOk = false;
1527       int ps = curval.toInt( &isOk );
1528       if ( isOk )
1529         fVal.setPointSize( ps );
1530     }
1531   }
1532
1533   return true;
1534 }
1535
1536 /*!
1537   \brief Get byte array parameter value.
1538   \param sect section name
1539   \param name parameter name
1540   \param baVal parameter to return resulting byte array value
1541   \return \c true if parameter is found and \c false if parameter is not found
1542           (in this case \a baVal value is undefined)
1543 */
1544 bool QtxResourceMgr::value( const QString& sect, const QString& name, QByteArray& baVal ) const
1545 {
1546   QString val;
1547   if ( !value( sect, name, val, true ) )
1548     return false;
1549
1550   baVal.clear();
1551   QStringList lst = val.split( QRegExp( "[\\s|,]" ), QString::SkipEmptyParts );
1552   for ( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it )
1553   {
1554     int base = 10;
1555     QString str = *it;
1556     if ( str.startsWith( "#" ) )
1557     {
1558       base = 16;
1559       str = str.mid( 1 );
1560     }
1561     bool ok = false;
1562     int num = str.toInt( &ok, base );
1563     if ( !ok || num < 0 || num > 255 )
1564       continue;
1565
1566     baVal.append( (char)num );
1567   }
1568   return !baVal.isEmpty();
1569 }
1570
1571 /*!
1572   \brief Get linear gradient parameter value.
1573   \param sect section name
1574   \param name parameter name
1575   \param gVal parameter to return resulting linear gradient value
1576   \return \c true if parameter is found and \c false if parameter is not found
1577           (in this case \a gVal value is undefined)
1578 */
1579 bool QtxResourceMgr::value( const QString& sect, const QString& name, QLinearGradient& gVal ) const
1580 {
1581   QString val;
1582   if ( !value( sect, name, val, true ) )
1583     return false;
1584
1585   return Qtx::stringToLinearGradient( val, gVal );
1586 }
1587
1588 /*!
1589   \brief Get radial gradient parameter value.
1590   \param sect section name
1591   \param name parameter name
1592   \param gVal parameter to return resulting radial gradient value
1593   \return \c true if parameter is found and \c false if parameter is not found
1594           (in this case \a gVal value is undefined)
1595 */
1596 bool QtxResourceMgr::value( const QString& sect, const QString& name, QRadialGradient& gVal ) const
1597 {
1598   QString val;
1599   if ( !value( sect, name, val, true ) )
1600     return false;
1601
1602   return Qtx::stringToRadialGradient( val, gVal );
1603 }
1604
1605 /*!
1606   \brief Get conical gradient parameter value.
1607   \param sect section name
1608   \param name parameter name
1609   \param gVal parameter to return resulting conical gradient value
1610   \return \c true if parameter is found and \c false if parameter is not found
1611           (in this case \a gVal value is undefined)
1612 */
1613 bool QtxResourceMgr::value( const QString& sect, const QString& name, QConicalGradient& gVal ) const
1614 {
1615   QString val;
1616   if ( !value( sect, name, val, true ) )
1617     return false;
1618
1619   return Qtx::stringToConicalGradient( val, gVal );
1620 }
1621
1622 /*!
1623   \brief Get background parameter value.
1624   \param sect section name
1625   \param name parameter name
1626   \param bgVal parameter to return resulting background value
1627   \return \c true if parameter is found and \c false if parameter is not found
1628           (in this case \a bgVal value is undefined)
1629 */
1630 bool QtxResourceMgr::value( const QString& sect, const QString& name, Qtx::BackgroundData& bgVal ) const
1631 {
1632   QString val;
1633   if ( !value( sect, name, val, true ) )
1634     return false;
1635
1636   bgVal = Qtx::stringToBackground( val );
1637   return bgVal.isValid();
1638 }
1639
1640 /*!
1641   \brief Get string parameter value (native format).
1642   \param sect section name
1643   \param name parameter name
1644   \param val parameter to return resulting byte array value
1645   \param subst if \c true perform environment variables substitution
1646   \return \c true if parameter is found and \c false if parameter is not found
1647           (in this case \a val value is undefined)
1648 */
1649 bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& val, const bool subst ) const
1650 {
1651   initialize();
1652
1653   bool ok = false;
1654  
1655   ResList::ConstIterator it = myResources.begin();
1656   if ( myHasUserValues && workingMode() == IgnoreUserValues )
1657     ++it;
1658
1659   for ( ; it != myResources.end() && !ok; ++it )
1660   {
1661     ok = (*it)->hasValue( sect, name );
1662     if ( ok )
1663       val = (*it)->value( sect, name, subst );
1664   }
1665
1666   return ok;
1667 }
1668
1669 /*!
1670   \brief Get interger parameter value.
1671
1672   If the specified parameter is not found or can not be converted to the integer value,
1673   the specified default value is returned instead.
1674
1675   \param sect section name
1676   \param name parameter name
1677   \param def default value
1678   \return parameter value (or default value if parameter is not found)
1679 */
1680 int QtxResourceMgr::integerValue( const QString& sect, const QString& name, const int def ) const
1681 {
1682   int val;
1683   if ( !value( sect, name, val ) )
1684     val = def;
1685   return val;
1686 }
1687
1688 /*!
1689   \brief Get double parameter value.
1690
1691   If the specified parameter is not found or can not be converted to the double value,
1692   the specified default value is returned instead.
1693
1694   \param sect section name
1695   \param name parameter name
1696   \param def default value
1697   \return parameter value (or default value if parameter is not found)
1698 */
1699 double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, const double def ) const
1700 {
1701   double val;
1702   if ( !value( sect, name, val ) )
1703     val = def;
1704   return val;
1705 }
1706
1707 /*!
1708   \brief Get boolean parameter value.
1709
1710   If the specified parameter is not found or can not be converted to the boolean value,
1711   the specified default value is returned instead.
1712
1713   \param sect section name
1714   \param name parameter name
1715   \param def default value
1716   \return parameter value (or default value if parameter is not found)
1717 */
1718 bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, const bool def ) const
1719 {
1720   bool val;
1721   if ( !value( sect, name, val ) )
1722     val = def;
1723   return val;
1724 }
1725
1726 /*!
1727   \brief Get font parameter value.
1728
1729   If the specified parameter is not found or can not be converted to the font value,
1730   the specified default value is returned instead.
1731
1732   \param sect section name
1733   \param name parameter name
1734   \param def default value
1735   \return parameter value (or default value if parameter is not found)
1736 */
1737 QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const QFont& def ) const
1738 {
1739   QFont font;
1740   if( !value( sect, name, font ) )
1741     font = def;
1742   return font;
1743 }
1744
1745 /*!
1746   \brief Get color parameter value.
1747
1748   If the specified parameter is not found or can not be converted to the color value,
1749   the specified default value is returned instead.
1750
1751   \param sect section name
1752   \param name parameter name
1753   \param def default value
1754   \return parameter value (or default value if parameter is not found)
1755 */
1756 QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, const QColor& def ) const
1757 {
1758   QColor val;
1759   if ( !value( sect, name, val ) )
1760     val = def;
1761   return val;
1762 }
1763
1764 /*!
1765   \brief Get string parameter value.
1766
1767   If the specified parameter is not found, the specified default value is returned instead.
1768
1769   \param sect section name
1770   \param name parameter name
1771   \param def default value
1772   \return parameter value (or default value if parameter is not found)
1773 */
1774 QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, const QString& def ) const
1775 {
1776   QString val;
1777   if ( !value( sect, name, val ) )
1778     val = def;
1779   return val;
1780 }
1781
1782 /*!
1783   \brief Get byte array parameter value.
1784
1785   If the specified parameter is not found, the specified default value is returned instead.
1786
1787   \param sect section name
1788   \param name parameter name
1789   \param def default value
1790   \return parameter value (or default value if parameter is not found)
1791 */
1792 QByteArray QtxResourceMgr::byteArrayValue( const QString& sect, const QString& name, const QByteArray& def ) const
1793 {
1794   QByteArray val;
1795   if ( !value( sect, name, val ) )
1796     val = def;
1797   return val;
1798 }
1799
1800 /*!
1801   \brief Get linear gradient parameter value.
1802
1803   If the specified parameter is not found, the specified default value is returned instead.
1804
1805   \param sect section name
1806   \param name parameter name
1807   \param def default value
1808   \return parameter value (or default value if parameter is not found)
1809 */
1810 QLinearGradient QtxResourceMgr::linearGradientValue( const QString& sect, const QString& name, const QLinearGradient& def ) const
1811 {
1812   QLinearGradient val;
1813   if ( !value( sect, name, val ) )
1814     val = def;
1815   return val;
1816 }
1817
1818 /*!
1819   \brief Get radial gradient parameter value.
1820
1821   If the specified parameter is not found, the specified default value is returned instead.
1822
1823   \param sect section name
1824   \param name parameter name
1825   \param def default value
1826   \return parameter value (or default value if parameter is not found)
1827 */
1828 QRadialGradient QtxResourceMgr::radialGradientValue( const QString& sect, const QString& name, const QRadialGradient& def ) const
1829 {
1830   QRadialGradient val;
1831   if ( !value( sect, name, val ) )
1832     val = def;
1833   return val;
1834 }
1835
1836 /*!
1837   \brief Get conical gradient parameter value.
1838
1839   If the specified parameter is not found, the specified default value is returned instead.
1840
1841   \param sect section name
1842   \param name parameter name
1843   \param def default value
1844   \return parameter value (or default value if parameter is not found)
1845 */
1846 QConicalGradient QtxResourceMgr::conicalGradientValue( const QString& sect, const QString& name, const QConicalGradient& def ) const
1847 {
1848   QConicalGradient val;
1849   if ( !value( sect, name, val ) )
1850     val = def;
1851   return val;
1852 }
1853
1854 /*!
1855   \brief Get background parameter value.
1856
1857   If the specified parameter is not found, the specified default value is returned instead.
1858
1859   \param sect section name
1860   \param name parameter name
1861   \param def default value
1862   \return parameter value (or default value if parameter is not found)
1863 */
1864 Qtx::BackgroundData QtxResourceMgr::backgroundValue( const QString& sect, const QString& name, const Qtx::BackgroundData& def ) const
1865 {
1866   Qtx::BackgroundData val;
1867   if ( !value( sect, name, val ) )
1868     val = def;
1869   return val;
1870 }
1871
1872 /*!
1873   \brief Check parameter existence.
1874   \param sect section name
1875   \param name parameter name
1876   \return \c true if parameter exists in specified section
1877 */
1878 bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
1879 {
1880   initialize();
1881
1882   bool ok = false;
1883
1884   ResList::ConstIterator it = myResources.begin();
1885   if ( myHasUserValues && workingMode() == IgnoreUserValues )
1886     ++it;
1887
1888   for ( ; it != myResources.end() && !ok; ++it )
1889     ok = (*it)->hasValue( sect, name );
1890
1891   return ok;
1892 }
1893
1894 /*!
1895   \brief Check section existence.
1896   \param sect section name
1897   \return \c true if section exists
1898 */
1899 bool QtxResourceMgr::hasSection( const QString& sect ) const
1900 {
1901   initialize();
1902
1903   bool ok = false;
1904
1905   ResList::ConstIterator it = myResources.begin();
1906   if ( myHasUserValues && workingMode() == IgnoreUserValues )
1907     ++it;
1908
1909   for ( ; it != myResources.end() && !ok; ++it )
1910     ok = (*it)->hasSection( sect );
1911
1912   return ok;
1913 }
1914
1915 /*!
1916   \brief Set integer parameter value.
1917   \param sect section name
1918   \param name parameter name
1919   \param val parameter value
1920 */
1921 void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val )
1922 {
1923   int res;
1924   if ( checkExisting() && value( sect, name, res ) && res == val )
1925     return;
1926
1927   setResource( sect, name, QString::number( val ) );
1928 }
1929
1930 /*!
1931   \brief Set double parameter value.
1932   \param sect section name
1933   \param name parameter name
1934   \param val parameter value
1935 */
1936 void QtxResourceMgr::setValue( const QString& sect, const QString& name, double val )
1937 {
1938   double res;
1939   if ( checkExisting() && value( sect, name, res ) && res == val )
1940     return;
1941
1942   setResource( sect, name, QString::number( val, 'g', 12 ) );
1943 }
1944
1945 /*!
1946   \brief Set boolean parameter value.
1947   \param sect section name
1948   \param name parameter name
1949   \param val parameter value
1950 */
1951 void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool val )
1952 {
1953   bool res;
1954   if ( checkExisting() && value( sect, name, res ) && res == val )
1955     return;
1956
1957   setResource( sect, name, QString( val ? "true" : "false" ) );
1958 }
1959
1960 /*!
1961   \brief Set color parameter value.
1962   \param sect section name
1963   \param name parameter name
1964   \param val parameter value
1965 */
1966 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QColor& val )
1967 {
1968   QColor res;
1969   if ( checkExisting() && value( sect, name, res ) && res == val )
1970     return;
1971
1972   setResource( sect, name, Qtx::colorToString( val ) );
1973 }
1974
1975 /*!
1976   \brief Set font parameter value.
1977   \param sect section name
1978   \param name parameter name
1979   \param val parameter value
1980 */
1981 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QFont& val )
1982 {
1983   QFont res;
1984   if ( checkExisting() && value( sect, name, res ) && res == val )
1985     return;
1986
1987   QStringList fontDescr;
1988   fontDescr.append( val.family() );
1989   if ( val.bold() )
1990     fontDescr.append( "Bold" );
1991   if ( val.italic() )
1992     fontDescr.append( "Italic" );
1993   if ( val.underline() )
1994     fontDescr.append( "Underline" );
1995   if ( val.overline() )
1996     fontDescr.append( "Overline" );
1997   fontDescr.append( QString( "%1" ).arg( val.pointSize() ) );
1998
1999   setResource( sect, name, fontDescr.join( "," ) );
2000 }
2001
2002 /*!
2003   \brief Set string parameter value.
2004   \param sect section name
2005   \param name parameter name
2006   \param val parameter value
2007 */
2008 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QString& val )
2009 {
2010   QString res;
2011   if ( checkExisting() && value( sect, name, res ) && res == val )
2012     return;
2013
2014   setResource( sect, name, val );
2015 }
2016
2017 /*!
2018   \brief Set byte array parameter value.
2019   \param sect section name
2020   \param name parameter name
2021   \param val parameter value
2022 */
2023 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QByteArray& val )
2024 {
2025   QByteArray res;
2026   if ( checkExisting() && value( sect, name, res ) && res == val )
2027     return;
2028
2029   char buf[8];
2030   QStringList lst;
2031   for ( int i = 0; i < val.size();  i++ )
2032   {
2033     ::sprintf( buf, "#%02X", (unsigned char)val.at( i ) );
2034     lst.append( QString( buf ) );
2035   }
2036   setResource( sect, name, lst.join( " " ) );
2037 }
2038
2039 /*!
2040   \brief Set linear gradient parameter value.
2041   \param sect section name
2042   \param name parameter name
2043   \param val parameter value
2044 */
2045 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QLinearGradient& val )
2046 {
2047   QLinearGradient res;
2048   if ( checkExisting() && value( sect, name, res ) && res == val )
2049     return;
2050
2051   setResource( sect, name, Qtx::gradientToString( val ) );
2052 }
2053
2054 /*!
2055   \brief Set radial gradient parameter value.
2056   \param sect section name
2057   \param name parameter name
2058   \param val parameter value
2059 */
2060 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QRadialGradient& val )
2061 {
2062   QRadialGradient res;
2063   if ( checkExisting() && value( sect, name, res ) && res == val )
2064     return;
2065
2066   setResource( sect, name, Qtx::gradientToString( val ) );
2067 }
2068
2069 /*!
2070   \brief Set conical gradient parameter value.
2071   \param sect section name
2072   \param name parameter name
2073   \param val parameter value
2074 */
2075 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QConicalGradient& val )
2076 {
2077   QConicalGradient res;
2078   if ( checkExisting() && value( sect, name, res ) && res == val )
2079     return;
2080
2081   setResource( sect, name, Qtx::gradientToString( val ) );
2082 }
2083
2084 /*!
2085   \brief Set background parameter value.
2086   \param sect section name
2087   \param name parameter name
2088   \param val parameter value
2089 */
2090 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const Qtx::BackgroundData& val )
2091 {
2092   Qtx::BackgroundData res;
2093   if ( checkExisting() && value( sect, name, res ) && res == val )
2094     return;
2095
2096   setResource( sect, name, Qtx::backgroundToString( val ) );
2097 }
2098
2099 /*!
2100   \brief Remove resources section.
2101   \param sect section name
2102 */
2103 void QtxResourceMgr::remove( const QString& sect )
2104 {
2105   initialize();
2106
2107   for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2108     (*it)->removeSection( sect );
2109 }
2110
2111 /*!
2112   \brief Remove the specified parameter.
2113   \param sect section name
2114   \param name parameter name
2115 */
2116 void QtxResourceMgr::remove( const QString& sect, const QString& name )
2117 {
2118   initialize();
2119
2120   for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2121     (*it)->removeValue( sect, name );
2122 }
2123
2124 /*!
2125   \brief Get current configuration files format.
2126   \return configuration files format name
2127 */
2128 QString QtxResourceMgr::currentFormat() const
2129 {
2130   QString fmt;
2131   if ( !myFormats.isEmpty() )
2132     fmt = myFormats[0]->format();
2133   return fmt;
2134 }
2135
2136 /*!
2137   \brief Set current configuration files format.
2138   \param fmt configuration files format name
2139 */
2140 void QtxResourceMgr::setCurrentFormat( const QString& fmt )
2141 {
2142   Format* form = format( fmt );
2143   if ( !form )
2144     return;
2145
2146   myFormats.removeAll( form );
2147   myFormats.prepend( form );
2148
2149   if ( myResources.isEmpty() )
2150     return;
2151
2152   ResList::Iterator resIt = myResources.begin();
2153   if ( myResources.count() > myDirList.count() && resIt != myResources.end() )
2154   {
2155     (*resIt)->setFile( userFileName( appName() ) );
2156     ++resIt;
2157   }
2158
2159   for ( QStringList::ConstIterator it = myDirList.begin(); it != myDirList.end() && resIt != myResources.end(); ++it, ++resIt )
2160     (*resIt)->setFile( Qtx::addSlash( *it ) + globalFileName( appName() ) );
2161 }
2162
2163 /*!
2164   \brief Get configuration files format by specified format name.
2165   \param fmt configuration files format name
2166   \return format object or 0 if format is not defined
2167 */
2168 QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
2169 {
2170   Format* form = 0;
2171   for ( FormatList::ConstIterator it = myFormats.begin(); it != myFormats.end() && !form; ++it )
2172   {
2173     if ( (*it)->format() == fmt )
2174       form = *it;
2175   }
2176
2177   return form;
2178 }
2179
2180 /*!
2181   \brief Install configuration files format.
2182   
2183   Added format becomes current.
2184
2185   \param form format object to be installed
2186 */
2187 void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
2188 {
2189   if ( !myFormats.contains( form ) )
2190     myFormats.prepend( form );
2191 }
2192
2193 /*!
2194   \brief Remove configuration files format.
2195   \param form format object to be uninstalled
2196 */
2197 void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
2198 {
2199   myFormats.removeAll( form );
2200 }
2201
2202 /*!
2203   \brief Get resource format options names.
2204   \return list of options names
2205 */
2206 QStringList QtxResourceMgr::options() const
2207 {
2208   return myOptions.keys();
2209 }
2210
2211 /*!
2212   \brief Get the string value of the specified resources format option.
2213
2214   If option does not exist, null QString is returned.
2215
2216   \param opt option name
2217   \return option value
2218   \sa setOption(), options()
2219 */
2220 QString QtxResourceMgr::option( const QString& opt ) const
2221 {
2222   QString val;
2223   if ( myOptions.contains( opt ) )
2224     val = myOptions[opt];
2225   return val;
2226 }
2227
2228 /*!
2229   \brief Set the string value of the specified resources format option.
2230   \param opt option name
2231   \param val option value
2232   \sa option(), options()
2233 */
2234 void QtxResourceMgr::setOption( const QString& opt, const QString& val )
2235 {
2236   myOptions.insert( opt, val );
2237 }
2238
2239 /*!
2240   \brief Load all resources from all resource files (global and user).
2241   \return \c true on success and \c false on error
2242   \sa save()
2243 */
2244 bool QtxResourceMgr::load()
2245 {
2246   initialize( false );
2247
2248   Format* fmt = format( currentFormat() );
2249   if ( !fmt )
2250     return false;
2251
2252   bool res = true;
2253   for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2254     res = fmt->load( *it ) && res;
2255
2256   return res;
2257 }
2258
2259 /*!
2260   \brief Import resources from specified resource file.
2261   \param fname resources file name
2262   \return \c true on success and \c false on error
2263 */
2264 bool QtxResourceMgr::import( const QString& fname )
2265 {
2266   Format* fmt = format( currentFormat() );
2267   if ( !fmt )
2268     return false;
2269
2270   if ( myResources.isEmpty() || !myHasUserValues )
2271     return false;
2272
2273   Resources* r = myResources[0];
2274   if ( !r )
2275     return false;
2276
2277   QString old = r->file();
2278   r->setFile( fname );
2279   bool res = fmt->load( r );
2280   r->setFile( old );
2281   return res;
2282 }
2283
2284 /*!
2285   \brief Save all resources to the user resource files.
2286   \return \c true on success and \c false on error
2287 */
2288 bool QtxResourceMgr::save()
2289 {
2290   initialize( false );
2291
2292   Format* fmt = format( currentFormat() );
2293   if ( !fmt )
2294     return false;
2295
2296   if ( myResources.isEmpty() || !myHasUserValues )
2297     return true;
2298
2299   bool result = fmt->save( myResources[0] );
2300
2301   saved();
2302
2303   return result;
2304 }
2305
2306 /*!
2307   \brief Get all sections names.
2308   \return list of section names
2309 */
2310 QStringList QtxResourceMgr::sections() const
2311 {
2312   initialize();
2313
2314   QMap<QString, int> map;
2315
2316   ResList::ConstIterator it = myResources.begin();
2317   if ( myHasUserValues && workingMode() == IgnoreUserValues )
2318     ++it;
2319
2320   for ( ; it != myResources.end(); ++it )
2321   {
2322     QStringList lst = (*it)->sections();
2323     for ( QStringList::ConstIterator itr = lst.begin(); itr != lst.end(); ++itr )
2324       map.insert( *itr, 0 );
2325   }
2326
2327   return map.keys();
2328 }
2329
2330 /*!
2331   \brief Get all sections names matching specified regular expression.
2332   \param re searched regular expression
2333   \return list of sections names
2334 */
2335 QStringList QtxResourceMgr::sections(const QRegExp& re) const
2336 {
2337   return sections().filter( re );
2338 }
2339
2340 /*!
2341   \brief Get all sections names with the prefix specified by passed
2342   list of parent sections names. 
2343
2344   Sub-sections are separated inside the section name by the sections 
2345   separator token, for example "splash:color:label".
2346
2347   \param names parent sub-sections names 
2348   \return list of sections names
2349 */
2350 QStringList QtxResourceMgr::sections(const QStringList& names) const
2351 {
2352   QStringList nm = names;
2353   nm << ".+";
2354   QRegExp re( QString( "^%1$" ).arg( nm.join( sectionsToken() ) ) );
2355   return sections( re );
2356 }
2357
2358 /*!
2359   \brief Get list of sub-sections names for the specified parent section name.
2360
2361   Sub-sections are separated inside the section name by the sections 
2362   separator token, for example "splash:color:label".
2363
2364   \param section parent sub-section name
2365   \param full if \c true return full names of child sub-sections, if \c false,
2366          return only top-level sub-sections names
2367   \return list of sub-sections names
2368 */
2369 QStringList QtxResourceMgr::subSections(const QString& section, const bool full) const
2370 {
2371   QStringList names = sections( QStringList() << section );
2372   QMutableListIterator<QString> it( names );
2373   while ( it.hasNext() ) {
2374     QString name = it.next().mid( section.size() + 1 ).trimmed();
2375     if ( name.isEmpty() ) {
2376       it.remove();
2377       continue;
2378     }
2379     if ( !full ) name = name.split( sectionsToken() ).first();
2380     it.setValue( name );
2381   }
2382   names.removeDuplicates();
2383   names.sort();
2384   return names;
2385 }
2386
2387 /*!
2388   \brief Get all parameters name in specified section.
2389   \param sec section name
2390   \return list of settings names
2391 */
2392 QStringList QtxResourceMgr::parameters( const QString& sec ) const
2393 {
2394   initialize();
2395
2396 #if defined(QTX_NO_INDEXED_MAP)
2397   typedef QMap<QString, int> PMap;
2398 #else
2399   typedef IMap<QString, int> PMap;
2400 #endif
2401   PMap pmap;
2402   
2403   Resources* ur = !myResources.isEmpty() && workingMode() == IgnoreUserValues ? myResources[0] : 0;
2404   
2405   QListIterator<Resources*> it( myResources );
2406   it.toBack();
2407   while ( it.hasPrevious() )
2408   {
2409     Resources* r = it.previous();
2410     if ( r == ur ) break;
2411     QStringList lst = r->parameters( sec );
2412     for ( QStringList::ConstIterator itr = lst.begin(); itr != lst.end(); ++itr )
2413 #if defined(QTX_NO_INDEXED_MAP)
2414       if ( !pmap.contains( *itr ) ) pmap.insert( *itr, 0 );
2415 #else
2416       pmap.insert( *itr, 0, false );
2417 #endif
2418   }
2419
2420   return pmap.keys();
2421 }
2422
2423 /*!
2424   \brief Get all parameters name in specified
2425   list of sub-sections names. 
2426
2427   Sub-sections are separated inside the section name by the sections 
2428   separator token, for example "splash:color:label".
2429
2430   \param names parent sub-sections names 
2431   \return list of settings names
2432 */
2433 QStringList QtxResourceMgr::parameters( const QStringList& names ) const
2434 {
2435   return parameters( names.join( sectionsToken() ) );
2436 }
2437
2438 /*!
2439   \brief Get absolute path to the file which name is defined by the parameter.
2440
2441   The file name is defined by \a name argument, while directory name is retrieved
2442   from resources parameter \a prefix of section \a sec. Both directory and file name
2443   can be relative. If the directory is relative, it is calculated from the initial
2444   resources file name. Directory parameter can contain environment 
2445   variables, which are substituted automatically.
2446
2447   \param sec section name
2448   \param prefix parameter containing directory name
2449   \param name file name
2450   \return absolute file path or null QString if file does not exist
2451 */
2452 QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const QString& name ) const
2453 {
2454   QString res;
2455
2456   ResList::ConstIterator it = myResources.begin();
2457   if ( myHasUserValues && workingMode() == IgnoreUserValues )
2458     ++it;
2459
2460   for ( ; it != myResources.end() && res.isEmpty(); ++it )
2461     res = (*it)->path( sect, prefix, name );
2462   return res;
2463 }
2464
2465 /*!
2466   \brief Get application resources section name.
2467
2468   By default, application resources section name is "resources" but
2469   it can be changed by setting the "res_section_name" resources manager option.
2470   
2471   \return section corresponding to the resources directories
2472   \sa option(), setOption()
2473 */
2474 QString QtxResourceMgr::resSection() const
2475 {
2476   QString res = option( "res_section_name" );
2477   if ( res.isEmpty() )
2478     res = QString( "resources" );
2479   return res;
2480 }
2481
2482 /*!
2483   \brief Get application language section name.
2484
2485   By default, application language section name is "language" but
2486   it can be changed by setting the "lang_section_name" resources manager option.
2487   
2488   \return section corresponding to the application language settings
2489   \sa option(), setOption()
2490 */
2491 QString QtxResourceMgr::langSection() const
2492 {
2493   QString res = option( "lang_section_name" );
2494   if ( res.isEmpty() )
2495     res = QString( "language" );
2496   return res;
2497 }
2498
2499 /*!
2500   \brief Get sections separator token.
2501
2502   By default, sections separator token is colon symbol ":" but
2503   it can be changed by setting the "section_token" resources manager option.
2504   
2505   \return string corresponding to the current section separator token
2506   \sa option(), setOption()
2507 */
2508 QString QtxResourceMgr::sectionsToken() const
2509 {
2510   QString res = option( "section_token" );
2511   if ( res.isEmpty() )
2512     res = QString( ":" );
2513   return res;
2514 }
2515
2516 /*!
2517   \brief Get default pixmap.
2518   
2519   Default pixmap is used when requested pixmap resource is not found.
2520
2521   \return default pixmap
2522   \sa setDefaultPixmap(), loadPixmap()
2523 */
2524 QPixmap QtxResourceMgr::defaultPixmap() const
2525 {
2526   QPixmap res;
2527   if ( myDefaultPix && !myDefaultPix->isNull() )
2528     res = *myDefaultPix;
2529   return res;
2530 }
2531
2532 /*!
2533   \brief Set default pixmap.
2534   
2535   Default pixmap is used when requested pixmap resource is not found.
2536
2537   \param pix default pixmap
2538   \sa defaultPixmap(), loadPixmap()
2539 */
2540 void QtxResourceMgr::setDefaultPixmap( const QPixmap& pix )
2541 {
2542   delete myDefaultPix;
2543   if ( pix.isNull() )
2544     myDefaultPix = 0;
2545   else
2546     myDefaultPix = new QPixmap( pix );
2547 }
2548
2549 /*!
2550   \brief Load pixmap resource.
2551   \param prefix parameter which refers to the resources directory (directories)
2552   \param name pixmap file name
2553   \return pixmap loaded from the file 
2554   \sa defaultPixmap(), setDefaultPixmap()
2555 */
2556 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name ) const
2557 {
2558   return loadPixmap( prefix, name, true );
2559 }
2560
2561 /*!
2562   \brief Load pixmap resource.
2563   \overload
2564   \param prefix parameter which refers to the resources directory (directories)
2565   \param name pixmap file name
2566   \param useDef if \c false, default pixmap is not returned if resource is not found,
2567          in this case null pixmap is returned instead
2568   \return pixmap loaded from the file 
2569   \sa defaultPixmap(), setDefaultPixmap()
2570 */
2571 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const bool useDef ) const
2572 {
2573   return loadPixmap( prefix, name, useDef ? defaultPixmap() : QPixmap() );
2574 }
2575
2576 /*!
2577   \brief Load pixmap resource.
2578   \overload
2579   \param prefix parameter which refers to the resources directory (directories)
2580   \param name pixmap file name
2581   \param defPix default which should be used if the resource file doesn't exist
2582   \return pixmap loaded from the file 
2583   \sa defaultPixmap(), setDefaultPixmap()
2584 */
2585 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const QPixmap& defPix ) const
2586 {
2587   initialize();
2588
2589   QPixmap pix;
2590
2591   ResList::ConstIterator it = myResources.begin();
2592   if ( myHasUserValues && workingMode() == IgnoreUserValues )
2593     ++it;
2594
2595   for ( ; it != myResources.end() && pix.isNull(); ++it )
2596     pix = (*it)->loadPixmap( resSection(), prefix, name );
2597   if ( pix.isNull() )
2598     pix = defPix;
2599   return pix;
2600 }
2601
2602 /*!
2603   \brief Load translation files according to the specified language.
2604
2605   Names of the translation files are calculated according to the pattern specified
2606   by the "translators" option (this option is read from the section "language" of resources files).
2607   By default, "%P_msg_%L.qm" pattern is used.
2608   Keywords \%A, \%P, \%L in the pattern are substituted by the application name, prefix and language name
2609   correspondingly.
2610   For example, for prefix "SUIT" and language "en", all translation files "SUIT_msg_en.qm" are searched and
2611   loaded.
2612
2613   If prefix is empty or null string, all translation files specified in the "resources" section of resources
2614   files are loaded (actually, the section is retrieved from resSection() method). 
2615   If language is not specified, it is retrieved from the langSection() method, and if the latest is also empty,
2616   by default "en" (English) language is used.
2617   By default, settings from the user preferences file are also loaded (if user resource file is valid, 
2618   see userFileName()). To avoid loading user settings, pass \c false as first parameter.
2619
2620   \param pref parameter which defines translation context (for example, package name)
2621   \param l language name
2622
2623   \sa resSection(), langSection(), loadTranslators()
2624 */
2625 void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
2626 {
2627   initialize( true );
2628
2629   QMap<QChar, QString> substMap;
2630   substMap.insert( 'A', appName() );
2631
2632   QString lang = l;
2633   if ( lang.isEmpty() )
2634     value( langSection(), "language", lang );
2635
2636   if ( lang.isEmpty() )
2637   {
2638     lang = QString( "en" );
2639     qWarning() << "QtxResourceMgr: Language not specified. Assumed:" << lang;
2640   }
2641
2642   substMap.insert( 'L', lang );
2643
2644   QString trs;
2645   if ( value( langSection(), "translators", trs, false ) && !trs.isEmpty() )
2646   {
2647     QStringList translators    = option( "translators" ).split( "|", QString::SkipEmptyParts );
2648     QStringList newTranslators = trs.split( "|", QString::SkipEmptyParts );
2649     for ( int i = 0; i < (int)newTranslators.count(); i++ )
2650     {
2651       if ( translators.indexOf( newTranslators[i] ) < 0 )
2652         translators += newTranslators[i];
2653     }
2654     setOption( "translators", translators.join( "|" ) );
2655   }
2656
2657   QStringList trList = option( "translators" ).split( "|", QString::SkipEmptyParts );
2658   if ( trList.isEmpty() )
2659   {
2660     trList.append( "%P_msg_%L.qm" );
2661     qWarning() << "QtxResourceMgr: Translators not defined. Assumed:" << trList[0];
2662   }
2663
2664   QStringList prefixList;
2665   if ( !pref.isEmpty() )
2666     prefixList.append( pref );
2667   else
2668     prefixList = parameters( resSection() );
2669
2670   if ( pref.isEmpty() && lang != "en" ) {
2671     // load Qt resources
2672     QString qt_translations = QLibraryInfo::location( QLibraryInfo::TranslationsPath );
2673     QString qt_dir_trpath;
2674     if ( ::getenv( "QTDIR" ) )
2675       qt_dir_trpath = QString( ::getenv( "QTDIR" ) );
2676     if ( !qt_dir_trpath.isEmpty() )
2677       qt_dir_trpath = QDir( qt_dir_trpath ).absoluteFilePath( "translations" );
2678
2679     QTranslator* trans = new QtxTranslator( 0 );
2680     if ( trans->load( QString("qt_%1").arg( lang ), qt_translations ) || trans->load( QString("qt_%1").arg( lang ), qt_dir_trpath ) )
2681       QApplication::instance()->installTranslator( trans );
2682   }
2683
2684   for ( QStringList::ConstIterator iter = prefixList.begin(); iter != prefixList.end(); ++iter )
2685   {
2686     QString prefix = *iter;
2687     substMap.insert( 'P', prefix );
2688
2689     QStringList trs;
2690     for ( QStringList::ConstIterator it = trList.begin(); it != trList.end(); ++it )
2691       trs.append( substMacro( *it, substMap ).trimmed() );
2692
2693     loadTranslators( prefix, trs );
2694   }
2695 }
2696
2697 /*!
2698   \brief Load translation files for the specified translation context.
2699   \param prefix parameter which defines translation context (for example, package name)
2700   \param translators list of translation files 
2701   \sa loadLanguage()
2702 */
2703 void QtxResourceMgr::loadTranslators( const QString& prefix, const QStringList& translators )
2704 {
2705   initialize();
2706
2707   ResList lst;
2708
2709   ResList::ConstIterator iter = myResources.begin();
2710   if ( myHasUserValues && workingMode() == IgnoreUserValues )
2711     ++iter;
2712
2713   for ( ; iter != myResources.end(); ++iter )
2714     lst.prepend( *iter );
2715
2716   QTranslator* trans = 0;
2717   
2718   for ( ResList::Iterator it = lst.begin(); it != lst.end(); ++it )
2719   {
2720     for ( QStringList::ConstIterator itr = translators.begin(); itr != translators.end(); ++itr )
2721     {
2722       trans = (*it)->loadTranslator( resSection(), prefix, *itr );
2723       if ( trans )
2724       {
2725         if ( !myTranslator[prefix].contains( trans ) )
2726           myTranslator[prefix].append( trans );
2727         QApplication::instance()->installTranslator( trans );
2728       }
2729     }
2730   }
2731 }
2732
2733 /*!
2734   \brief Load translation file.
2735   \param prefix parameter which defines translation context (for example, package name)
2736   \param name translator file name
2737   \sa loadLanguage(), loadTranslators()
2738 */
2739 void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name )
2740 {
2741   initialize();
2742
2743   QTranslator* trans = 0;
2744
2745   Resources* ur = !myResources.isEmpty() && workingMode() == IgnoreUserValues ? myResources[0] : 0;
2746   
2747   QListIterator<Resources*> it( myResources );
2748   it.toBack();
2749   while ( it.hasPrevious() )
2750   {
2751     Resources* r = it.previous();
2752     if ( r == ur ) break;
2753
2754     trans = r->loadTranslator( resSection(), prefix, name );
2755     if ( trans )
2756     {
2757       if ( !myTranslator[prefix].contains( trans ) )
2758         myTranslator[prefix].append( trans );
2759       QApplication::instance()->installTranslator( trans );
2760     }
2761   }
2762 }
2763
2764 /*!
2765   \brief Remove all translators corresponding to the specified translation context.
2766   \param prefix parameter which defines translation context (for example, package name)
2767 */
2768 void QtxResourceMgr::removeTranslators( const QString& prefix )
2769 {
2770   if ( !myTranslator.contains( prefix ) )
2771     return;
2772
2773   for ( TransList::Iterator it = myTranslator[prefix].begin(); it != myTranslator[prefix].end(); ++it )
2774   {
2775     QApplication::instance()->removeTranslator( *it );
2776     delete *it;
2777   }
2778
2779   myTranslator.remove( prefix );
2780 }
2781
2782 /*!
2783   \brief Move all translators corresponding to the specified translation context 
2784          to the top of translators stack (increase their priority).
2785   \param prefix parameter which defines translation context (for example, package name)
2786 */
2787 void QtxResourceMgr::raiseTranslators( const QString& prefix )
2788 {
2789   if ( !myTranslator.contains( prefix ) )
2790     return;
2791
2792   for ( TransList::Iterator it = myTranslator[prefix].begin(); it != myTranslator[prefix].end(); ++it )
2793   {
2794     QApplication::instance()->removeTranslator( *it );
2795     QApplication::instance()->installTranslator( *it );
2796   }
2797 }
2798
2799 /*!
2800   \brief Copy all parameters to the user resources in order to
2801          saved them lately in the user home folder.
2802 */
2803 void QtxResourceMgr::refresh()
2804 {
2805   QStringList sl = sections();
2806   for ( QStringList::ConstIterator it = sl.begin(); it != sl.end(); ++it )
2807   {
2808     QStringList pl = parameters( *it );
2809     for ( QStringList::ConstIterator itr = pl.begin(); itr != pl.end(); ++itr )
2810       setResource( *it, *itr, stringValue( *it, *itr ) );
2811   }
2812 }
2813
2814 /*!
2815   \brief Set the resource directories (where global confguration files are searched).
2816   
2817   This function also clears all currently set resources.
2818
2819   \param dl directories list
2820 */
2821 void QtxResourceMgr::setDirList( const QStringList& dl )
2822 {
2823   myDirList = dl;
2824   for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2825     delete *it;
2826
2827   myResources.clear();
2828 }
2829
2830 /*!
2831   \brief Set parameter value.
2832   \param sect section name
2833   \param name parameter name
2834   \param val parameter value
2835 */
2836 void QtxResourceMgr::setResource( const QString& sect, const QString& name, const QString& val )
2837 {
2838   initialize();
2839
2840   if ( !myResources.isEmpty() && myHasUserValues )
2841     myResources.first()->setValue( sect, name, val );
2842 }
2843
2844 /*!
2845   \brief Get user configuration file name.
2846
2847   This method can be redefined in the successor class to customize the user configuration file name.
2848   User configuration file is always situated in the user's home directory. By default .<appName>rc
2849   file is used on Linux (e.g. .MyApprc) and <appName>.<format> under Windows (e.g. MyApp.xml).
2850
2851   Parameter \a for_load (not used in default implementation) specifies the usage mode, i.e. if
2852   user configuration file is opened for reading or writing. This allows customizing a way of application
2853   resources initializing (for example, if the user configuraion file includes version number and there is
2854   no file corresponding to this version in the user's home directory, it could be good idea to try 
2855   the configuration file from the previous versions of the application).
2856   
2857   \param appName application name
2858   \param for_load boolean flag indicating that file is opened for loading or saving (not used in default implementation) 
2859   \return user configuration file name
2860   \sa globalFileName()
2861 */
2862 QString QtxResourceMgr::userFileName( const QString& appName, const bool /*for_load*/ ) const
2863 {
2864   QString fileName;
2865   QString pathName = QDir::homePath();
2866
2867   QString cfgAppName = QApplication::applicationName();
2868   if ( !cfgAppName.isEmpty() )
2869     pathName = Qtx::addSlash( Qtx::addSlash( pathName ) + QString( ".config" ) ) + cfgAppName;
2870
2871 #ifdef WIN32
2872   fileName = QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
2873 #else
2874   fileName = QString( "%1rc" ).arg( appName );
2875   // VSR 24/09/2012: issue 0021781: do not prepend filename with "."
2876   // when user file is stored in ~/.config/<appname> directory
2877   if ( cfgAppName.isEmpty() )
2878     fileName.prepend( "." );
2879 #endif
2880
2881   if ( !fileName.isEmpty() )
2882     pathName = Qtx::addSlash( pathName ) + fileName;
2883
2884   return pathName;
2885 }
2886
2887 /*!
2888   \brief Get global configuration file name.
2889   
2890   This method can be redefined in the successor class to customize the global configuration file name.
2891   Global configuration files are searched in the directories specified by the application resources
2892   environment variable (e.g. MyAppResources). By default <appName>.<format> file name is used
2893   (e.g. MyApp.xml).
2894
2895   \param appName application name
2896   \return global configuration file name
2897   \sa userFileName()
2898 */
2899 QString QtxResourceMgr::globalFileName( const QString& appName ) const
2900 {
2901   return QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
2902 }
2903
2904 /*!
2905   \brief This function is called after user configuration file is saved.
2906   Can be redefined in the successor classes, default implementation does nothing.
2907 */
2908 void QtxResourceMgr::saved()
2909 {
2910 }
2911
2912 /*!
2913   \brief Perform substitution of the patterns like \%A, \%B, etc by values from the map.
2914
2915   Used by loadLanguage().
2916
2917   \param src sring to be processed
2918   \param substMap map of values for replacing
2919   \return processed string
2920 */
2921 QString QtxResourceMgr::substMacro( const QString& src, const QMap<QChar, QString>& substMap ) const
2922 {
2923   QString trg = src;
2924
2925   QRegExp rx( "%[A-Za-z%]" );
2926
2927   int idx = 0;
2928   while ( ( idx = rx.indexIn( trg, idx ) ) >= 0 )
2929   {
2930     QChar spec = trg.at( idx + 1 );
2931     QString subst;
2932     if ( spec == '%' )
2933       subst = "%";
2934     else if ( substMap.contains( spec ) )
2935       subst = substMap[spec];
2936
2937     if ( !subst.isEmpty() )
2938     {
2939       trg.replace( idx, rx.matchedLength(), subst );
2940       idx += subst.length();
2941     }
2942     else
2943       idx += rx.matchedLength();
2944   }
2945
2946   return trg;
2947 }