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