]> 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 - 1 ).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 QtxResourceMgr::Format::Format( const QString& fmt )
514 : myFmt( fmt )
515 {
516 }
517
518 QtxResourceMgr::Format::~Format()
519 {
520 }
521
522 QString QtxResourceMgr::Format::format() const
523 {
524   return myFmt;
525 }
526
527 QStringList QtxResourceMgr::Format::options() const
528 {
529   return myOpt.keys();
530 }
531
532 QString QtxResourceMgr::Format::option( const QString& opt ) const
533 {
534   QString val;
535   if ( myOpt.contains( opt ) )
536     val = myOpt[opt];
537   return val;
538 }
539 void QtxResourceMgr::Format::setOption( const QString& opt, const QString& val )
540 {
541   myOpt.insert( opt, val );
542 }
543
544 bool QtxResourceMgr::Format::load( Resources* res )
545 {
546   if ( !res )
547     return false;
548
549   QMap<QString, Section> sections;
550   bool status = load( res->myFileName, sections );
551   if ( status )
552     res->mySections = sections;
553   else
554     qDebug( "QtxResourceMgr: Could not load resource file \"%s\"", res->myFileName.latin1() );
555
556   return status;
557 }
558
559 bool QtxResourceMgr::Format::save( Resources* res )
560 {
561   if ( !res )
562     return false;
563
564   Qtx::mkDir( Qtx::dir( res->myFileName ) );
565
566   return save( res->myFileName, res->mySections );
567 }
568
569 /*!
570         Class: QtxResourceMgr
571         Level: Public
572 */
573
574 QtxResourceMgr::QtxResourceMgr( const QString& appName, const QString& resVarTemplate )
575 : myAppName( appName )
576 {
577   QString envVar = !resVarTemplate.isEmpty() ? resVarTemplate : QString( "%1Resources" );
578   if ( envVar.contains( "%1" ) )
579     envVar = envVar.arg( appName );
580
581   QString dirs;
582   if ( ::getenv( envVar ) )
583     dirs = ::getenv( envVar );
584
585   setDirList( QStringList::split( ";", dirs ) );
586
587   installFormat( new XmlFormat() );
588   installFormat( new IniFormat() );
589
590   setOption( "translators", QString( "%P_msg_%L.qm|%P_images.qm" ) );
591 }
592
593 QtxResourceMgr::~QtxResourceMgr()
594 {
595   QStringList prefList = myTranslator.keys();
596   for ( QStringList::const_iterator it = prefList.begin(); it != prefList.end(); ++it )
597     removeTranslators( *it );
598 }
599
600 QString QtxResourceMgr::appName() const
601 {
602   return myAppName;
603 }
604
605 QStringList QtxResourceMgr::dirList() const
606 {
607   return myDirList;
608 }
609
610 void QtxResourceMgr::setDirList( const QStringList& dl )
611 {
612   myDirList = dl;
613   for ( ResListIterator it( myResources ); it.current(); ++it )
614     delete it.current();
615
616   myResources.clear();
617 }
618
619 void QtxResourceMgr::initialize( const bool autoLoad ) const
620 {
621   if ( !myResources.isEmpty() )
622     return;
623
624   QtxResourceMgr* that = (QtxResourceMgr*)this;
625
626   that->myResources.append( new Resources( userFileName( appName() ) ) );
627   for ( QStringList::const_iterator it = myDirList.begin(); it != myDirList.end(); ++it )
628   {
629     QString path = Qtx::addSlash( *it ) + globalFileName( appName() );
630     that->myResources.append( new Resources( path ) );
631   }
632
633   if ( autoLoad )
634     that->load();
635 }
636
637 void QtxResourceMgr::clear()
638 {
639   for ( ResListIterator it( myResources ); it.current(); ++it )
640     it.current()->clear();
641 }
642
643 QString QtxResourceMgr::currentSection() const
644 {
645   return myCurSection;
646 }
647
648 void QtxResourceMgr::setCurrentSection( const QString& str )
649 {
650   myCurSection = str;
651 }
652
653 bool QtxResourceMgr::value( const QString& name, int& val ) const
654 {
655   return value( currentSection(), name, val );
656 }
657
658 bool QtxResourceMgr::value( const QString& name, double& val ) const
659 {
660   return value( currentSection(), name, val );
661 }
662
663 bool QtxResourceMgr::value( const QString& name, bool& val ) const
664 {
665   return value( currentSection(), name, val );
666 }
667
668 bool QtxResourceMgr::value( const QString& name, QColor& val ) const
669 {
670   return value( currentSection(), name, val );
671 }
672
673 bool QtxResourceMgr::value( const QString& name, QFont& val ) const
674 {
675   return value( currentSection(), name, val );
676 }
677
678 bool QtxResourceMgr::value( const QString& name, QString& val, const bool subst ) const
679 {
680   return value( currentSection(), name, val, subst );
681 }
682
683 bool QtxResourceMgr::value( const QString& sect, const QString& name, int& iVal ) const
684 {
685   QString val;
686   if ( !value( sect, name, val, true ) )
687     return false;
688
689   bool ok;
690   iVal = val.toInt( &ok );
691
692   return ok;
693 }
694
695 bool QtxResourceMgr::value( const QString& sect, const QString& name, double& dVal ) const
696 {
697   QString val;
698   if ( !value( sect, name, val, true ) )
699     return false;
700
701   bool ok;
702   dVal = val.toDouble( &ok );
703
704   return ok;
705 }
706
707 bool QtxResourceMgr::value( const QString& sect, const QString& name, bool& bVal ) const
708 {
709   QString val;
710   if ( !value( sect, name, val, true ) )
711     return false;
712
713   static QMap<QString, bool> boolMap;
714   if ( boolMap.isEmpty() )
715   {
716     boolMap["true"]  = boolMap["yes"] = boolMap["on"]  = true;
717     boolMap["false"] = boolMap["no"]  = boolMap["off"] = false;
718   }
719
720   val = val.lower();
721   bool res = boolMap.contains( val );
722   if ( res )
723     bVal = boolMap[val];
724   else
725   {
726     double num = val.toDouble( &res );
727     if ( res )
728       bVal = num != 0;
729   }
730
731   return res;
732 }
733
734 bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cVal ) const
735 {
736   QString val;
737   if ( !value( sect, name, val, true ) )
738     return false;
739
740   bool res = true;
741   QStringList vals = QStringList::split( ",", val, true );
742
743   QIntList nums;
744   for ( QStringList::const_iterator it = vals.begin(); it != vals.end() && res; ++it )
745     nums.append( (*it).toInt( &res ) );
746
747   if ( res && nums.count() >= 3 )
748     cVal.setRgb( nums[0], nums[1], nums[2] );
749   else
750   {
751     int pack = val.toInt( &res );
752     if ( res )
753       Qtx::rgbSet( pack, cVal );
754   }
755
756   return res;
757 }
758
759 bool QtxResourceMgr::value( const QString& sect, const QString& name, QFont& fVal ) const
760 {
761   QString val = stringValue( sect, name, "" );
762   QStringList font_values = QStringList::split( ",", val );
763   if( font_values.count()<2 || font_values.count()>5 )
764     return false;
765   
766   QString family = font_values[0];
767   bool isBold = false, isItalic = false, isUnderline = false, isOk = false;
768   int pSize = -1;
769   for( int i=1, n=font_values.count(); i<n; i++ )
770   {
771     QString curval = font_values[i].stripWhiteSpace().lower();
772     if( !isBold && curval=="bold" )
773       isBold = true;
774     else if( !isItalic && curval=="italic" )
775       isItalic = true;
776     else if( !isUnderline && curval=="underline" )
777       isUnderline = true;
778     else if( pSize<0 )
779     {
780       pSize = curval.toInt( &isOk );
781       if( !isOk )
782         pSize = -1;
783     }
784   }
785
786   if( pSize>0 && !family.isEmpty() )
787   {
788     fVal = QFont( family, pSize );
789     fVal.setBold( isBold );
790     fVal.setItalic( isItalic );
791     fVal.setUnderline( isUnderline );
792     return true;
793   }
794   else
795     return false;
796 }
797
798 bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& val, const bool subst ) const
799 {
800   initialize();
801
802   bool ok = false;
803   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
804   {
805     ok = it.current()->hasValue( sect, name );
806     if ( ok )
807       val = it.current()->value( sect, name, subst );
808   }
809
810   return ok;
811 }
812
813 int QtxResourceMgr::integerValue( const QString& name, const int def ) const
814 {
815   return integerValue( currentSection(), name, def );
816 }
817
818 double QtxResourceMgr::doubleValue( const QString& name, const double def ) const
819 {
820   return doubleValue( currentSection(), name, def );
821 }
822
823 bool QtxResourceMgr::booleanValue( const QString& name, const bool def ) const
824 {
825   return booleanValue( currentSection(), name, def );
826 }
827
828 QFont QtxResourceMgr::fontValue( const QString& name, const QFont& def ) const
829 {
830   return fontValue( currentSection(), name, def );
831 }
832   
833 QColor QtxResourceMgr::colorValue( const QString& name, const QColor& def ) const
834 {
835   return colorValue( currentSection(), name, def );
836 }
837
838 QString QtxResourceMgr::stringValue( const QString& name, const char* def ) const
839 {
840   return stringValue( currentSection(), name, def );
841 }
842
843 int QtxResourceMgr::integerValue( const QString& sect, const QString& name, const int def ) const
844 {
845   int val;
846   if ( !value( sect, name, val ) )
847     val = def;
848   return val;
849 }
850
851 double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, const double def ) const
852 {
853   double val;
854   if ( !value( sect, name, val ) )
855     val = def;
856   return val;
857 }
858
859 bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, const bool def ) const
860 {
861   bool val;
862   if ( !value( sect, name, val ) )
863     val = def;
864   return val;
865 }
866
867 QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const QFont& def ) const
868 {
869   QFont font;
870   if( !value( sect, name, font ) )
871     font = def;
872   return font;
873 }
874
875 QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, const QColor& def ) const
876 {
877   QColor val;
878   if ( !value( sect, name, val ) )
879     val = def;
880   return val;
881 }
882
883 QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, const char* def ) const
884 {
885   QString val;
886   if ( !value( sect, name, val ) )
887     val = def;
888   return val;
889 }
890
891 bool QtxResourceMgr::hasValue( const QString& name ) const
892 {
893   return hasValue( currentSection(), name );
894 }
895
896 bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
897 {
898   initialize();
899
900   bool ok = false;
901   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
902     ok = it.current()->hasValue( sect, name );
903
904   return ok;
905 }
906
907 bool QtxResourceMgr::hasSection( const QString& sect ) const
908 {
909   initialize();
910
911   bool ok = false;
912   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
913     ok = it.current()->hasSection( sect );
914
915   return ok;
916 }
917
918 void QtxResourceMgr::setValue( const QString& name, int val )
919 {
920   setValue( currentSection(), name, val );
921 }
922
923 void QtxResourceMgr::setValue( const QString& name, double val )
924 {
925   setValue( currentSection(), name, val );
926 }
927
928 void QtxResourceMgr::setValue( const QString& name, bool val )
929 {
930   setValue( currentSection(), name, val );
931 }
932
933 void QtxResourceMgr::setValue( const QString& name, const QColor& val )
934 {
935   setValue( currentSection(), name, val );
936 }
937
938 void QtxResourceMgr::setValue( const QString& name, const QFont& val )
939 {
940   setValue( currentSection(), name, val );
941 }
942
943 void QtxResourceMgr::setValue( const QString& name, const QString& val )
944 {
945   setValue( currentSection(), name, val );
946 }
947
948 void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val )
949 {
950   setValue( sect, name, QString::number( val ) );
951 }
952
953 void QtxResourceMgr::setValue( const QString& sect, const QString& name, double val )
954 {
955   setValue( sect, name, QString::number( val, 'g', 12 ) );
956 }
957
958 void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool val )
959 {
960   setValue( sect, name, QString( val ? "true" : "false" ) );
961 }
962
963 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QColor& val )
964 {
965   setValue( sect, name, QString( "%1, %2, %3").arg( val.red() ).arg( val.green() ).arg( val.blue() ) );
966 }
967
968 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QFont& f )
969 {
970   QStringList val;
971   val.append( f.family() );
972   if( f.bold() )
973     val.append( "Bold" );
974   if( f.italic() )
975     val.append( "Italic" );
976   if( f.underline() )
977     val.append( "Underline" );
978   val.append( QString( "%1" ).arg( f.pointSize() ) );
979   
980   setValue( sect, name, val.join( "," ) );
981 }
982
983 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QString& val )
984 {
985   initialize();
986
987   if ( !myResources.isEmpty() )
988     myResources.first()->setValue( sect, name, val );
989 }
990
991 void QtxResourceMgr::remove( const QString& name )
992 {
993   remove( currentSection(), name );
994 }
995
996 void QtxResourceMgr::remove( const QString& sect, const QString& name )
997 {
998   initialize();
999
1000   for ( ResListIterator it( myResources ); it.current(); ++it )
1001     it.current()->removeValue( sect, name );
1002 }
1003
1004 void QtxResourceMgr::removeSection( const QString& sect )
1005 {
1006   initialize();
1007
1008   for ( ResListIterator it( myResources ); it.current(); ++it )
1009     it.current()->removeSection( sect );
1010 }
1011
1012 QString QtxResourceMgr::currentFormat() const
1013 {
1014   QString fmt;
1015   if ( !myFormats.isEmpty() )
1016     fmt = myFormats.getFirst()->format();
1017   return fmt;
1018 }
1019
1020 void QtxResourceMgr::setCurrentFormat( const QString& fmt )
1021 {
1022   Format* form = format( fmt );
1023   if ( !form )
1024     return;
1025
1026   myFormats.remove( form );
1027   myFormats.prepend( form );
1028
1029   if ( myResources.isEmpty() )
1030     return;
1031
1032   ResListIterator resIt( myResources );
1033   if ( resIt.current() )
1034     resIt.current()->setFile( userFileName( appName() ) );
1035   ++resIt;
1036
1037   for ( QStringList::const_iterator it = myDirList.begin(); it != myDirList.end() && resIt.current(); ++it, ++resIt )
1038     resIt.current()->setFile( Qtx::addSlash( *it ) + globalFileName( appName() ) );
1039 }
1040
1041 QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
1042 {
1043   Format* form = 0;
1044   for ( FormatListIterator it( myFormats ); it.current() && !form; ++it )
1045   {
1046     if ( it.current()->format() == fmt )
1047       form = it.current();
1048   }
1049
1050   return form;
1051 }
1052
1053 void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
1054 {
1055   if ( !myFormats.contains( form ) )
1056     myFormats.prepend( form );
1057 }
1058
1059 void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
1060 {
1061   myFormats.remove( form );
1062 }
1063
1064 QStringList QtxResourceMgr::options() const
1065 {
1066   return myOptions.keys();
1067 }
1068
1069 QString QtxResourceMgr::option( const QString& opt ) const
1070 {
1071   QString val;
1072   if ( myOptions.contains( opt ) )
1073     val = myOptions[opt];
1074   return val;
1075 }
1076
1077 void QtxResourceMgr::setOption( const QString& opt, const QString& val )
1078 {
1079   myOptions.insert( opt, val );
1080 }
1081
1082 bool QtxResourceMgr::load()
1083 {
1084   initialize( false );
1085
1086   Format* fmt = format( currentFormat() );
1087   if ( !fmt )
1088     return false;
1089
1090   bool res = true;
1091   for ( ResListIterator it( myResources ); it.current(); ++it )
1092     res = fmt->load( it.current() ) && res;
1093
1094   return res;
1095 }
1096
1097 bool QtxResourceMgr::save()
1098 {
1099   initialize( false );
1100
1101   Format* fmt = format( currentFormat() );
1102   if ( !fmt )
1103     return false;
1104
1105   if ( myResources.isEmpty() )
1106     return true;
1107
1108   return fmt->save( myResources.getFirst() );
1109 }
1110
1111 QStringList QtxResourceMgr::sections() const
1112 {
1113   initialize();
1114
1115   QMap<QString, int> map;
1116   for ( ResListIterator it( myResources ); it.current(); ++it )
1117   {
1118     QStringList lst = it.current()->sections();
1119     for ( QStringList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
1120       map.insert( *itr, 0 );
1121   }
1122
1123   QStringList res;
1124   for ( QMap<QString, int>::ConstIterator iter = map.begin(); iter != map.end(); ++iter )
1125     res.append( iter.key() );
1126
1127   return res;
1128 }
1129
1130 QStringList QtxResourceMgr::parameters( const QString& sec ) const
1131 {
1132   initialize();
1133
1134   QMap<QString, int> map;
1135   for ( ResListIterator it( myResources ); it.current(); ++it )
1136   {
1137     QStringList lst = it.current()->parameters( sec );
1138     for ( QStringList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
1139       map.insert( *itr, 0 );
1140   }
1141
1142   QStringList res;
1143   for ( QMap<QString, int>::ConstIterator iter = map.begin(); iter != map.end(); ++iter )
1144     res.append( iter.key() );
1145
1146   return res;
1147 }
1148
1149 QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const QString& name ) const
1150 {
1151   QString res;
1152   for ( ResListIterator it( myResources ); it.current() && res.isEmpty(); ++it )
1153     res = it.current()->path( sect, prefix, name );
1154   return res;
1155 }
1156
1157 QString QtxResourceMgr::resSection() const
1158 {
1159   QString res = option( "res_section_name" );
1160   if ( res.isEmpty() )
1161     res = QString( "resources" );
1162   return res;
1163 }
1164
1165 QString QtxResourceMgr::langSection() const
1166 {
1167   QString res = option( "lang_section_name" );
1168   if ( res.isEmpty() )
1169     res = QString( "language" );
1170   return res;
1171 }
1172
1173 QPixmap QtxResourceMgr::defaultPixmap() const
1174 {
1175   return myDefaultPix;
1176 }
1177
1178 void QtxResourceMgr::setDefaultPixmap( const QPixmap& pix )
1179 {
1180   myDefaultPix = pix;
1181 }
1182
1183 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name ) const
1184 {
1185   return loadPixmap( prefix, name, true );
1186 }
1187
1188 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const bool useDef ) const
1189 {
1190   return loadPixmap( prefix, name, useDef ? defaultPixmap() : QPixmap() );
1191 }
1192
1193 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const QPixmap& defPix ) const
1194 {
1195   initialize();
1196
1197   QPixmap pix;
1198   for ( ResListIterator it( myResources ); it.current() && pix.isNull(); ++it )
1199     pix = it.current()->loadPixmap( resSection(), prefix, name );
1200   if ( pix.isNull() )
1201     pix = defPix;
1202   return pix;
1203 }
1204
1205 void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
1206 {
1207   initialize();
1208
1209   QMap<QChar, QString> substMap;
1210   substMap.insert( 'A', appName() );
1211
1212   QString lang = l;
1213   if ( lang.isEmpty() )
1214     value( langSection(), "language", lang );
1215
1216   if ( lang.isEmpty() )
1217   {
1218     lang = QString( "en" );
1219     qWarning( QString( "Language not specified. Assumed: %1" ).arg( lang ) );
1220   }
1221
1222   substMap.insert( 'L', lang );
1223
1224   QString trs;
1225   if ( value( langSection(), "translators", trs, false ) && !trs.isEmpty() )
1226   {
1227     QStringList translators    = QStringList::split( "|", option( "translators" ) );
1228     QStringList newTranslators = QStringList::split( "|", trs );
1229     for ( uint i = 0; i < newTranslators.count(); i++ )
1230       if ( translators.find( newTranslators[i] ) == translators.end() )
1231         translators += newTranslators[i];
1232     setOption( "translators", translators.join( "|" ) );
1233   }
1234
1235   QStringList trList = QStringList::split( "|", option( "translators" ) );
1236   if ( trList.isEmpty() )
1237   {
1238     trList.append( "%P_msg_%L.qm" );
1239     qWarning( QString( "Translators not defined. Assumed: %1" ).arg( trList.first() ) );
1240   }
1241
1242   QStringList prefixList;
1243   if ( !pref.isEmpty() )
1244     prefixList.append( pref );
1245   else
1246     prefixList = parameters( resSection() );
1247
1248   for ( QStringList::const_iterator iter = prefixList.begin(); iter != prefixList.end(); ++iter )
1249   {
1250     QString prefix = *iter;
1251     substMap.insert( 'P', prefix );
1252
1253     QStringList trs;
1254     for ( QStringList::const_iterator it = trList.begin(); it != trList.end(); ++it )
1255       trs.append( substMacro( *it, substMap ).stripWhiteSpace() );
1256
1257     for ( QStringList::const_iterator itr = trs.begin(); itr != trs.end(); ++itr )
1258       loadTranslator( prefix, *itr );
1259   }
1260 }
1261
1262 void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name )
1263 {
1264   initialize();
1265
1266   QTranslator* trans = 0;
1267   for ( ResListIterator it( myResources ); it.current() && !trans; ++it )
1268     trans = it.current()->loadTranslator( resSection(), prefix, name );
1269
1270   if ( !trans )
1271     return;
1272
1273   if ( !myTranslator[prefix].contains( trans ) )
1274     myTranslator[prefix].append( trans );
1275   qApp->installTranslator( trans );
1276 }
1277
1278 void QtxResourceMgr::removeTranslators( const QString& prefix )
1279 {
1280   if ( !myTranslator.contains( prefix ) )
1281     return;
1282
1283   for ( TransListIterator it( myTranslator[prefix] ); it.current(); ++it )
1284   {
1285     qApp->removeTranslator( it.current() );
1286     delete it.current();
1287   }
1288
1289   myTranslator.remove( prefix );
1290 }
1291
1292 void QtxResourceMgr::raiseTranslators( const QString& prefix )
1293 {
1294   if ( !myTranslator.contains( prefix ) )
1295     return;
1296
1297   for ( TransListIterator it( myTranslator[prefix] ); it.current(); ++it )
1298   {
1299     qApp->removeTranslator( it.current() );
1300     qApp->installTranslator( it.current() );
1301   }
1302 }
1303
1304 void QtxResourceMgr::refresh()
1305 {
1306   QStringList sl = sections();
1307   for ( QStringList::const_iterator it = sl.begin(); it != sl.end(); ++it )
1308   {
1309     QStringList pl = parameters( *it );
1310     for ( QStringList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
1311       setValue( *it, *itr, stringValue( *it, *itr ) );
1312   }
1313 }
1314
1315 QString QtxResourceMgr::userFileName( const QString& appName ) const
1316 {
1317   QString fileName;
1318   QString pathName = QDir::homeDirPath();
1319
1320 #ifdef WIN32
1321   fileName = QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
1322 #else
1323   fileName = QString( ".%1rc" ).arg( appName );
1324 #endif
1325
1326   if ( !fileName.isEmpty() )
1327     pathName = Qtx::addSlash( pathName ) + fileName;
1328
1329   return pathName;
1330 }
1331
1332 QString QtxResourceMgr::globalFileName( const QString& appName ) const
1333 {
1334   return QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
1335 }
1336
1337 QString QtxResourceMgr::substMacro( const QString& src, const QMap<QChar, QString>& substMap ) const
1338 {
1339   QString trg = src;
1340
1341   QRegExp rx( "%[A-Za-z%]" );
1342
1343   int idx = 0;
1344   while ( ( idx = rx.search( trg, idx ) ) >= 0 )
1345   {
1346     QChar spec = trg.at( idx + 1 );
1347     QString subst;
1348     if ( spec == '%' )
1349       subst = "%";
1350     else if ( substMap.contains( spec ) )
1351       subst = substMap[spec];
1352
1353     if ( !subst.isEmpty() )
1354     {
1355       trg.replace( idx, rx.matchedLength(), subst );
1356       idx += subst.length();
1357     }
1358     else
1359       idx += rx.matchedLength();
1360   }
1361
1362   return trg;
1363 }