]> SALOME platform Git repositories - modules/gui.git/blob - src/Qtx/QtxResourceMgr.cxx
Salome HOME
no message
[modules/gui.git] / src / Qtx / QtxResourceMgr.cxx
1 #include "QtxResourceMgr.h"
2
3 #include <qdir.h>
4 #include <qfile.h>
5 #include <qregexp.h>
6 #include <qpixmap.h>
7 #include <qtranslator.h>
8 #include <qapplication.h>
9
10 #ifndef QT_NO_DOM
11 #include <qdom.h>
12 #endif
13
14 #include <stdlib.h>
15
16 /*!
17   Class: QtxResourceMgr::Resources
18   Level: Internal
19 */
20
21 QtxResourceMgr::Resources::Resources( const QString& fileName )
22 : myFileName( fileName )
23 {
24 }
25
26 QtxResourceMgr::Resources::~Resources()
27 {
28 }
29
30 QString QtxResourceMgr::Resources::file() const
31 {
32   return myFileName;
33 }
34
35 void QtxResourceMgr::Resources::setFile( const QString& fn )
36 {
37   myFileName = fn;
38 }
39
40 QString QtxResourceMgr::Resources::value( const QString& sect, const QString& name, const bool subst ) const
41 {
42   QString val;
43
44   if ( hasValue( sect, name ) )
45   {
46     val = section( sect )[name];
47     if ( subst )
48       val = makeSubstitution( val, sect, name );
49   }
50   return val;
51 }
52
53 void QtxResourceMgr::Resources::setValue( const QString& sect, const QString& name, const QString& val )
54 {
55   Section& s = section( sect );
56   s.insert( name, val );
57 }
58
59 bool QtxResourceMgr::Resources::hasSection( const QString& sect ) const
60 {
61   return mySections.contains( sect );
62 }
63
64 bool QtxResourceMgr::Resources::hasValue( const QString& sect, const QString& name ) const
65 {
66   return hasSection( sect ) && section( sect ).contains( name );
67 }
68
69 void QtxResourceMgr::Resources::removeSection( const QString& sect )
70 {
71   mySections.remove( sect );
72 }
73
74 void QtxResourceMgr::Resources::removeValue( const QString& sect, const QString& name )
75 {
76   if ( !hasSection( sect ) )
77     return;
78
79   Section& s = section( sect );
80   s.remove( name );
81
82   if ( s.isEmpty() )
83     mySections.remove( sect );
84 }
85
86 void QtxResourceMgr::Resources::clear()
87 {
88   mySections.clear();
89 }
90
91 QStringList QtxResourceMgr::Resources::sections() const
92 {
93   return mySections.keys();
94 }
95
96 QStringList QtxResourceMgr::Resources::parameters( const QString& sec ) const
97 {
98   if ( !hasSection( sec ) )
99     return QStringList();
100
101   return section( sec ).keys();
102 }
103
104 QString QtxResourceMgr::Resources::path( const QString& sec, const QString& prefix, const QString& name ) const
105 {
106   QString filePath = fileName( sec, prefix, name );
107   if ( !filePath.isEmpty() )
108   {
109     if ( !QFileInfo( filePath ).exists() )
110       filePath = QString::null;
111   }
112   return filePath;
113 }
114
115 QtxResourceMgr::Section& QtxResourceMgr::Resources::section( const QString& sn )
116 {
117   if ( !mySections.contains( sn ) )
118     mySections.insert( sn, Section() );
119
120   return mySections[sn];
121 }
122
123 const QtxResourceMgr::Section& QtxResourceMgr::Resources::section( const QString& sn ) const
124 {
125   return mySections[sn];
126 }
127
128 QString QtxResourceMgr::Resources::fileName( const QString& sect, const QString& prefix, const QString& name ) const
129 {
130   QString path;
131   if ( hasValue( sect, prefix ) )
132   {
133     path = value( sect, prefix, true );
134     if ( !path.isEmpty() )
135     {
136       if ( QFileInfo( path ).isRelative() )
137         path = Qtx::addSlash( QFileInfo( myFileName ).dirPath( true ) ) + path;
138
139       path = Qtx::addSlash( path ) + name;
140     }
141   }
142   return QDir::convertSeparators( path );
143 }
144
145 QPixmap QtxResourceMgr::Resources::loadPixmap( const QString& sect, const QString& prefix, const QString& name ) const
146 {
147   return QPixmap( fileName( sect, prefix, name ) );
148 }
149
150 QTranslator* QtxResourceMgr::Resources::loadTranslator( const QString& sect, const QString& prefix, const QString& name ) const
151 {
152   QTranslator* trans = new QTranslator( 0 );
153   if ( !trans->load( fileName( sect, prefix, name ) ) )
154   {
155     delete trans;
156     trans = 0;
157   }
158   return trans;
159 }
160
161 QString QtxResourceMgr::Resources::environmentVariable( const QString& str, int& start, int& len ) const
162 {
163   QString varName = QString::null;
164   len = 0;
165
166   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_]*)\\%" );
167
168   int pos = rx.search( str, start );
169   if ( pos != -1 )
170   {
171     start = pos;
172     len = rx.matchedLength();
173     QStringList caps = rx.capturedTexts();
174     for ( uint i = 1; i <= caps.count() && varName.isEmpty(); i++ )
175       varName = *caps.at( i );
176   }
177   return varName;
178 }
179
180 QString QtxResourceMgr::Resources::makeSubstitution( const QString& str, const QString& sect, const QString& name ) const
181 {
182   QString res = str;
183
184   QMap<QString, int> ignoreMap;
185   ignoreMap.insert( name, 0 );
186
187   int start( 0 ), len( 0 );
188   while ( true )
189   {
190     QString envName = environmentVariable( res, start, len );
191     if ( envName.isNull() )
192       break;
193
194     QString newStr = QString::null;
195     if ( ::getenv( envName ) )
196       newStr = QString( ::getenv( envName ) );
197
198     if ( newStr.isNull() )
199     {
200       if ( ignoreMap.contains( envName ) )
201       {
202         start += len;
203         continue;
204       }
205
206       if ( hasValue( sect, envName ) )
207         newStr = value( sect, envName, false );
208       ignoreMap.insert( envName, 0 );
209     }
210     res.replace( start, len, newStr );
211   }
212
213   return res;
214 }
215
216 /*!
217         Class: QtxResourceMgr::IniFormat
218         Level: Internal
219 */
220
221 class QtxResourceMgr::IniFormat : public Format
222 {
223 public:
224   IniFormat();
225   ~IniFormat();
226
227 protected:
228   virtual bool load( const QString&, QMap<QString, Section>& );
229   virtual bool save( const QString&, const QMap<QString, Section>& );
230 };
231
232 QtxResourceMgr::IniFormat::IniFormat()
233 : Format( "ini" )
234 {
235 }
236
237 QtxResourceMgr::IniFormat::~IniFormat()
238 {
239 }
240
241 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap )
242 {
243   QFile file( fname );
244   if ( !file.open( IO_ReadOnly ) )
245     return false;
246
247   QTextStream ts( &file );
248
249   QString data;
250   int line = 0;
251   bool res = true;
252   QString section;
253
254   QString separator = option( "separator" );
255   if ( separator.isNull() )
256     separator = QString( "=" );
257
258   QString comment = option( "comment" );
259   if ( comment.isNull() )
260     comment = QString( "#" );
261
262   while ( true )
263   {
264     data = ts.readLine();
265     line++;
266
267     if ( data.isNull() )
268       break;
269
270     data = data.stripWhiteSpace();
271     if ( data.isEmpty() )
272       continue;
273
274     if ( data.startsWith( comment ) )
275       continue;
276
277     QRegExp rx( "^\\[([\\w\\s\\._]*)\\]$" );
278     if ( rx.search( data ) != -1 )
279     {
280       section = rx.cap( 1 );
281       if ( section.isEmpty() )
282       {
283         res = false;
284         qWarning( QString( "Empty section in line %1" ).arg( line ) );
285       }
286     }
287     else if ( data.contains( "=" ) && !section.isEmpty() )
288     {
289       int pos = data.find( separator );
290       QString key = data.left( pos ).stripWhiteSpace();
291       QString val = data.mid( pos + 1 ).stripWhiteSpace();
292       secMap[section].insert( key, val );
293     }
294     else
295     {
296       res = false;
297       section.isEmpty() ? qWarning( "Current section is empty" ) :
298                           qWarning( QString( "Error in line: %1" ).arg( line ) );
299     }
300   }
301
302   file.close();
303
304   return res;
305 }
306
307 bool QtxResourceMgr::IniFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
308 {
309   QFile file( fname );
310   if ( !file.open( IO_WriteOnly ) )
311     return false;
312
313   bool res = true;
314   for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end() && res; ++it )
315   {
316     QString data = QString( "[%1]\n" ).arg( it.key() );
317     for ( Section::ConstIterator iter = it.data().begin(); iter != it.data().end(); ++iter )
318       data += iter.key() + " = " + iter.data() + "\n";
319     data += "\n";
320
321     res = file.writeBlock( data.latin1(), data.length() ) == (int)data.length();
322   }
323
324   file.close();
325
326   return res;
327 }
328
329 /*!
330         Class: QtxResourceMgr::XmlFormat
331         Level: Internal
332 */
333
334 class QtxResourceMgr::XmlFormat : public Format
335 {
336 public:
337   XmlFormat();
338   ~XmlFormat();
339
340 protected:
341   virtual bool load( const QString&, QMap<QString, Section>& );
342   virtual bool save( const QString&, const QMap<QString, Section>& );
343
344 private:
345   QString      docTag() const;
346   QString      sectionTag() const;
347   QString      parameterTag() const;
348   QString      nameAttribute() const;
349   QString      valueAttribute() const;
350 };
351
352 QtxResourceMgr::XmlFormat::XmlFormat()
353 : Format( "xml" )
354 {
355 }
356
357 QtxResourceMgr::XmlFormat::~XmlFormat()
358 {
359 }
360
361 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap )
362 {
363   bool res = false;
364
365 #ifndef QT_NO_DOM
366
367   QFile file( fname );
368   if ( !file.open( IO_ReadOnly ) )
369     return false;
370
371   QDomDocument doc;
372
373   res = doc.setContent( &file );
374   file.close();
375
376   if ( !res )
377     return false;
378
379   QDomElement root = doc.documentElement();
380   if ( root.isNull() || root.tagName() != docTag() )
381     return false;
382
383   QDomNode sectNode = root.firstChild();
384   while ( res && !sectNode.isNull() )
385   {
386     res = sectNode.isElement();
387     if ( res )
388     {
389       QDomElement sectElem = sectNode.toElement();
390       if ( sectElem.tagName() == sectionTag() && sectElem.hasAttribute( nameAttribute() ) )
391       {
392         QString section = sectElem.attribute( nameAttribute() );
393         QDomNode paramNode = sectNode.firstChild();
394         while ( res && !paramNode.isNull() )
395         {
396           res = paramNode.isElement();
397           if ( res )
398           {
399             QDomElement paramElem = paramNode.toElement();
400             if ( paramElem.tagName() == parameterTag() &&
401                  paramElem.hasAttribute( nameAttribute() ) && paramElem.hasAttribute( valueAttribute() ) )
402             {
403               QString paramName = paramElem.attribute( nameAttribute() );
404               QString paramValue = paramElem.attribute( valueAttribute() );
405
406               secMap[section].insert( paramName, paramValue );
407             }
408             else
409               res = false;
410           }
411           else
412             res = paramNode.isComment();
413
414           paramNode = paramNode.nextSibling();
415         }
416       }
417       else
418         res = false;
419     }
420     else
421       res = sectNode.isComment(); // if it's a comment -- let it be, pass it..
422
423     sectNode = sectNode.nextSibling();
424   }
425
426 #endif
427
428   return res;
429 }
430
431 bool QtxResourceMgr::XmlFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
432 {
433   bool res = false;
434
435 #ifndef QT_NO_DOM
436
437   QFile file( fname );
438   if ( !file.open( IO_WriteOnly ) )
439     return false;
440
441   QDomDocument doc( docTag() );
442   QDomElement root = doc.createElement( docTag() );
443   doc.appendChild( root );
444
445   for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end(); ++it )
446   {
447     QDomElement sect = doc.createElement( sectionTag() );
448     sect.setAttribute( nameAttribute(), it.key() );
449     root.appendChild( sect );
450     for ( QMap<QString, QString>::ConstIterator iter = it.data().begin(); iter != it.data().end(); ++iter )
451     {
452       QDomElement val = doc.createElement( parameterTag() );
453       val.setAttribute( nameAttribute(), iter.key() );
454       val.setAttribute( valueAttribute(), iter.data() );
455       sect.appendChild( val );
456     }
457   }
458
459   QString docStr = doc.toString();
460   res = file.writeBlock( docStr.latin1(), docStr.length() ) == (int)docStr.length();
461   file.close();
462
463 #endif
464
465   return res;
466 }
467
468 QString QtxResourceMgr::XmlFormat::docTag() const
469 {
470   QString tag = option( "doc_tag" );
471   if ( tag.isEmpty() )
472     tag = QString( "document" );
473   return tag;
474 }
475
476 QString QtxResourceMgr::XmlFormat::sectionTag() const
477 {
478   QString tag = option( "section_tag" );
479   if ( tag.isEmpty() )
480     tag = QString( "section" );
481   return tag;
482 }
483
484 QString QtxResourceMgr::XmlFormat::parameterTag() const
485 {
486   QString tag = option( "parameter_tag" );
487   if ( tag.isEmpty() )
488     tag = QString( "parameter" );
489   return tag;
490 }
491
492 QString QtxResourceMgr::XmlFormat::nameAttribute() const
493 {
494   QString str = option( "name_attribute" );
495   if ( str.isEmpty() )
496     str = QString( "name" );
497   return str;
498 }
499
500 QString QtxResourceMgr::XmlFormat::valueAttribute() const
501 {
502   QString str = option( "value_attribute" );
503   if ( str.isEmpty() )
504     str = QString( "value" );
505   return str;
506 }
507
508 /*!
509         Class: QtxResourceMgr::Format
510         Level: Public
511 */
512
513 /*!
514   \brief Constructs the format object with specified name.
515   \param fmt - name of the format
516 */
517 QtxResourceMgr::Format::Format( const QString& fmt )
518 : myFmt( fmt )
519 {
520 }
521
522 /*!
523   \brief Destructs the format object.
524 */
525 QtxResourceMgr::Format::~Format()
526 {
527 }
528
529 /*!
530   \brief Returns the format name.
531 */
532 QString QtxResourceMgr::Format::format() const
533 {
534   return myFmt;
535 }
536
537 /*!
538   \brief Returns the string list of the format options.
539 */
540 QStringList QtxResourceMgr::Format::options() const
541 {
542   return myOpt.keys();
543 }
544
545 /*!
546   \brief Returns the value of the option with specified name.
547          If option doesn't exist then empty string returned.
548   \param opt - name of the option
549 */
550 QString QtxResourceMgr::Format::option( const QString& opt ) const
551 {
552   QString val;
553   if ( myOpt.contains( opt ) )
554     val = myOpt[opt];
555   return val;
556 }
557
558 /*!
559   \brief Sets the value of the option with specified name.
560   \param opt - name of the option
561   \param opt - value of the option
562 */
563 void QtxResourceMgr::Format::setOption( const QString& opt, const QString& val )
564 {
565   myOpt.insert( opt, val );
566 }
567
568 /*!
569   \brief Perform the loading of the resources from resource file.
570   \param res - resources object which will be loaded
571 */
572 bool QtxResourceMgr::Format::load( Resources* res )
573 {
574   if ( !res )
575     return false;
576
577   QMap<QString, Section> sections;
578   bool status = load( res->myFileName, sections );
579   if ( status )
580     res->mySections = sections;
581   else
582     qDebug( "QtxResourceMgr: Could not load resource file \"%s\"", res->myFileName.latin1() );
583
584   return status;
585 }
586
587 /*!
588   \brief Perform the saving of the resources into resource file.
589   \param res - resources object which will be saved
590 */
591 bool QtxResourceMgr::Format::save( Resources* res )
592 {
593   if ( !res )
594     return false;
595
596   Qtx::mkDir( Qtx::dir( res->myFileName ) );
597
598   return save( res->myFileName, res->mySections );
599 }
600
601 /*!
602         Class: QtxResourceMgr
603         Level: Public
604 */
605
606 /*!
607   \brief Constructs the resource manager object for application.
608   \param appName - name of the application which resources will be used.
609   \param resVarTemplate - template for the resource environment variable name which
610                           should point to the resource directory list.
611                           Default value is "%1Resources". Its mean that for application
612                           with name "MyApp" environment variable "MyAppResources" will
613                           be used. Template may not have the parameter '%1' substituted
614                           by application name. In this case this string will be used as
615                           is without substitution.
616   Resource environment variable should contains one or several resource directories
617   separated by symbol ';'. Resource directories list transfered into the setDirList().
618   These directories and the user home directory used for the loading application resources.
619   Each of the resource directories can contains resource file. The name of this file defined
620   by the function globalFileName(). Resource file name in the user home defined by the
621   function userFileName(). Any resource looking firstly in the user home resources then
622   resource directories used in the specified order. All setted resources always stored into
623   the resource file at the user home. Only user home resource file is saved.
624 */
625 QtxResourceMgr::QtxResourceMgr( const QString& appName, const QString& resVarTemplate )
626 : myAppName( appName ),
627 myCheckExist( true )
628 {
629   QString envVar = !resVarTemplate.isEmpty() ? resVarTemplate : QString( "%1Resources" );
630   if ( envVar.contains( "%1" ) )
631     envVar = envVar.arg( appName );
632
633   QString dirs;
634   if ( ::getenv( envVar ) )
635     dirs = ::getenv( envVar );
636
637   setDirList( QStringList::split( ";", dirs ) );
638
639   installFormat( new XmlFormat() );
640   installFormat( new IniFormat() );
641
642   setOption( "translators", QString( "%P_msg_%L.qm|%P_images.qm" ) );
643 }
644
645 /*!
646   \brief Destructs the resource manager object and free allocated memory.
647 */
648 QtxResourceMgr::~QtxResourceMgr()
649 {
650   QStringList prefList = myTranslator.keys();
651   for ( QStringList::const_iterator it = prefList.begin(); it != prefList.end(); ++it )
652     removeTranslators( *it );
653 }
654
655 /*!
656   \brief Returns the application name.
657 */
658 QString QtxResourceMgr::appName() const
659 {
660   return myAppName;
661 }
662
663 /*!
664   \brief Returns the checking of the existance flag. If its 'true' then resource
665          will be setted into the manager only if it doesn't exist or has different
666          value that existing value.
667 */
668 bool QtxResourceMgr::checkExisting() const
669 {
670   return myCheckExist;
671 }
672
673 /*!
674   \brief Sets the checking of the existance flag.
675   \param on - boolean value of the flag.
676 */
677 void QtxResourceMgr::setCheckExisting( const bool on )
678 {
679   myCheckExist = on;
680 }
681
682 /*!
683   \brief Returns the resource directories list except user home directory.
684 */
685 QStringList QtxResourceMgr::dirList() const
686 {
687   return myDirList;
688 }
689
690 /*!
691   \brief Initialise the manager. Prepare the resource containers and load resources.
692   \param autoLoad - if 'true' then all resources will be loaded.
693 */
694 void QtxResourceMgr::initialize( const bool autoLoad ) const
695 {
696   if ( !myResources.isEmpty() )
697     return;
698
699   QtxResourceMgr* that = (QtxResourceMgr*)this;
700
701   that->myResources.append( new Resources( userFileName( appName() ) ) );
702   for ( QStringList::const_iterator it = myDirList.begin(); it != myDirList.end(); ++it )
703   {
704     QString path = Qtx::addSlash( *it ) + globalFileName( appName() );
705     that->myResources.append( new Resources( path ) );
706   }
707
708   if ( autoLoad )
709     that->load();
710 }
711
712 /*!
713   \brief Removes all resources from the manager.
714 */
715 void QtxResourceMgr::clear()
716 {
717   for ( ResListIterator it( myResources ); it.current(); ++it )
718     it.current()->clear();
719 }
720
721 /*!
722   \brief Get the resource value as integer. Returns 'true' if it successfull otherwise
723          returns 'false'.
724   \param sect - Resource section name which contains resource.
725   \param name - Name of the resource.
726   \param iVal - Reference on the variable which should contains the resource output.
727 */
728 bool QtxResourceMgr::value( const QString& sect, const QString& name, int& iVal ) const
729 {
730   QString val;
731   if ( !value( sect, name, val, true ) )
732     return false;
733
734   bool ok;
735   iVal = val.toInt( &ok );
736
737   return ok;
738 }
739
740 /*!
741   \brief Get the resource value as double. Returns 'true' if it successfull otherwise
742          returns 'false'.
743   \param sect - Resource section name which contains resource.
744   \param name - Name of the resource.
745   \param dVal - Reference on the variable which should contains the resource output.
746 */
747 bool QtxResourceMgr::value( const QString& sect, const QString& name, double& dVal ) const
748 {
749   QString val;
750   if ( !value( sect, name, val, true ) )
751     return false;
752
753   bool ok;
754   dVal = val.toDouble( &ok );
755
756   return ok;
757 }
758
759 /*!
760   \brief Get the resource value as boolean. Returns 'true' if it successfull otherwise
761          returns 'false'.
762   \param sect - Resource section name which contains resource.
763   \param name - Name of the resource.
764   \param bVal - Reference on the variable which should contains the resource output.
765 */
766 bool QtxResourceMgr::value( const QString& sect, const QString& name, bool& bVal ) const
767 {
768   QString val;
769   if ( !value( sect, name, val, true ) )
770     return false;
771
772   static QMap<QString, bool> boolMap;
773   if ( boolMap.isEmpty() )
774   {
775     boolMap["true"]  = boolMap["yes"] = boolMap["on"]  = true;
776     boolMap["false"] = boolMap["no"]  = boolMap["off"] = false;
777   }
778
779   val = val.lower();
780   bool res = boolMap.contains( val );
781   if ( res )
782     bVal = boolMap[val];
783   else
784   {
785     double num = val.toDouble( &res );
786     if ( res )
787       bVal = num != 0;
788   }
789
790   return res;
791 }
792
793 /*!
794   \brief Get the resource value as color. Returns 'true' if it successfull otherwise
795          returns 'false'.
796   \param sect - Resource section name which contains resource.
797   \param name - Name of the resource.
798   \param cVal - Reference on the variable which should contains the resource output.
799 */
800 bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cVal ) const
801 {
802   QString val;
803   if ( !value( sect, name, val, true ) )
804     return false;
805
806   bool res = true;
807   QStringList vals = QStringList::split( ",", val, true );
808
809   QIntList nums;
810   for ( QStringList::const_iterator it = vals.begin(); it != vals.end() && res; ++it )
811     nums.append( (*it).toInt( &res ) );
812
813   if ( res && nums.count() >= 3 )
814     cVal.setRgb( nums[0], nums[1], nums[2] );
815   else
816   {
817     int pack = val.toInt( &res );
818     if ( res )
819       Qtx::rgbSet( pack, cVal );
820   }
821
822   return res;
823 }
824
825 /*!
826   \brief Get the resource value as font. Returns 'true' if it successfull otherwise
827          returns 'false'.
828   \param sect - Resource section name which contains resource.
829   \param name - Name of the resource.
830   \param fVal - Reference on the variable which should contains the resource output.
831 */
832 bool QtxResourceMgr::value( const QString& sect, const QString& name, QFont& fVal ) const
833 {
834   QString val;
835   if ( !value( sect, name, val, true ) )
836     return false;
837
838   QStringList fontDescr = QStringList::split( ",", val );
839
840   if ( fontDescr.count() < 2 )
841     return false;
842
843   QString family = fontDescr[0];
844   if ( family.isEmpty() )
845     return false;
846
847   fVal = QFont( family );
848
849   for ( int i = 1; i < (int)fontDescr.count(); i++ )
850   {
851     QString curval = fontDescr[i].stripWhiteSpace().lower();
852     if ( curval == QString( "bold" ) )
853       fVal.setBold( true );
854     else if ( curval == QString( "italic" ) )
855       fVal.setItalic( true );
856     else if ( curval == QString( "underline" ) )
857       fVal.setUnderline( true );
858     else
859     {
860       bool isOk = false;
861       int ps = curval.toInt( &isOk );
862       if ( isOk )
863         fVal.setPointSize( ps );
864     }
865   }
866
867   return true;
868 }
869
870 /*!
871   \brief Get the resource value as string (native format). Returns 'true' if it
872          successfull otherwise returns 'false'.
873   \param sect  - Resource section name which contains resource.
874   \param name  - Name of the resource.
875   \param val   - Reference on the variable which should contains the resource output.
876   \param subst - If 'true' then manager substitute reference on environment variables
877                  and other resources by thier values. Default value of this parameter
878                  is 'true'
879 */
880 bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& val, const bool subst ) const
881 {
882   initialize();
883
884   bool ok = false;
885   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
886   {
887     ok = it.current()->hasValue( sect, name );
888     if ( ok )
889       val = it.current()->value( sect, name, subst );
890   }
891
892   return ok;
893 }
894
895 /*!
896   \brief Returns the integer resource value. If resource can not be found or converted
897          then specified default value will be returned.
898   \param sect  - Resource section name which contains resource.
899   \param name  - Name of the resource.
900   \param def   - Default resource value which will be used when resource not found.
901 */
902 int QtxResourceMgr::integerValue( const QString& sect, const QString& name, const int def ) const
903 {
904   int val;
905   if ( !value( sect, name, val ) )
906     val = def;
907   return val;
908 }
909
910 /*!
911   \brief Returns the double resource value. If resource can not be found or converted
912          then specified default value will be returned.
913   \param sect  - Resource section name which contains resource.
914   \param name  - Name of the resource.
915   \param def   - Default resource value which will be used when resource not found.
916 */
917 double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, const double def ) const
918 {
919   double val;
920   if ( !value( sect, name, val ) )
921     val = def;
922   return val;
923 }
924
925 /*!
926   \brief Returns the boolean resource value. If resource can not be found or converted
927          then specified default value will be returned.
928   \param sect  - Resource section name which contains resource.
929   \param name  - Name of the resource.
930   \param def   - Default resource value which will be used when resource not found.
931 */
932 bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, const bool def ) const
933 {
934   bool val;
935   if ( !value( sect, name, val ) )
936     val = def;
937   return val;
938 }
939
940 /*!
941   \brief Returns the font resource value. If resource can not be found or converted
942          then specified default value will be returned.
943   \param sect  - Resource section name which contains resource.
944   \param name  - Name of the resource.
945   \param def   - Default resource value which will be used when resource not found.
946 */
947 QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const QFont& def ) const
948 {
949   QFont font;
950   if( !value( sect, name, font ) )
951     font = def;
952   return font;
953 }
954
955 /*!
956   \brief Returns the color resource value. If resource can not be found or converted
957          then specified default value will be returned.
958   \param sect  - Resource section name which contains resource.
959   \param name  - Name of the resource.
960   \param def   - Default resource value which will be used when resource not found.
961 */
962 QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, const QColor& def ) const
963 {
964   QColor val;
965   if ( !value( sect, name, val ) )
966     val = def;
967   return val;
968 }
969
970 /*!
971   \brief Returns the string resource value. If resource can not be found or converted
972          then specified default value will be returned.
973   \param sect  - Resource section name which contains resource.
974   \param name  - Name of the resource.
975   \param def   - Default resource value which will be used when resource not found.
976 */
977 QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, const QString& def ) const
978 {
979   QString val;
980   if ( !value( sect, name, val ) )
981     val = def;
982   return val;
983 }
984
985 /*!
986   \brief Checks existance of the specified resource.
987   \param sect  - Resource section name which contains resource.
988   \param name  - Name of the resource.
989 */
990 bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
991 {
992   initialize();
993
994   bool ok = false;
995   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
996     ok = it.current()->hasValue( sect, name );
997
998   return ok;
999 }
1000
1001 /*!
1002   \brief Checks existance of the specified resource section.
1003   \param sect  - Resource section name which contains resource.
1004 */
1005 bool QtxResourceMgr::hasSection( const QString& sect ) const
1006 {
1007   initialize();
1008
1009   bool ok = false;
1010   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
1011     ok = it.current()->hasSection( sect );
1012
1013   return ok;
1014 }
1015
1016 /*!
1017   \brief Sets the integer resource value.
1018   \param sect  - Resource section name.
1019   \param name  - Name of the resource.
1020   \param val   - Resource value.
1021 */
1022 void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val )
1023 {
1024   int res;
1025   if ( checkExisting() && value( sect, name, res ) && res == val )
1026     return;
1027
1028   setResource( sect, name, QString::number( val ) );
1029 }
1030
1031 /*!
1032   \brief Sets the double resource value.
1033   \param sect  - Resource section name.
1034   \param name  - Name of the resource.
1035   \param val   - Resource value.
1036 */
1037 void QtxResourceMgr::setValue( const QString& sect, const QString& name, double val )
1038 {
1039   double res;
1040   if ( checkExisting() && value( sect, name, res ) && res == val )
1041     return;
1042
1043   setResource( sect, name, QString::number( val, 'g', 12 ) );
1044 }
1045
1046 /*!
1047   \brief Sets the boolean resource value.
1048   \param sect  - Resource section name.
1049   \param name  - Name of the resource.
1050   \param val   - Resource value.
1051 */
1052 void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool val )
1053 {
1054   bool res;
1055   if ( checkExisting() && value( sect, name, res ) && res == val )
1056     return;
1057
1058   setResource( sect, name, QString( val ? "true" : "false" ) );
1059 }
1060
1061 /*!
1062   \brief Sets the color resource value.
1063   \param sect  - Resource section name.
1064   \param name  - Name of the resource.
1065   \param val   - Resource value.
1066 */
1067 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QColor& val )
1068 {
1069   QColor res;
1070   if ( checkExisting() && value( sect, name, res ) && res == val )
1071     return;
1072
1073   setResource( sect, name, QString( "%1, %2, %3" ).arg( val.red() ).arg( val.green() ).arg( val.blue() ) );
1074 }
1075
1076 /*!
1077   \brief Sets the font resource value.
1078   \param sect  - Resource section name.
1079   \param name  - Name of the resource.
1080   \param val   - Resource value.
1081 */
1082 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QFont& val )
1083 {
1084   QFont res;
1085   if ( checkExisting() && value( sect, name, res ) && res == val )
1086     return;
1087
1088   QStringList fontDescr;
1089   fontDescr.append( val.family() );
1090   if ( val.bold() )
1091     fontDescr.append( "Bold" );
1092   if ( val.italic() )
1093     fontDescr.append( "Italic" );
1094   if ( val.underline() )
1095     fontDescr.append( "Underline" );
1096   fontDescr.append( QString( "%1" ).arg( val.pointSize() ) );
1097
1098   setResource( sect, name, fontDescr.join( "," ) );
1099 }
1100
1101 /*!
1102   \brief Sets the string resource value.
1103   \param sect  - Resource section name.
1104   \param name  - Name of the resource.
1105   \param val   - Resource value.
1106 */
1107 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QString& val )
1108 {
1109   QString res;
1110   if ( checkExisting() && value( sect, name, res ) && res == val )
1111     return;
1112
1113   setResource( sect, name, val );
1114 }
1115
1116 /*!
1117   \brief Remove the all specified resource section.
1118   \param sect  - Resource section name.
1119 */
1120 void QtxResourceMgr::remove( const QString& sect )
1121 {
1122   initialize();
1123
1124   for ( ResListIterator it( myResources ); it.current(); ++it )
1125     it.current()->removeSection( sect );
1126 }
1127
1128 /*!
1129   \brief Remove the specified resource.
1130   \param sect  - Resource section name.
1131   \param name  - Name of the resource.
1132 */
1133 void QtxResourceMgr::remove( const QString& sect, const QString& name )
1134 {
1135   initialize();
1136
1137   for ( ResListIterator it( myResources ); it.current(); ++it )
1138     it.current()->removeValue( sect, name );
1139 }
1140
1141 /*!
1142   \brief Returns the current format which operates with resource files.
1143 */
1144 QString QtxResourceMgr::currentFormat() const
1145 {
1146   QString fmt;
1147   if ( !myFormats.isEmpty() )
1148     fmt = myFormats.getFirst()->format();
1149   return fmt;
1150 }
1151
1152 /*!
1153   \brief Sets the current format which operates with resource files.
1154   \param fmt - Resource format name.
1155 */
1156 void QtxResourceMgr::setCurrentFormat( const QString& fmt )
1157 {
1158   Format* form = format( fmt );
1159   if ( !form )
1160     return;
1161
1162   myFormats.remove( form );
1163   myFormats.prepend( form );
1164
1165   if ( myResources.isEmpty() )
1166     return;
1167
1168   ResListIterator resIt( myResources );
1169   if ( resIt.current() )
1170     resIt.current()->setFile( userFileName( appName() ) );
1171   ++resIt;
1172
1173   for ( QStringList::const_iterator it = myDirList.begin(); it != myDirList.end() && resIt.current(); ++it, ++resIt )
1174     resIt.current()->setFile( Qtx::addSlash( *it ) + globalFileName( appName() ) );
1175 }
1176
1177 /*!
1178   \brief Returns the resource format object by it name.
1179   \param fmt - Resource format name.
1180 */
1181 QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
1182 {
1183   Format* form = 0;
1184   for ( FormatListIterator it( myFormats ); it.current() && !form; ++it )
1185   {
1186     if ( it.current()->format() == fmt )
1187       form = it.current();
1188   }
1189
1190   return form;
1191 }
1192
1193 /*!
1194   \brief Add the resource format to the manager. Newly added become current.
1195   \param form - Resource format object.
1196 */
1197 void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
1198 {
1199   if ( !myFormats.contains( form ) )
1200     myFormats.prepend( form );
1201 }
1202
1203 /*!
1204   \brief Remove the resource format from the manager.
1205   \param form - Resource format object.
1206 */
1207 void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
1208 {
1209   myFormats.remove( form );
1210 }
1211
1212 /*!
1213   \brief Returns the string list of the resource format options names.
1214 */
1215 QStringList QtxResourceMgr::options() const
1216 {
1217   return myOptions.keys();
1218 }
1219
1220 /*!
1221   \brief Returns the string value for the specified option. If option doesn't exist
1222          then empty string will be returned.
1223   \param opt - Option name.
1224 */
1225 QString QtxResourceMgr::option( const QString& opt ) const
1226 {
1227   QString val;
1228   if ( myOptions.contains( opt ) )
1229     val = myOptions[opt];
1230   return val;
1231 }
1232
1233 /*!
1234   \brief Sets the string value for the specified option.
1235   \param opt - Option name.
1236   \param val - Option value.
1237 */
1238 void QtxResourceMgr::setOption( const QString& opt, const QString& val )
1239 {
1240   myOptions.insert( opt, val );
1241 }
1242
1243 /*!
1244   \brief Load the all resources from the resource files.
1245 */
1246 bool QtxResourceMgr::load()
1247 {
1248   initialize( false );
1249
1250   Format* fmt = format( currentFormat() );
1251   if ( !fmt )
1252     return false;
1253
1254   bool res = true;
1255   for ( ResListIterator it( myResources ); it.current(); ++it )
1256     res = fmt->load( it.current() ) && res;
1257
1258   return res;
1259 }
1260
1261 /*!
1262   \brief Save the changed resources in to the user resource file.
1263 */
1264 bool QtxResourceMgr::save()
1265 {
1266   initialize( false );
1267
1268   Format* fmt = format( currentFormat() );
1269   if ( !fmt )
1270     return false;
1271
1272   if ( myResources.isEmpty() )
1273     return true;
1274
1275   return fmt->save( myResources.getFirst() );
1276 }
1277
1278 /*!
1279   \brief Returns the string list of the existing section names..
1280 */
1281 QStringList QtxResourceMgr::sections() const
1282 {
1283   initialize();
1284
1285   QMap<QString, int> map;
1286   for ( ResListIterator it( myResources ); it.current(); ++it )
1287   {
1288     QStringList lst = it.current()->sections();
1289     for ( QStringList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
1290       map.insert( *itr, 0 );
1291   }
1292
1293   QStringList res;
1294   for ( QMap<QString, int>::ConstIterator iter = map.begin(); iter != map.end(); ++iter )
1295     res.append( iter.key() );
1296
1297   return res;
1298 }
1299
1300 /*!
1301   \brief Returns the string list of the existing resource names in the specified section.
1302   \param sec - Resource section name.
1303 */
1304 QStringList QtxResourceMgr::parameters( const QString& sec ) const
1305 {
1306   initialize();
1307
1308   QMap<QString, int> map;
1309   for ( ResListIterator it( myResources ); it.current(); ++it )
1310   {
1311     QStringList lst = it.current()->parameters( sec );
1312     for ( QStringList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
1313       map.insert( *itr, 0 );
1314   }
1315
1316   QStringList res;
1317   for ( QMap<QString, int>::ConstIterator iter = map.begin(); iter != map.end(); ++iter )
1318     res.append( iter.key() );
1319
1320   return res;
1321 }
1322
1323 QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const QString& name ) const
1324 {
1325   QString res;
1326   for ( ResListIterator it( myResources ); it.current() && res.isEmpty(); ++it )
1327     res = it.current()->path( sect, prefix, name );
1328   return res;
1329 }
1330
1331 QString QtxResourceMgr::resSection() const
1332 {
1333   QString res = option( "res_section_name" );
1334   if ( res.isEmpty() )
1335     res = QString( "resources" );
1336   return res;
1337 }
1338
1339 QString QtxResourceMgr::langSection() const
1340 {
1341   QString res = option( "lang_section_name" );
1342   if ( res.isEmpty() )
1343     res = QString( "language" );
1344   return res;
1345 }
1346
1347 QPixmap QtxResourceMgr::defaultPixmap() const
1348 {
1349   return myDefaultPix;
1350 }
1351
1352 void QtxResourceMgr::setDefaultPixmap( const QPixmap& pix )
1353 {
1354   myDefaultPix = pix;
1355 }
1356
1357 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name ) const
1358 {
1359   return loadPixmap( prefix, name, true );
1360 }
1361
1362 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const bool useDef ) const
1363 {
1364   return loadPixmap( prefix, name, useDef ? defaultPixmap() : QPixmap() );
1365 }
1366
1367 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const QPixmap& defPix ) const
1368 {
1369   initialize();
1370
1371   QPixmap pix;
1372   for ( ResListIterator it( myResources ); it.current() && pix.isNull(); ++it )
1373     pix = it.current()->loadPixmap( resSection(), prefix, name );
1374   if ( pix.isNull() )
1375     pix = defPix;
1376   return pix;
1377 }
1378
1379 void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
1380 {
1381   initialize();
1382
1383   QMap<QChar, QString> substMap;
1384   substMap.insert( 'A', appName() );
1385
1386   QString lang = l;
1387   if ( lang.isEmpty() )
1388     value( langSection(), "language", lang );
1389
1390   if ( lang.isEmpty() )
1391   {
1392     lang = QString( "en" );
1393     qWarning( QString( "Language not specified. Assumed: %1" ).arg( lang ) );
1394   }
1395
1396   substMap.insert( 'L', lang );
1397
1398   QString trs;
1399   if ( value( langSection(), "translators", trs, false ) && !trs.isEmpty() )
1400   {
1401     QStringList translators    = QStringList::split( "|", option( "translators" ) );
1402     QStringList newTranslators = QStringList::split( "|", trs );
1403     for ( uint i = 0; i < newTranslators.count(); i++ )
1404       if ( translators.find( newTranslators[i] ) == translators.end() )
1405         translators += newTranslators[i];
1406     setOption( "translators", translators.join( "|" ) );
1407   }
1408
1409   QStringList trList = QStringList::split( "|", option( "translators" ) );
1410   if ( trList.isEmpty() )
1411   {
1412     trList.append( "%P_msg_%L.qm" );
1413     qWarning( QString( "Translators not defined. Assumed: %1" ).arg( trList.first() ) );
1414   }
1415
1416   QStringList prefixList;
1417   if ( !pref.isEmpty() )
1418     prefixList.append( pref );
1419   else
1420     prefixList = parameters( resSection() );
1421
1422   for ( QStringList::const_iterator iter = prefixList.begin(); iter != prefixList.end(); ++iter )
1423   {
1424     QString prefix = *iter;
1425     substMap.insert( 'P', prefix );
1426
1427     QStringList trs;
1428     for ( QStringList::const_iterator it = trList.begin(); it != trList.end(); ++it )
1429       trs.append( substMacro( *it, substMap ).stripWhiteSpace() );
1430
1431     for ( QStringList::const_iterator itr = trs.begin(); itr != trs.end(); ++itr )
1432       loadTranslator( prefix, *itr );
1433   }
1434 }
1435
1436 void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name )
1437 {
1438   initialize();
1439
1440   QTranslator* trans = 0;
1441   for ( ResListIterator it( myResources ); it.current() && !trans; ++it )
1442     trans = it.current()->loadTranslator( resSection(), prefix, name );
1443
1444   if ( !trans )
1445     return;
1446
1447   if ( !myTranslator[prefix].contains( trans ) )
1448     myTranslator[prefix].append( trans );
1449   qApp->installTranslator( trans );
1450 }
1451
1452 void QtxResourceMgr::removeTranslators( const QString& prefix )
1453 {
1454   if ( !myTranslator.contains( prefix ) )
1455     return;
1456
1457   for ( TransListIterator it( myTranslator[prefix] ); it.current(); ++it )
1458   {
1459     qApp->removeTranslator( it.current() );
1460     delete it.current();
1461   }
1462
1463   myTranslator.remove( prefix );
1464 }
1465
1466 void QtxResourceMgr::raiseTranslators( const QString& prefix )
1467 {
1468   if ( !myTranslator.contains( prefix ) )
1469     return;
1470
1471   for ( TransListIterator it( myTranslator[prefix] ); it.current(); ++it )
1472   {
1473     qApp->removeTranslator( it.current() );
1474     qApp->installTranslator( it.current() );
1475   }
1476 }
1477
1478 void QtxResourceMgr::refresh()
1479 {
1480   QStringList sl = sections();
1481   for ( QStringList::const_iterator it = sl.begin(); it != sl.end(); ++it )
1482   {
1483     QStringList pl = parameters( *it );
1484     for ( QStringList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
1485       setResource( *it, *itr, stringValue( *it, *itr ) );
1486   }
1487 }
1488
1489 void QtxResourceMgr::setDirList( const QStringList& dl )
1490 {
1491   myDirList = dl;
1492   for ( ResListIterator it( myResources ); it.current(); ++it )
1493     delete it.current();
1494
1495   myResources.clear();
1496 }
1497
1498 void QtxResourceMgr::setResource( const QString& sect, const QString& name, const QString& val )
1499 {
1500   initialize();
1501
1502   if ( !myResources.isEmpty() )
1503     myResources.first()->setValue( sect, name, val );
1504 }
1505
1506 QString QtxResourceMgr::userFileName( const QString& appName ) const
1507 {
1508   QString fileName;
1509   QString pathName = QDir::homeDirPath();
1510
1511 #ifdef WIN32
1512   fileName = QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
1513 #else
1514   fileName = QString( ".%1rc" ).arg( appName );
1515 #endif
1516
1517   if ( !fileName.isEmpty() )
1518     pathName = Qtx::addSlash( pathName ) + fileName;
1519
1520   return pathName;
1521 }
1522
1523 QString QtxResourceMgr::globalFileName( const QString& appName ) const
1524 {
1525   return QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
1526 }
1527
1528 QString QtxResourceMgr::substMacro( const QString& src, const QMap<QChar, QString>& substMap ) const
1529 {
1530   QString trg = src;
1531
1532   QRegExp rx( "%[A-Za-z%]" );
1533
1534   int idx = 0;
1535   while ( ( idx = rx.search( trg, idx ) ) >= 0 )
1536   {
1537     QChar spec = trg.at( idx + 1 );
1538     QString subst;
1539     if ( spec == '%' )
1540       subst = "%";
1541     else if ( substMap.contains( spec ) )
1542       subst = substMap[spec];
1543
1544     if ( !subst.isEmpty() )
1545     {
1546       trg.replace( idx, rx.matchedLength(), subst );
1547       idx += subst.length();
1548     }
1549     else
1550       idx += rx.matchedLength();
1551   }
1552
1553   return trg;
1554 }