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