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