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