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