Salome HOME
Fix for bug 10438: Crash during Explode on Blocks operation (Global selection on...
[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 ( Section::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   if ( !userFileName( appName() ).isEmpty() )
702     that->myResources.append( new Resources( userFileName( appName() ) ) );
703
704   for ( QStringList::const_iterator it = myDirList.begin(); it != myDirList.end(); ++it )
705   {
706     QString path = Qtx::addSlash( *it ) + globalFileName( appName() );
707     that->myResources.append( new Resources( path ) );
708   }
709
710   if ( autoLoad )
711     that->load();
712 }
713
714 /*!
715   \brief Removes all resources from the manager.
716 */
717 void QtxResourceMgr::clear()
718 {
719   for ( ResListIterator it( myResources ); it.current(); ++it )
720     it.current()->clear();
721 }
722
723 /*!
724   \brief Get the resource value as integer. Returns 'true' if it successfull otherwise
725          returns 'false'.
726   \param sect - Resource section name which contains resource.
727   \param name - Name of the resource.
728   \param iVal - Reference on the variable which should contains the resource output.
729 */
730 bool QtxResourceMgr::value( const QString& sect, const QString& name, int& iVal ) const
731 {
732   QString val;
733   if ( !value( sect, name, val, true ) )
734     return false;
735
736   bool ok;
737   iVal = val.toInt( &ok );
738
739   return ok;
740 }
741
742 /*!
743   \brief Get the resource value as double. Returns 'true' if it successfull otherwise
744          returns 'false'.
745   \param sect - Resource section name which contains resource.
746   \param name - Name of the resource.
747   \param dVal - Reference on the variable which should contains the resource output.
748 */
749 bool QtxResourceMgr::value( const QString& sect, const QString& name, double& dVal ) const
750 {
751   QString val;
752   if ( !value( sect, name, val, true ) )
753     return false;
754
755   bool ok;
756   dVal = val.toDouble( &ok );
757
758   return ok;
759 }
760
761 /*!
762   \brief Get the resource value as boolean. Returns 'true' if it successfull otherwise
763          returns 'false'.
764   \param sect - Resource section name which contains resource.
765   \param name - Name of the resource.
766   \param bVal - Reference on the variable which should contains the resource output.
767 */
768 bool QtxResourceMgr::value( const QString& sect, const QString& name, bool& bVal ) const
769 {
770   QString val;
771   if ( !value( sect, name, val, true ) )
772     return false;
773
774   static QMap<QString, bool> boolMap;
775   if ( boolMap.isEmpty() )
776   {
777     boolMap["true"]  = boolMap["yes"] = boolMap["on"]  = true;
778     boolMap["false"] = boolMap["no"]  = boolMap["off"] = false;
779   }
780
781   val = val.lower();
782   bool res = boolMap.contains( val );
783   if ( res )
784     bVal = boolMap[val];
785   else
786   {
787     double num = val.toDouble( &res );
788     if ( res )
789       bVal = num != 0;
790   }
791
792   return res;
793 }
794
795 /*!
796   \brief Get the resource value as color. Returns 'true' if it successfull otherwise
797          returns 'false'.
798   \param sect - Resource section name which contains resource.
799   \param name - Name of the resource.
800   \param cVal - Reference on the variable which should contains the resource output.
801 */
802 bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cVal ) const
803 {
804   QString val;
805   if ( !value( sect, name, val, true ) )
806     return false;
807
808   bool res = true;
809   QStringList vals = QStringList::split( ",", val, true );
810
811   QIntList nums;
812   for ( QStringList::const_iterator it = vals.begin(); it != vals.end() && res; ++it )
813     nums.append( (*it).toInt( &res ) );
814
815   if ( res && nums.count() >= 3 )
816     cVal.setRgb( nums[0], nums[1], nums[2] );
817   else
818   {
819     int pack = val.toInt( &res );
820     if ( res )
821       Qtx::rgbSet( pack, cVal );
822   }
823
824   return res;
825 }
826
827 /*!
828   \brief Get the resource value as font. Returns 'true' if it successfull otherwise
829          returns 'false'.
830   \param sect - Resource section name which contains resource.
831   \param name - Name of the resource.
832   \param fVal - Reference on the variable which should contains the resource output.
833 */
834 bool QtxResourceMgr::value( const QString& sect, const QString& name, QFont& fVal ) const
835 {
836   QString val;
837   if ( !value( sect, name, val, true ) )
838     return false;
839
840   QStringList fontDescr = QStringList::split( ",", val );
841
842   if ( fontDescr.count() < 2 )
843     return false;
844
845   QString family = fontDescr[0];
846   if ( family.isEmpty() )
847     return false;
848
849   fVal = QFont( family );
850
851   for ( int i = 1; i < (int)fontDescr.count(); i++ )
852   {
853     QString curval = fontDescr[i].stripWhiteSpace().lower();
854     if ( curval == QString( "bold" ) )
855       fVal.setBold( true );
856     else if ( curval == QString( "italic" ) )
857       fVal.setItalic( true );
858     else if ( curval == QString( "underline" ) )
859       fVal.setUnderline( true );
860     else
861     {
862       bool isOk = false;
863       int ps = curval.toInt( &isOk );
864       if ( isOk )
865         fVal.setPointSize( ps );
866     }
867   }
868
869   return true;
870 }
871
872 /*!
873   \brief Get the resource value as string (native format). Returns 'true' if it
874          successfull otherwise returns 'false'.
875   \param sect  - Resource section name which contains resource.
876   \param name  - Name of the resource.
877   \param val   - Reference on the variable which should contains the resource output.
878   \param subst - If 'true' then manager substitute reference on environment variables
879                  and other resources by thier values. Default value of this parameter
880                  is 'true'
881 */
882 bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& val, const bool subst ) const
883 {
884   initialize();
885
886   bool ok = false;
887   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
888   {
889     ok = it.current()->hasValue( sect, name );
890     if ( ok )
891       val = it.current()->value( sect, name, subst );
892   }
893
894   return ok;
895 }
896
897 /*!
898   \brief Returns the integer resource value. If resource can not be found or converted
899          then specified default value will be returned.
900   \param sect  - Resource section name which contains resource.
901   \param name  - Name of the resource.
902   \param def   - Default resource value which will be used when resource not found.
903 */
904 int QtxResourceMgr::integerValue( const QString& sect, const QString& name, const int def ) const
905 {
906   int val;
907   if ( !value( sect, name, val ) )
908     val = def;
909   return val;
910 }
911
912 /*!
913   \brief Returns the double resource value. If resource can not be found or converted
914          then specified default value will be returned.
915   \param sect  - Resource section name which contains resource.
916   \param name  - Name of the resource.
917   \param def   - Default resource value which will be used when resource not found.
918 */
919 double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, const double def ) const
920 {
921   double val;
922   if ( !value( sect, name, val ) )
923     val = def;
924   return val;
925 }
926
927 /*!
928   \brief Returns the boolean resource value. If resource can not be found or converted
929          then specified default value will be returned.
930   \param sect  - Resource section name which contains resource.
931   \param name  - Name of the resource.
932   \param def   - Default resource value which will be used when resource not found.
933 */
934 bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, const bool def ) const
935 {
936   bool val;
937   if ( !value( sect, name, val ) )
938     val = def;
939   return val;
940 }
941
942 /*!
943   \brief Returns the font resource value. If resource can not be found or converted
944          then specified default value will be returned.
945   \param sect  - Resource section name which contains resource.
946   \param name  - Name of the resource.
947   \param def   - Default resource value which will be used when resource not found.
948 */
949 QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const QFont& def ) const
950 {
951   QFont font;
952   if( !value( sect, name, font ) )
953     font = def;
954   return font;
955 }
956
957 /*!
958   \brief Returns the color resource value. If resource can not be found or converted
959          then specified default value will be returned.
960   \param sect  - Resource section name which contains resource.
961   \param name  - Name of the resource.
962   \param def   - Default resource value which will be used when resource not found.
963 */
964 QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, const QColor& def ) const
965 {
966   QColor val;
967   if ( !value( sect, name, val ) )
968     val = def;
969   return val;
970 }
971
972 /*!
973   \brief Returns the string resource value. If resource can not be found or converted
974          then specified default value will be returned.
975   \param sect  - Resource section name which contains resource.
976   \param name  - Name of the resource.
977   \param def   - Default resource value which will be used when resource not found.
978 */
979 QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, const QString& def ) const
980 {
981   QString val;
982   if ( !value( sect, name, val ) )
983     val = def;
984   return val;
985 }
986
987 /*!
988   \brief Checks existance of the specified resource.
989   \param sect  - Resource section name which contains resource.
990   \param name  - Name of the resource.
991 */
992 bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
993 {
994   initialize();
995
996   bool ok = false;
997   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
998     ok = it.current()->hasValue( sect, name );
999
1000   return ok;
1001 }
1002
1003 /*!
1004   \brief Checks existance of the specified resource section.
1005   \param sect  - Resource section name which contains resource.
1006 */
1007 bool QtxResourceMgr::hasSection( const QString& sect ) const
1008 {
1009   initialize();
1010
1011   bool ok = false;
1012   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
1013     ok = it.current()->hasSection( sect );
1014
1015   return ok;
1016 }
1017
1018 /*!
1019   \brief Sets the integer resource value.
1020   \param sect  - Resource section name.
1021   \param name  - Name of the resource.
1022   \param val   - Resource value.
1023 */
1024 void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val )
1025 {
1026   int res;
1027   if ( checkExisting() && value( sect, name, res ) && res == val )
1028     return;
1029
1030   setResource( sect, name, QString::number( val ) );
1031 }
1032
1033 /*!
1034   \brief Sets the double resource value.
1035   \param sect  - Resource section name.
1036   \param name  - Name of the resource.
1037   \param val   - Resource value.
1038 */
1039 void QtxResourceMgr::setValue( const QString& sect, const QString& name, double val )
1040 {
1041   double res;
1042   if ( checkExisting() && value( sect, name, res ) && res == val )
1043     return;
1044
1045   setResource( sect, name, QString::number( val, 'g', 12 ) );
1046 }
1047
1048 /*!
1049   \brief Sets the boolean resource value.
1050   \param sect  - Resource section name.
1051   \param name  - Name of the resource.
1052   \param val   - Resource value.
1053 */
1054 void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool val )
1055 {
1056   bool res;
1057   if ( checkExisting() && value( sect, name, res ) && res == val )
1058     return;
1059
1060   setResource( sect, name, QString( val ? "true" : "false" ) );
1061 }
1062
1063 /*!
1064   \brief Sets the color resource value.
1065   \param sect  - Resource section name.
1066   \param name  - Name of the resource.
1067   \param val   - Resource value.
1068 */
1069 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QColor& val )
1070 {
1071   QColor res;
1072   if ( checkExisting() && value( sect, name, res ) && res == val )
1073     return;
1074
1075   setResource( sect, name, QString( "%1, %2, %3" ).arg( val.red() ).arg( val.green() ).arg( val.blue() ) );
1076 }
1077
1078 /*!
1079   \brief Sets the font resource value.
1080   \param sect  - Resource section name.
1081   \param name  - Name of the resource.
1082   \param val   - Resource value.
1083 */
1084 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QFont& val )
1085 {
1086   QFont res;
1087   if ( checkExisting() && value( sect, name, res ) && res == val )
1088     return;
1089
1090   QStringList fontDescr;
1091   fontDescr.append( val.family() );
1092   if ( val.bold() )
1093     fontDescr.append( "Bold" );
1094   if ( val.italic() )
1095     fontDescr.append( "Italic" );
1096   if ( val.underline() )
1097     fontDescr.append( "Underline" );
1098   fontDescr.append( QString( "%1" ).arg( val.pointSize() ) );
1099
1100   setResource( sect, name, fontDescr.join( "," ) );
1101 }
1102
1103 /*!
1104   \brief Sets the string resource value.
1105   \param sect  - Resource section name.
1106   \param name  - Name of the resource.
1107   \param val   - Resource value.
1108 */
1109 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QString& val )
1110 {
1111   QString res;
1112   if ( checkExisting() && value( sect, name, res ) && res == val )
1113     return;
1114
1115   setResource( sect, name, val );
1116 }
1117
1118 /*!
1119   \brief Remove the all specified resource section.
1120   \param sect  - Resource section name.
1121 */
1122 void QtxResourceMgr::remove( const QString& sect )
1123 {
1124   initialize();
1125
1126   for ( ResListIterator it( myResources ); it.current(); ++it )
1127     it.current()->removeSection( sect );
1128 }
1129
1130 /*!
1131   \brief Remove the specified resource.
1132   \param sect  - Resource section name.
1133   \param name  - Name of the resource.
1134 */
1135 void QtxResourceMgr::remove( const QString& sect, const QString& name )
1136 {
1137   initialize();
1138
1139   for ( ResListIterator it( myResources ); it.current(); ++it )
1140     it.current()->removeValue( sect, name );
1141 }
1142
1143 /*!
1144   \brief Returns the current format which operates with resource files.
1145 */
1146 QString QtxResourceMgr::currentFormat() const
1147 {
1148   QString fmt;
1149   if ( !myFormats.isEmpty() )
1150     fmt = myFormats.getFirst()->format();
1151   return fmt;
1152 }
1153
1154 /*!
1155   \brief Sets the current format which operates with resource files.
1156   \param fmt - Resource format name.
1157 */
1158 void QtxResourceMgr::setCurrentFormat( const QString& fmt )
1159 {
1160   Format* form = format( fmt );
1161   if ( !form )
1162     return;
1163
1164   myFormats.remove( form );
1165   myFormats.prepend( form );
1166
1167   if ( myResources.isEmpty() )
1168     return;
1169
1170   ResListIterator resIt( myResources );
1171   if ( myResources.count() > myDirList.count() && resIt.current() ) {
1172     resIt.current()->setFile( userFileName( appName() ) );
1173     ++resIt;
1174   }
1175
1176   for ( QStringList::const_iterator it = myDirList.begin(); it != myDirList.end() && resIt.current(); ++it, ++resIt )
1177     resIt.current()->setFile( Qtx::addSlash( *it ) + globalFileName( appName() ) );
1178 }
1179
1180 /*!
1181   \brief Returns the resource format object by it name.
1182   \param fmt - Resource format name.
1183 */
1184 QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
1185 {
1186   Format* form = 0;
1187   for ( FormatListIterator it( myFormats ); it.current() && !form; ++it )
1188   {
1189     if ( it.current()->format() == fmt )
1190       form = it.current();
1191   }
1192
1193   return form;
1194 }
1195
1196 /*!
1197   \brief Add the resource format to the manager. Newly added become current.
1198   \param form - Resource format object.
1199 */
1200 void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
1201 {
1202   if ( !myFormats.contains( form ) )
1203     myFormats.prepend( form );
1204 }
1205
1206 /*!
1207   \brief Remove the resource format from the manager.
1208   \param form - Resource format object.
1209 */
1210 void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
1211 {
1212   myFormats.remove( form );
1213 }
1214
1215 /*!
1216   \brief Returns the string list of the resource format options names.
1217 */
1218 QStringList QtxResourceMgr::options() const
1219 {
1220   return myOptions.keys();
1221 }
1222
1223 /*!
1224   \brief Returns the string value for the specified option. If option doesn't exist
1225          then empty string will be returned.
1226   \param opt - Option name.
1227 */
1228 QString QtxResourceMgr::option( const QString& opt ) const
1229 {
1230   QString val;
1231   if ( myOptions.contains( opt ) )
1232     val = myOptions[opt];
1233   return val;
1234 }
1235
1236 /*!
1237   \brief Sets the string value for the specified option.
1238   \param opt - Option name.
1239   \param val - Option value.
1240 */
1241 void QtxResourceMgr::setOption( const QString& opt, const QString& val )
1242 {
1243   myOptions.insert( opt, val );
1244 }
1245
1246 /*!
1247   \brief Load the all resources from the resource files.
1248 */
1249 bool QtxResourceMgr::load()
1250 {
1251   initialize( false );
1252
1253   Format* fmt = format( currentFormat() );
1254   if ( !fmt )
1255     return false;
1256
1257   bool res = true;
1258   for ( ResListIterator it( myResources ); it.current(); ++it )
1259     res = fmt->load( it.current() ) && res;
1260
1261   return res;
1262 }
1263
1264 /*!
1265   \brief Save the changed resources in to the user resource file.
1266 */
1267 bool QtxResourceMgr::save()
1268 {
1269   initialize( false );
1270
1271   Format* fmt = format( currentFormat() );
1272   if ( !fmt )
1273     return false;
1274
1275   if ( myResources.isEmpty() )
1276     return true;
1277
1278   return fmt->save( myResources.getFirst() );
1279 }
1280
1281 /*!
1282   \brief Returns the string list of the existing section names..
1283 */
1284 QStringList QtxResourceMgr::sections() const
1285 {
1286   initialize();
1287
1288   QMap<QString, int> map;
1289   for ( ResListIterator it( myResources ); it.current(); ++it )
1290   {
1291     QStringList lst = it.current()->sections();
1292     for ( QStringList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
1293       map.insert( *itr, 0 );
1294   }
1295
1296   QStringList res;
1297   for ( QMap<QString, int>::ConstIterator iter = map.begin(); iter != map.end(); ++iter )
1298     res.append( iter.key() );
1299
1300   return res;
1301 }
1302
1303 /*!
1304   \brief Returns the string list of the existing resource names in the specified section.
1305   \param sec - Resource section name.
1306 */
1307 QStringList QtxResourceMgr::parameters( const QString& sec ) const
1308 {
1309   initialize();
1310
1311 #if defined(QTX_NO_INDEXED_MAP)
1312   typedef QMap<QString, int> PMap;
1313 #else
1314   typedef IMap<QString, int> PMap;
1315 #endif
1316   PMap pmap;
1317   ResListIterator it( myResources );
1318   it.toLast();
1319   for ( ; it.current(); --it ) {
1320     QStringList lst = it.current()->parameters( sec );
1321     for ( QStringList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
1322       pmap.insert( *itr, 0, false );
1323   }
1324
1325   QStringList res;
1326   for ( PMap::ConstIterator iter = pmap.begin(); iter != pmap.end(); ++iter )
1327     res.append( iter.key() );
1328
1329   return res;
1330 }
1331
1332 QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const QString& name ) const
1333 {
1334   QString res;
1335   for ( ResListIterator it( myResources ); it.current() && res.isEmpty(); ++it )
1336     res = it.current()->path( sect, prefix, name );
1337   return res;
1338 }
1339
1340 QString QtxResourceMgr::resSection() const
1341 {
1342   QString res = option( "res_section_name" );
1343   if ( res.isEmpty() )
1344     res = QString( "resources" );
1345   return res;
1346 }
1347
1348 QString QtxResourceMgr::langSection() const
1349 {
1350   QString res = option( "lang_section_name" );
1351   if ( res.isEmpty() )
1352     res = QString( "language" );
1353   return res;
1354 }
1355
1356 QPixmap QtxResourceMgr::defaultPixmap() const
1357 {
1358   return myDefaultPix;
1359 }
1360
1361 void QtxResourceMgr::setDefaultPixmap( const QPixmap& pix )
1362 {
1363   myDefaultPix = pix;
1364 }
1365
1366 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name ) const
1367 {
1368   return loadPixmap( prefix, name, true );
1369 }
1370
1371 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const bool useDef ) const
1372 {
1373   return loadPixmap( prefix, name, useDef ? defaultPixmap() : QPixmap() );
1374 }
1375
1376 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const QPixmap& defPix ) const
1377 {
1378   initialize();
1379
1380   QPixmap pix;
1381   for ( ResListIterator it( myResources ); it.current() && pix.isNull(); ++it )
1382     pix = it.current()->loadPixmap( resSection(), prefix, name );
1383   if ( pix.isNull() )
1384     pix = defPix;
1385   return pix;
1386 }
1387
1388 void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
1389 {
1390   initialize();
1391
1392   QMap<QChar, QString> substMap;
1393   substMap.insert( 'A', appName() );
1394
1395   QString lang = l;
1396   if ( lang.isEmpty() )
1397     value( langSection(), "language", lang );
1398
1399   if ( lang.isEmpty() )
1400   {
1401     lang = QString( "en" );
1402     qWarning( QString( "Language not specified. Assumed: %1" ).arg( lang ) );
1403   }
1404
1405   substMap.insert( 'L', lang );
1406
1407   QString trs;
1408   if ( value( langSection(), "translators", trs, false ) && !trs.isEmpty() )
1409   {
1410     QStringList translators    = QStringList::split( "|", option( "translators" ) );
1411     QStringList newTranslators = QStringList::split( "|", trs );
1412     for ( uint i = 0; i < newTranslators.count(); i++ )
1413       if ( translators.find( newTranslators[i] ) == translators.end() )
1414         translators += newTranslators[i];
1415     setOption( "translators", translators.join( "|" ) );
1416   }
1417
1418   QStringList trList = QStringList::split( "|", option( "translators" ) );
1419   if ( trList.isEmpty() )
1420   {
1421     trList.append( "%P_msg_%L.qm" );
1422     qWarning( QString( "Translators not defined. Assumed: %1" ).arg( trList.first() ) );
1423   }
1424
1425   QStringList prefixList;
1426   if ( !pref.isEmpty() )
1427     prefixList.append( pref );
1428   else
1429     prefixList = parameters( resSection() );
1430
1431   for ( QStringList::const_iterator iter = prefixList.begin(); iter != prefixList.end(); ++iter )
1432   {
1433     QString prefix = *iter;
1434     substMap.insert( 'P', prefix );
1435
1436     QStringList trs;
1437     for ( QStringList::const_iterator it = trList.begin(); it != trList.end(); ++it )
1438       trs.append( substMacro( *it, substMap ).stripWhiteSpace() );
1439
1440     loadTranslators( prefix, trs );
1441   }
1442 }
1443
1444 void QtxResourceMgr::loadTranslators( const QString& prefix, const QStringList& translators )
1445 {
1446   initialize();
1447
1448   QTranslator* trans = 0;
1449   ResListIterator it( myResources );
1450   it.toLast();
1451   for ( ; it.current(); --it )
1452   {
1453     for ( QStringList::const_iterator itr = translators.begin(); itr != translators.end(); ++itr )
1454     {
1455       trans = it.current()->loadTranslator( resSection(), prefix, *itr );
1456       if ( trans )
1457       {
1458         if ( !myTranslator[prefix].contains( trans ) )
1459           myTranslator[prefix].append( trans );
1460         qApp->installTranslator( trans );
1461       }
1462     }
1463   }
1464 }
1465
1466 void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name )
1467 {
1468   initialize();
1469
1470   QTranslator* trans = 0;
1471   ResListIterator it( myResources );
1472   it.toLast();
1473   for ( ; it.current(); --it )
1474   {
1475     trans = it.current()->loadTranslator( resSection(), prefix, name );
1476     if ( trans )
1477     {
1478       if ( !myTranslator[prefix].contains( trans ) )
1479         myTranslator[prefix].append( trans );
1480       qApp->installTranslator( trans );
1481     }
1482   }
1483 }
1484
1485 void QtxResourceMgr::removeTranslators( const QString& prefix )
1486 {
1487   if ( !myTranslator.contains( prefix ) )
1488     return;
1489
1490   for ( TransListIterator it( myTranslator[prefix] ); it.current(); ++it )
1491   {
1492     qApp->removeTranslator( it.current() );
1493     delete it.current();
1494   }
1495
1496   myTranslator.remove( prefix );
1497 }
1498
1499 void QtxResourceMgr::raiseTranslators( const QString& prefix )
1500 {
1501   if ( !myTranslator.contains( prefix ) )
1502     return;
1503
1504   for ( TransListIterator it( myTranslator[prefix] ); it.current(); ++it )
1505   {
1506     qApp->removeTranslator( it.current() );
1507     qApp->installTranslator( it.current() );
1508   }
1509 }
1510
1511 void QtxResourceMgr::refresh()
1512 {
1513   QStringList sl = sections();
1514   for ( QStringList::const_iterator it = sl.begin(); it != sl.end(); ++it )
1515   {
1516     QStringList pl = parameters( *it );
1517     for ( QStringList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
1518       setResource( *it, *itr, stringValue( *it, *itr ) );
1519   }
1520 }
1521
1522 void QtxResourceMgr::setDirList( const QStringList& dl )
1523 {
1524   myDirList = dl;
1525   for ( ResListIterator it( myResources ); it.current(); ++it )
1526     delete it.current();
1527
1528   myResources.clear();
1529 }
1530
1531 void QtxResourceMgr::setResource( const QString& sect, const QString& name, const QString& val )
1532 {
1533   initialize();
1534
1535   if ( !myResources.isEmpty() )
1536     myResources.first()->setValue( sect, name, val );
1537 }
1538
1539 QString QtxResourceMgr::userFileName( const QString& appName ) const
1540 {
1541   QString fileName;
1542   QString pathName = QDir::homeDirPath();
1543
1544 #ifdef WIN32
1545   fileName = QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
1546 #else
1547   fileName = QString( ".%1rc" ).arg( appName );
1548 #endif
1549
1550   if ( !fileName.isEmpty() )
1551     pathName = Qtx::addSlash( pathName ) + fileName;
1552
1553   return pathName;
1554 }
1555
1556 QString QtxResourceMgr::globalFileName( const QString& appName ) const
1557 {
1558   return QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
1559 }
1560
1561 QString QtxResourceMgr::substMacro( const QString& src, const QMap<QChar, QString>& substMap ) const
1562 {
1563   QString trg = src;
1564
1565   QRegExp rx( "%[A-Za-z%]" );
1566
1567   int idx = 0;
1568   while ( ( idx = rx.search( trg, idx ) ) >= 0 )
1569   {
1570     QChar spec = trg.at( idx + 1 );
1571     QString subst;
1572     if ( spec == '%' )
1573       subst = "%";
1574     else if ( substMap.contains( spec ) )
1575       subst = substMap[spec];
1576
1577     if ( !subst.isEmpty() )
1578     {
1579       trg.replace( idx, rx.matchedLength(), subst );
1580       idx += subst.length();
1581     }
1582     else
1583       idx += rx.matchedLength();
1584   }
1585
1586   return trg;
1587 }