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