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