]> SALOME platform Git repositories - modules/gui.git/blob - src/Qtx/QtxResourceMgr.cxx
Salome HOME
New item (FontItem), allowing to show information about font setting and to select...
[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, "" ).stripWhiteSpace();
762   QStringList font_values = QStringList::split( val, "," );
763   if( font_values.count()<2 || font_values.count()>4 )
764     return false;
765   
766   QString family = font_values[0];
767   bool isBold = false, isItalic = false, isOk = false;
768   int pSize = -1;
769   for( int i=1, n=font_values.count(); i<n; i++ )
770   {
771     if( !isBold && font_values[i].lower()=="bold" )
772       isBold = true;
773     else if( !isItalic && font_values[i].lower()=="italic" )
774       isItalic = true;
775     else if( pSize<0 )
776     {
777       pSize = font_values[i].toInt( &isOk );
778       if( !isOk )
779         pSize = -1;
780     }
781   }
782
783   if( pSize>0 && !family.isEmpty() )
784   {
785     fVal = QFont( family, pSize );
786     fVal.setBold( isBold );
787     fVal.setItalic( isItalic );
788     return true;
789   }
790   else
791     return false;
792 }
793
794 bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& val, const bool subst ) const
795 {
796   initialize();
797
798   bool ok = false;
799   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
800   {
801     ok = it.current()->hasValue( sect, name );
802     if ( ok )
803       val = it.current()->value( sect, name, subst );
804   }
805
806   return ok;
807 }
808
809 int QtxResourceMgr::integerValue( const QString& name, const int def ) const
810 {
811   return integerValue( currentSection(), name, def );
812 }
813
814 double QtxResourceMgr::doubleValue( const QString& name, const double def ) const
815 {
816   return doubleValue( currentSection(), name, def );
817 }
818
819 bool QtxResourceMgr::booleanValue( const QString& name, const bool def ) const
820 {
821   return booleanValue( currentSection(), name, def );
822 }
823
824 QFont QtxResourceMgr::fontValue( const QString& name, const QFont& def ) const
825 {
826   return fontValue( currentSection(), name, def );
827 }
828   
829 QColor QtxResourceMgr::colorValue( const QString& name, const QColor& def ) const
830 {
831   return colorValue( currentSection(), name, def );
832 }
833
834 QString QtxResourceMgr::stringValue( const QString& name, const char* def ) const
835 {
836   return stringValue( currentSection(), name, def );
837 }
838
839 int QtxResourceMgr::integerValue( const QString& sect, const QString& name, const int def ) const
840 {
841   int val;
842   if ( !value( sect, name, val ) )
843     val = def;
844   return val;
845 }
846
847 double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, const double def ) const
848 {
849   double val;
850   if ( !value( sect, name, val ) )
851     val = def;
852   return val;
853 }
854
855 bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, const bool def ) const
856 {
857   bool val;
858   if ( !value( sect, name, val ) )
859     val = def;
860   return val;
861 }
862
863 QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const QFont& def ) const
864 {
865   QFont font;
866   if( !value( sect, name, font ) )
867     font = def;
868   return font;
869 }
870
871 QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, const QColor& def ) const
872 {
873   QColor val;
874   if ( !value( sect, name, val ) )
875     val = def;
876   return val;
877 }
878
879 QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, const char* def ) const
880 {
881   QString val;
882   if ( !value( sect, name, val ) )
883     val = def;
884   return val;
885 }
886
887 bool QtxResourceMgr::hasValue( const QString& name ) const
888 {
889   return hasValue( currentSection(), name );
890 }
891
892 bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
893 {
894   initialize();
895
896   bool ok = false;
897   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
898     ok = it.current()->hasValue( sect, name );
899
900   return ok;
901 }
902
903 bool QtxResourceMgr::hasSection( const QString& sect ) const
904 {
905   initialize();
906
907   bool ok = false;
908   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
909     ok = it.current()->hasSection( sect );
910
911   return ok;
912 }
913
914 void QtxResourceMgr::setValue( const QString& name, int val )
915 {
916   setValue( currentSection(), name, val );
917 }
918
919 void QtxResourceMgr::setValue( const QString& name, double val )
920 {
921   setValue( currentSection(), name, val );
922 }
923
924 void QtxResourceMgr::setValue( const QString& name, bool val )
925 {
926   setValue( currentSection(), name, val );
927 }
928
929 void QtxResourceMgr::setValue( const QString& name, const QColor& val )
930 {
931   setValue( currentSection(), name, val );
932 }
933
934 void QtxResourceMgr::setValue( const QString& name, const QFont& val )
935 {
936   setValue( currentSection(), name, val );
937 }
938
939 void QtxResourceMgr::setValue( const QString& name, const QString& val )
940 {
941   setValue( currentSection(), name, val );
942 }
943
944 void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val )
945 {
946   setValue( sect, name, QString::number( val ) );
947 }
948
949 void QtxResourceMgr::setValue( const QString& sect, const QString& name, double val )
950 {
951   setValue( sect, name, QString::number( val, 'g', 12 ) );
952 }
953
954 void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool val )
955 {
956   setValue( sect, name, QString( val ? "true" : "false" ) );
957 }
958
959 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QColor& val )
960 {
961   setValue( sect, name, QString( "%1, %2, %3").arg( val.red() ).arg( val.green() ).arg( val.blue() ) );
962 }
963
964 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QFont& f )
965 {
966   QStringList val;
967   val.append( f.family() );
968   if( f.bold() )
969     val.append( "Bold" );
970   if( f.italic() )
971     val.append( "Italic" );
972   val.append( QString( "%1" ).arg( f.pointSize() ) );
973   
974   setValue( sect, name, val.join( "," ) );
975 }
976
977 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QString& val )
978 {
979   initialize();
980
981   if ( !myResources.isEmpty() )
982     myResources.first()->setValue( sect, name, val );
983 }
984
985 void QtxResourceMgr::remove( const QString& name )
986 {
987   remove( currentSection(), name );
988 }
989
990 void QtxResourceMgr::remove( const QString& sect, const QString& name )
991 {
992   initialize();
993
994   for ( ResListIterator it( myResources ); it.current(); ++it )
995     it.current()->removeValue( sect, name );
996 }
997
998 void QtxResourceMgr::removeSection( const QString& sect )
999 {
1000   initialize();
1001
1002   for ( ResListIterator it( myResources ); it.current(); ++it )
1003     it.current()->removeSection( sect );
1004 }
1005
1006 QString QtxResourceMgr::currentFormat() const
1007 {
1008   QString fmt;
1009   if ( !myFormats.isEmpty() )
1010     fmt = myFormats.getFirst()->format();
1011   return fmt;
1012 }
1013
1014 void QtxResourceMgr::setCurrentFormat( const QString& fmt )
1015 {
1016   Format* form = format( fmt );
1017   if ( !form )
1018     return;
1019
1020   myFormats.remove( form );
1021   myFormats.prepend( form );
1022
1023   if ( myResources.isEmpty() )
1024     return;
1025
1026   ResListIterator resIt( myResources );
1027   if ( resIt.current() )
1028     resIt.current()->setFile( userFileName( appName() ) );
1029   ++resIt;
1030
1031   for ( QStringList::const_iterator it = myDirList.begin(); it != myDirList.end() && resIt.current(); ++it, ++resIt )
1032     resIt.current()->setFile( Qtx::addSlash( *it ) + globalFileName( appName() ) );
1033 }
1034
1035 QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
1036 {
1037   Format* form = 0;
1038   for ( FormatListIterator it( myFormats ); it.current() && !form; ++it )
1039   {
1040     if ( it.current()->format() == fmt )
1041       form = it.current();
1042   }
1043
1044   return form;
1045 }
1046
1047 void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
1048 {
1049   if ( !myFormats.contains( form ) )
1050     myFormats.prepend( form );
1051 }
1052
1053 void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
1054 {
1055   myFormats.remove( form );
1056 }
1057
1058 QStringList QtxResourceMgr::options() const
1059 {
1060   return myOptions.keys();
1061 }
1062
1063 QString QtxResourceMgr::option( const QString& opt ) const
1064 {
1065   QString val;
1066   if ( myOptions.contains( opt ) )
1067     val = myOptions[opt];
1068   return val;
1069 }
1070
1071 void QtxResourceMgr::setOption( const QString& opt, const QString& val )
1072 {
1073   myOptions.insert( opt, val );
1074 }
1075
1076 bool QtxResourceMgr::load()
1077 {
1078   initialize( false );
1079
1080   Format* fmt = format( currentFormat() );
1081   if ( !fmt )
1082     return false;
1083
1084   bool res = true;
1085   for ( ResListIterator it( myResources ); it.current(); ++it )
1086     res = fmt->load( it.current() ) && res;
1087
1088   return res;
1089 }
1090
1091 bool QtxResourceMgr::save()
1092 {
1093   initialize( false );
1094
1095   Format* fmt = format( currentFormat() );
1096   if ( !fmt )
1097     return false;
1098
1099   if ( myResources.isEmpty() )
1100     return true;
1101
1102   return fmt->save( myResources.getFirst() );
1103 }
1104
1105 QStringList QtxResourceMgr::sections() const
1106 {
1107   initialize();
1108
1109   QMap<QString, int> map;
1110   for ( ResListIterator it( myResources ); it.current(); ++it )
1111   {
1112     QStringList lst = it.current()->sections();
1113     for ( QStringList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
1114       map.insert( *itr, 0 );
1115   }
1116
1117   QStringList res;
1118   for ( QMap<QString, int>::ConstIterator iter = map.begin(); iter != map.end(); ++iter )
1119     res.append( iter.key() );
1120
1121   return res;
1122 }
1123
1124 QStringList QtxResourceMgr::parameters( const QString& sec ) const
1125 {
1126   initialize();
1127
1128   QMap<QString, int> map;
1129   for ( ResListIterator it( myResources ); it.current(); ++it )
1130   {
1131     QStringList lst = it.current()->parameters( sec );
1132     for ( QStringList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
1133       map.insert( *itr, 0 );
1134   }
1135
1136   QStringList res;
1137   for ( QMap<QString, int>::ConstIterator iter = map.begin(); iter != map.end(); ++iter )
1138     res.append( iter.key() );
1139
1140   return res;
1141 }
1142
1143 QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const QString& name ) const
1144 {
1145   QString res;
1146   for ( ResListIterator it( myResources ); it.current() && res.isEmpty(); ++it )
1147     res = it.current()->path( sect, prefix, name );
1148   return res;
1149 }
1150
1151 QString QtxResourceMgr::resSection() const
1152 {
1153   QString res = option( "res_section_name" );
1154   if ( res.isEmpty() )
1155     res = QString( "resources" );
1156   return res;
1157 }
1158
1159 QString QtxResourceMgr::langSection() const
1160 {
1161   QString res = option( "lang_section_name" );
1162   if ( res.isEmpty() )
1163     res = QString( "language" );
1164   return res;
1165 }
1166
1167 QPixmap QtxResourceMgr::defaultPixmap() const
1168 {
1169   return myDefaultPix;
1170 }
1171
1172 void QtxResourceMgr::setDefaultPixmap( const QPixmap& pix )
1173 {
1174   myDefaultPix = pix;
1175 }
1176
1177 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name ) const
1178 {
1179   return loadPixmap( prefix, name, true );
1180 }
1181
1182 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const bool useDef ) const
1183 {
1184   return loadPixmap( prefix, name, useDef ? defaultPixmap() : QPixmap() );
1185 }
1186
1187 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const QPixmap& defPix ) const
1188 {
1189   initialize();
1190
1191   QPixmap pix;
1192   for ( ResListIterator it( myResources ); it.current() && pix.isNull(); ++it )
1193     pix = it.current()->loadPixmap( resSection(), prefix, name );
1194   if ( pix.isNull() )
1195     pix = defPix;
1196   return pix;
1197 }
1198
1199 void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
1200 {
1201   initialize();
1202
1203   QMap<QChar, QString> substMap;
1204   substMap.insert( 'A', appName() );
1205
1206   QString lang = l;
1207   if ( lang.isEmpty() )
1208     value( langSection(), "language", lang );
1209
1210   if ( lang.isEmpty() )
1211   {
1212     lang = QString( "en" );
1213     qWarning( QString( "Language not specified. Assumed: %1" ).arg( lang ) );
1214   }
1215
1216   substMap.insert( 'L', lang );
1217
1218   QString trs;
1219   if ( value( langSection(), "translators", trs, false ) && !trs.isEmpty() )
1220   {
1221     QStringList translators    = QStringList::split( "|", option( "translators" ) );
1222     QStringList newTranslators = QStringList::split( "|", trs );
1223     for ( uint i = 0; i < newTranslators.count(); i++ )
1224       if ( translators.find( newTranslators[i] ) == translators.end() )
1225         translators += newTranslators[i];
1226     setOption( "translators", translators.join( "|" ) );
1227   }
1228
1229   QStringList trList = QStringList::split( "|", option( "translators" ) );
1230   if ( trList.isEmpty() )
1231   {
1232     trList.append( "%P_msg_%L.qm" );
1233     qWarning( QString( "Translators not defined. Assumed: %1" ).arg( trList.first() ) );
1234   }
1235
1236   QStringList prefixList;
1237   if ( !pref.isEmpty() )
1238     prefixList.append( pref );
1239   else
1240     prefixList = parameters( resSection() );
1241
1242   for ( QStringList::const_iterator iter = prefixList.begin(); iter != prefixList.end(); ++iter )
1243   {
1244     QString prefix = *iter;
1245     substMap.insert( 'P', prefix );
1246
1247     QStringList trs;
1248     for ( QStringList::const_iterator it = trList.begin(); it != trList.end(); ++it )
1249       trs.append( substMacro( *it, substMap ).stripWhiteSpace() );
1250
1251     for ( QStringList::const_iterator itr = trs.begin(); itr != trs.end(); ++itr )
1252       loadTranslator( prefix, *itr );
1253   }
1254 }
1255
1256 void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name )
1257 {
1258   initialize();
1259
1260   QTranslator* trans = 0;
1261   for ( ResListIterator it( myResources ); it.current() && !trans; ++it )
1262     trans = it.current()->loadTranslator( resSection(), prefix, name );
1263
1264   if ( !trans )
1265     return;
1266
1267   if ( !myTranslator[prefix].contains( trans ) )
1268     myTranslator[prefix].append( trans );
1269   qApp->installTranslator( trans );
1270 }
1271
1272 void QtxResourceMgr::removeTranslators( const QString& prefix )
1273 {
1274   if ( !myTranslator.contains( prefix ) )
1275     return;
1276
1277   for ( TransListIterator it( myTranslator[prefix] ); it.current(); ++it )
1278   {
1279     qApp->removeTranslator( it.current() );
1280     delete it.current();
1281   }
1282
1283   myTranslator.remove( prefix );
1284 }
1285
1286 void QtxResourceMgr::raiseTranslators( const QString& prefix )
1287 {
1288   if ( !myTranslator.contains( prefix ) )
1289     return;
1290
1291   for ( TransListIterator it( myTranslator[prefix] ); it.current(); ++it )
1292   {
1293     qApp->removeTranslator( it.current() );
1294     qApp->installTranslator( it.current() );
1295   }
1296 }
1297
1298 void QtxResourceMgr::refresh()
1299 {
1300   QStringList sl = sections();
1301   for ( QStringList::const_iterator it = sl.begin(); it != sl.end(); ++it )
1302   {
1303     QStringList pl = parameters( *it );
1304     for ( QStringList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
1305       setValue( *it, *itr, stringValue( *it, *itr ) );
1306   }
1307 }
1308
1309 QString QtxResourceMgr::userFileName( const QString& appName ) const
1310 {
1311   QString fileName;
1312   QString pathName = QDir::homeDirPath();
1313
1314 #ifdef WIN32
1315   fileName = QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
1316 #else
1317   fileName = QString( ".%1rc" ).arg( appName );
1318 #endif
1319
1320   if ( !fileName.isEmpty() )
1321     pathName = Qtx::addSlash( pathName ) + fileName;
1322
1323   return pathName;
1324 }
1325
1326 QString QtxResourceMgr::globalFileName( const QString& appName ) const
1327 {
1328   return QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
1329 }
1330
1331 QString QtxResourceMgr::substMacro( const QString& src, const QMap<QChar, QString>& substMap ) const
1332 {
1333   QString trg = src;
1334
1335   QRegExp rx( "%[A-Za-z%]" );
1336
1337   int idx = 0;
1338   while ( ( idx = rx.search( trg, idx ) ) >= 0 )
1339   {
1340     QChar spec = trg.at( idx + 1 );
1341     QString subst;
1342     if ( spec == '%' )
1343       subst = "%";
1344     else if ( substMap.contains( spec ) )
1345       subst = substMap[spec];
1346
1347     if ( !subst.isEmpty() )
1348     {
1349       trg.replace( idx, rx.matchedLength(), subst );
1350       idx += subst.length();
1351     }
1352     else
1353       idx += rx.matchedLength();
1354   }
1355
1356   return trg;
1357 }