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