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