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