Salome HOME
9824aff30b8f3b9bb4296783dc6875210b58d89d
[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 QtxResourceMgr* mgr, const QString& fileName )
40 : myFileName( fileName ),
41   myMgr( const_cast<QtxResourceMgr*>( mgr ) )
42 {
43 }
44
45 /*!
46   Destructor
47 */
48 QtxResourceMgr::Resources::~Resources()
49 {
50 }
51
52 /*!
53   Returns name of resource file
54   This file is used to load/save operations
55 */
56 QString QtxResourceMgr::Resources::file() const
57 {
58   return myFileName;
59 }
60
61 /*!
62   Sets name of resource file
63   \param fn - name of file
64 */
65 void QtxResourceMgr::Resources::setFile( const QString& fn )
66 {
67   myFileName = fn;
68 }
69
70 /*!
71   Returns string representation of parameter value
72   Returns QString::null if there is no such parameter
73
74   \param sect - name of section
75   \param name - name of parameter
76   \param subst - if it is true, then the substitution of variables
77   will be done with help of makeSubstitution method
78   \sa makeSubstitution()
79 */
80 QString QtxResourceMgr::Resources::value( const QString& sect, const QString& name, const bool subst ) const
81 {
82   QString val;
83
84   if ( hasValue( sect, name ) )
85   {
86     val = section( sect )[name];
87     if ( subst )
88       val = makeSubstitution( val, sect, name );
89   }
90   return val;
91 }
92
93 /*!
94   Sets value by it's string representation
95
96   \param sect - name of section
97   \param name - name of parameter
98   \param val - string value
99 */
100 void QtxResourceMgr::Resources::setValue( const QString& sect, const QString& name, const QString& val )
101 {
102   Section& s = section( sect );
103   s.insert( name, val );
104 }
105
106 /*!
107   \return true if section exists
108   \param sect - name of section
109 */
110 bool QtxResourceMgr::Resources::hasSection( const QString& sect ) const
111 {
112   return mySections.contains( sect );
113 }
114
115 /*!
116   \return true if parameter exists in section
117   \param sect - name of section
118   \param name - name of parameter
119 */
120 bool QtxResourceMgr::Resources::hasValue( const QString& sect, const QString& name ) const
121 {
122   return hasSection( sect ) && section( sect ).contains( name );
123 }
124
125 /*!
126   Removes section from resources
127   \param sect - name of section
128 */
129 void QtxResourceMgr::Resources::removeSection( const QString& sect )
130 {
131   mySections.remove( sect );
132 }
133
134 /*!
135   Removes parameter from section
136   \param sect - name of section
137   \param name - name of parameter
138 */
139 void QtxResourceMgr::Resources::removeValue( const QString& sect, const QString& name )
140 {
141   if ( !hasSection( sect ) )
142     return;
143
144   Section& s = section( sect );
145   s.remove( name );
146
147   if ( s.isEmpty() )
148     mySections.remove( sect );
149 }
150
151 /*!
152   Removes all sections
153 */
154 void QtxResourceMgr::Resources::clear()
155 {
156   mySections.clear();
157 }
158
159 /*!
160   \return list of section names
161 */
162 QStringList QtxResourceMgr::Resources::sections() const
163 {
164   return mySections.keys();
165 }
166
167 /*!
168   \return list of parameter names from section
169   \param sec - name of section
170 */
171 QStringList QtxResourceMgr::Resources::parameters( const QString& sec ) const
172 {
173   if ( !hasSection( sec ) )
174     return QStringList();
175
176   return section( sec ).keys();
177 }
178
179 /*!
180   \return path of file from directory built by parameter
181   \return QString::null if built path doesn't exist
182   \param sec - name of section
183   \param prefix - name of parameter containing some path
184   \param name - name of file
185 */
186 QString QtxResourceMgr::Resources::path( const QString& sec, const QString& prefix, const QString& name ) const
187 {
188   QString filePath = fileName( sec, prefix, name );
189   if ( !filePath.isEmpty() )
190   {
191     if ( !QFileInfo( filePath ).exists() )
192       filePath = QString::null;
193   }
194   return filePath;
195 }
196
197 /*!
198   \return corresponding resource manager
199 */
200 QtxResourceMgr* QtxResourceMgr::Resources::resMgr() const
201 {
202   return myMgr;
203 }
204
205 /*!
206   \return instance of section by it's name. Section will be created if it doesn't exist
207 */
208 QtxResourceMgr::Section& QtxResourceMgr::Resources::section( const QString& sn )
209 {
210   if ( !mySections.contains( sn ) )
211     mySections.insert( sn, Section() );
212
213   return mySections[sn];
214 }
215
216 /*!
217   \return instance of section by it's name. Section will be created if it doesn't exist
218 */
219 const QtxResourceMgr::Section& QtxResourceMgr::Resources::section( const QString& sn ) const
220 {
221   return mySections[sn];
222 }
223
224 /*!
225   \return full path of file
226   \param sect - name of section
227   \param prefix - name of parameter containing some path
228   \param name - name of file
229 */
230 QString QtxResourceMgr::Resources::fileName( const QString& sect, const QString& prefix, const QString& name ) const
231 {
232   QString path;
233   if ( hasValue( sect, prefix ) )
234   {
235     path = value( sect, prefix, true );
236     if ( !path.isEmpty() )
237     {
238       if ( QFileInfo( path ).isRelative() )
239         path = Qtx::addSlash( QFileInfo( myFileName ).dirPath( true ) ) + path;
240
241       path = Qtx::addSlash( path ) + name;
242     }
243   }
244   if( !path.isEmpty() )
245   {
246     QString fname = QDir::convertSeparators( path );
247     QFileInfo inf( fname );
248     fname = inf.absFilePath();
249     return fname;
250   }
251   return QString();
252 }
253
254 /*!
255   \return QPixmap loaded from file
256   \param sect - name of section
257   \param prefix - name of parameter containing some path
258   \param name - name of picture file
259 */
260 QPixmap QtxResourceMgr::Resources::loadPixmap( const QString& sect, const QString& prefix, const QString& name ) const
261 {
262   QString fname = fileName( sect, prefix, name );
263   bool toCache = resMgr() ? resMgr()->isPixmapCached() : false;
264   QPixmap p;
265   if( toCache && myPixmapCache.contains( fname ) )
266     p = myPixmapCache[fname];
267   else
268   {
269     p.load( fname );
270     if( toCache )
271       ( ( QMap<QString,QPixmap>& )myPixmapCache ).insert( fname, p );
272   }
273   return p;
274 }
275
276 /*!
277   \return just created and loaded translator
278   \param sect - name of section
279   \param prefix - name of parameter containing some path
280   \param name - name of file
281 */
282 QTranslator* QtxResourceMgr::Resources::loadTranslator( const QString& sect, const QString& prefix, const QString& name ) const
283 {
284   QTranslator* trans = new QTranslator( 0 );
285   if ( !trans->load( fileName( sect, prefix, name ) ) )
286   {
287     delete trans;
288     trans = 0;
289   }
290   return trans;
291 }
292
293 /*!
294   Finds in string variables by patterns: ${name} or $(name) or %name%
295   \return first found name or QString::null if there is no ones
296   \param str - string where the search is processed
297   \param start - integer value for returning start position of variable
298   \param len - integer value for returning length of variable
299 */
300 QString QtxResourceMgr::Resources::environmentVariable( const QString& str, int& start, int& len ) const
301 {
302   QString varName = QString::null;
303   len = 0;
304
305   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_]*)\\%" );
306
307   int pos = rx.search( str, start );
308   if ( pos != -1 )
309   {
310     start = pos;
311     len = rx.matchedLength();
312     QStringList caps = rx.capturedTexts();
313     for ( uint i = 1; i <= caps.count() && varName.isEmpty(); i++ )
314       varName = *caps.at( i );
315   }
316   return varName;
317 }
318
319 /*!
320   Substitutes variables by its' values. If variable is from enviroment,
321   it will be replaced by environment value. If it isn't, method tries to
322   find it's value among resources
323   \return new variant of string 'str'
324   \param str - string to process substitution
325   \param sect - section, in which the variables will be finding
326   \param name - name of variable which must be ignored during substitution
327 */
328 QString QtxResourceMgr::Resources::makeSubstitution( const QString& str, const QString& sect, const QString& name ) const
329 {
330   QString res = str;
331
332   QMap<QString, int> ignoreMap;
333   ignoreMap.insert( name, 0 );
334
335   int start( 0 ), len( 0 );
336   while ( true )
337   {
338     QString envName = environmentVariable( res, start, len );
339     if ( envName.isNull() )
340       break;
341
342     QString newStr = QString::null;
343     if ( ::getenv( envName ) )
344       newStr = QString( ::getenv( envName ) );
345
346     if ( newStr.isNull() )
347     {
348       if ( ignoreMap.contains( envName ) )
349       {
350         start += len;
351         continue;
352       }
353
354       if ( hasValue( sect, envName ) )
355         newStr = value( sect, envName, false );
356       ignoreMap.insert( envName, 0 );
357     }
358     res.replace( start, len, newStr );
359   }
360
361   return res;
362 }
363
364 /*!
365         Class: QtxResourceMgr::IniFormat
366         Level: Internal
367 */
368 class QtxResourceMgr::IniFormat : public Format
369 {
370 public:
371   IniFormat();
372   ~IniFormat();
373
374 protected:
375   virtual bool load( const QString&, QMap<QString, Section>& );
376   virtual bool save( const QString&, const QMap<QString, Section>& );
377 };
378
379 /*!
380   Default constructor
381 */
382 QtxResourceMgr::IniFormat::IniFormat()
383 : Format( "ini" )
384 {
385 }
386
387 /*!
388   Destructor
389 */
390 QtxResourceMgr::IniFormat::~IniFormat()
391 {
392 }
393
394 /*!
395   Loads resources from ini-file to map of sections
396   \param fname - name of resource file
397   \param secMap - map of sections
398 */
399 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap )
400 {
401   QFile file( fname );
402   if ( !file.open( IO_ReadOnly ) )
403     return false;
404
405   QTextStream ts( &file );
406
407   QString data;
408   int line = 0;
409   bool res = true;
410   QString section;
411
412   QString separator = option( "separator" );
413   if ( separator.isNull() )
414     separator = QString( "=" );
415
416   QString comment = option( "comment" );
417   if ( comment.isNull() )
418     comment = QString( "#" );
419
420   while ( true )
421   {
422     data = ts.readLine();
423     line++;
424
425     if ( data.isNull() )
426       break;
427
428     data = data.stripWhiteSpace();
429     if ( data.isEmpty() )
430       continue;
431
432     if ( data.startsWith( comment ) )
433       continue;
434
435     QRegExp rx( "^\\[([\\w\\s\\._]*)\\]$" );
436     if ( rx.search( data ) != -1 )
437     {
438       section = rx.cap( 1 );
439       if ( section.isEmpty() )
440       {
441         res = false;
442         qWarning( QString( "Empty section in line %1" ).arg( line ) );
443       }
444     }
445     else if ( data.contains( "=" ) && !section.isEmpty() )
446     {
447       int pos = data.find( separator );
448       QString key = data.left( pos ).stripWhiteSpace();
449       QString val = data.mid( pos + 1 ).stripWhiteSpace();
450       secMap[section].insert( key, val );
451     }
452     else
453     {
454       res = false;
455       section.isEmpty() ? qWarning( "Current section is empty" ) :
456                           qWarning( QString( "Error in line: %1" ).arg( line ) );
457     }
458   }
459
460   file.close();
461
462   return res;
463 }
464
465 /*!
466   Saves map of sections to resource ini-file
467   \param fname - name of resource file
468   \param secMap - map of sections
469 */
470 bool QtxResourceMgr::IniFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
471 {
472   QFile file( fname );
473   if ( !file.open( IO_WriteOnly ) )
474     return false;
475
476   bool res = true;
477   for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end() && res; ++it )
478   {
479     QString data = QString( "[%1]\n" ).arg( it.key() );
480     for ( Section::ConstIterator iter = it.data().begin(); iter != it.data().end(); ++iter )
481       data += iter.key() + " = " + iter.data() + "\n";
482     data += "\n";
483
484     res = file.writeBlock( data.latin1(), data.length() ) == (int)data.length();
485   }
486
487   file.close();
488
489   return res;
490 }
491
492 /*!
493         Class: QtxResourceMgr::XmlFormat
494         Level: Internal
495 */
496
497 class QtxResourceMgr::XmlFormat : public Format
498 {
499 public:
500   XmlFormat();
501   ~XmlFormat();
502
503 protected:
504   virtual bool load( const QString&, QMap<QString, Section>& );
505   virtual bool save( const QString&, const QMap<QString, Section>& );
506
507 private:
508   QString      docTag() const;
509   QString      sectionTag() const;
510   QString      parameterTag() const;
511   QString      nameAttribute() const;
512   QString      valueAttribute() const;
513 };
514
515 /*!
516   Default constructor
517 */
518 QtxResourceMgr::XmlFormat::XmlFormat()
519 : Format( "xml" )
520 {
521 }
522
523 /*!
524   Destructor
525 */
526 QtxResourceMgr::XmlFormat::~XmlFormat()
527 {
528 }
529
530 /*!
531   Loads resources from xml-file to map of sections
532   \param fname - name of resource file
533   \param secMap - map of sections
534 */
535 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap )
536 {
537   bool res = false;
538
539 #ifndef QT_NO_DOM
540
541   QFile file( fname );
542   if ( !file.open( IO_ReadOnly ) )
543   {
544     qDebug( "File cannot be opened" );
545     return false;
546   }
547
548   QDomDocument doc;
549
550   res = doc.setContent( &file );
551   file.close();
552
553   if ( !res )
554   {
555     qDebug( "File is empty" );
556     return false;
557   }
558
559   QDomElement root = doc.documentElement();
560   if ( root.isNull() || root.tagName() != docTag() )
561   {
562     qDebug( "Invalid root" );
563     return false;
564   }
565
566   QDomNode sectNode = root.firstChild();
567   while ( res && !sectNode.isNull() )
568   {
569     res = sectNode.isElement();
570     if ( res )
571     {
572       QDomElement sectElem = sectNode.toElement();
573       if ( sectElem.tagName() == sectionTag() && sectElem.hasAttribute( nameAttribute() ) )
574       {
575         QString section = sectElem.attribute( nameAttribute() );
576         QDomNode paramNode = sectNode.firstChild();
577         while ( res && !paramNode.isNull() )
578         {
579           res = paramNode.isElement();
580           if ( res )
581           {
582             QDomElement paramElem = paramNode.toElement();
583             if ( paramElem.tagName() == parameterTag() &&
584                  paramElem.hasAttribute( nameAttribute() ) && paramElem.hasAttribute( valueAttribute() ) )
585             {
586               QString paramName = paramElem.attribute( nameAttribute() );
587               QString paramValue = paramElem.attribute( valueAttribute() );
588
589               secMap[section].insert( paramName, paramValue );
590             }
591             else
592             {
593               qDebug( "Invalid parameter element" );
594               res = false;
595             }
596           }
597           else
598           {
599             res = paramNode.isComment();
600             if( !res )
601               qDebug( "Node isn't element nor comment" );
602           }
603
604           paramNode = paramNode.nextSibling();
605         }
606       }
607       else
608       {
609         qDebug( "Invalid section" );
610         res = false;
611       }
612     }
613     else
614     {
615       res = sectNode.isComment(); // if it's a comment -- let it be, pass it..
616       if( !res )
617         qDebug( "Node isn't element nor comment" );
618     }
619
620     sectNode = sectNode.nextSibling();
621   }
622
623 #endif
624
625   if( res )
626     qDebug( QString( "File '%1' is loaded successfully" ).arg( fname ) );
627   return res;
628 }
629
630 /*!
631   Saves map of sections to resource xml-file
632   \param fname - name of resource file
633   \param secMap - map of sections
634 */
635 bool QtxResourceMgr::XmlFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
636 {
637   bool res = false;
638
639 #ifndef QT_NO_DOM
640
641   QFile file( fname );
642   if ( !file.open( IO_WriteOnly ) )
643     return false;
644
645   QDomDocument doc( docTag() );
646   QDomElement root = doc.createElement( docTag() );
647   doc.appendChild( root );
648
649   for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end(); ++it )
650   {
651     QDomElement sect = doc.createElement( sectionTag() );
652     sect.setAttribute( nameAttribute(), it.key() );
653     root.appendChild( sect );
654     for ( Section::ConstIterator iter = it.data().begin(); iter != it.data().end(); ++iter )
655     {
656       QDomElement val = doc.createElement( parameterTag() );
657       val.setAttribute( nameAttribute(), iter.key() );
658       val.setAttribute( valueAttribute(), iter.data() );
659       sect.appendChild( val );
660     }
661   }
662
663   QString docStr = doc.toString();
664   res = file.writeBlock( docStr.latin1(), docStr.length() ) == (int)docStr.length();
665   file.close();
666
667 #endif
668
669   return res;
670 }
671
672 /*!
673   \return XML tag of document
674 */
675 QString QtxResourceMgr::XmlFormat::docTag() const
676 {
677   QString tag = option( "doc_tag" );
678   if ( tag.isEmpty() )
679     tag = QString( "document" );
680   return tag;
681 }
682
683 /*!
684   \return XML tag of section
685 */
686 QString QtxResourceMgr::XmlFormat::sectionTag() const
687 {
688   QString tag = option( "section_tag" );
689   if ( tag.isEmpty() )
690     tag = QString( "section" );
691   return tag;
692 }
693
694 /*!
695   \return XML tag of parameter
696 */
697 QString QtxResourceMgr::XmlFormat::parameterTag() const
698 {
699   QString tag = option( "parameter_tag" );
700   if ( tag.isEmpty() )
701     tag = QString( "parameter" );
702   return tag;
703 }
704
705 /*!
706   \return XML attribute of parameter name
707 */
708 QString QtxResourceMgr::XmlFormat::nameAttribute() const
709 {
710   QString str = option( "name_attribute" );
711   if ( str.isEmpty() )
712     str = QString( "name" );
713   return str;
714 }
715
716 /*!
717   \return XML attribute of parameter value
718 */
719 QString QtxResourceMgr::XmlFormat::valueAttribute() const
720 {
721   QString str = option( "value_attribute" );
722   if ( str.isEmpty() )
723     str = QString( "value" );
724   return str;
725 }
726
727 /*!
728         Class: QtxResourceMgr::Format
729         Level: Public
730 */
731
732 /*!
733   \brief Constructs the format object with specified name.
734   \param fmt - name of the format
735 */
736 QtxResourceMgr::Format::Format( const QString& fmt )
737 : myFmt( fmt )
738 {
739 }
740
741 /*!
742   \brief Destructs the format object.
743 */
744 QtxResourceMgr::Format::~Format()
745 {
746 }
747
748 /*!
749   \brief Returns the format name.
750 */
751 QString QtxResourceMgr::Format::format() const
752 {
753   return myFmt;
754 }
755
756 /*!
757   \brief Returns the string list of the format options.
758 */
759 QStringList QtxResourceMgr::Format::options() const
760 {
761   return myOpt.keys();
762 }
763
764 /*!
765   \brief Returns the value of the option with specified name.
766          If option doesn't exist then empty string returned.
767   \param opt - name of the option
768 */
769 QString QtxResourceMgr::Format::option( const QString& opt ) const
770 {
771   QString val;
772   if ( myOpt.contains( opt ) )
773     val = myOpt[opt];
774   return val;
775 }
776
777 /*!
778   \brief Sets the value of the option with specified name.
779   \param opt - name of the option
780   \param opt - value of the option
781 */
782 void QtxResourceMgr::Format::setOption( const QString& opt, const QString& val )
783 {
784   myOpt.insert( opt, val );
785 }
786
787 /*!
788   \brief Perform the loading of the resources from resource file.
789   \param res - resources object which will be loaded
790 */
791 bool QtxResourceMgr::Format::load( Resources* res )
792 {
793   if ( !res )
794     return false;
795
796   QMap<QString, Section> sections;
797   bool status = load( res->myFileName, sections );
798   if ( status )
799     res->mySections = sections;
800   else
801     qDebug( "QtxResourceMgr: Could not load resource file \"%s\"", res->myFileName.latin1() );
802
803   return status;
804 }
805
806 /*!
807   \brief Perform the saving of the resources into resource file.
808   \param res - resources object which will be saved
809 */
810 bool QtxResourceMgr::Format::save( Resources* res )
811 {
812   if ( !res )
813     return false;
814
815   Qtx::mkDir( Qtx::dir( res->myFileName ) );
816
817   QtxResourceMgr* mgr = res->resMgr();
818   QString name = mgr ? mgr->userFileName( mgr->appName(), false ) : res->myFileName;
819   return save( name, res->mySections );
820 }
821
822 /*!
823         Class: QtxResourceMgr
824         Level: Public
825 */
826
827 /*!
828   \brief Constructs the resource manager object for application.
829   \param appName - name of the application which resources will be used.
830   \param resVarTemplate - template for the resource environment variable name which
831                           should point to the resource directory list.
832                           Default value is "%1Resources". Its mean that for application
833                           with name "MyApp" environment variable "MyAppResources" will
834                           be used. Template may not have the parameter '%1' substituted
835                           by application name. In this case this string will be used as
836                           is without substitution.
837   Resource environment variable should contains one or several resource directories
838   separated by symbol ';'. Resource directories list transfered into the setDirList().
839   These directories and the user home directory used for the loading application resources.
840   Each of the resource directories can contains resource file. The name of this file defined
841   by the function globalFileName(). Resource file name in the user home defined by the
842   function userFileName(). Any resource looking firstly in the user home resources then
843   resource directories used in the specified order. All setted resources always stored into
844   the resource file at the user home. Only user home resource file is saved.
845   If you want to ignore of loading of Local User Preferences, you needs setup setIngoreUserValues()
846   as true.
847 */
848 QtxResourceMgr::QtxResourceMgr( const QString& appName, const QString& resVarTemplate )
849 : myAppName( appName ),
850   myCheckExist( true ),
851   myIsPixmapCached( true ),
852   myIsIgnoreUserValues( false )
853 {
854   QString envVar = !resVarTemplate.isEmpty() ? resVarTemplate : QString( "%1Resources" );
855   if ( envVar.contains( "%1" ) )
856     envVar = envVar.arg( appName );
857
858   QString dirs;
859   if ( ::getenv( envVar ) )
860     dirs = ::getenv( envVar );
861 #ifdef WNT
862   QString dirsep = ";";      // for Windows: ";" is used as directories separator
863 #else
864   QString dirsep = "[:|;]";  // for Linux: both ":" and ";" can be used
865 #endif
866   setDirList( QStringList::split( QRegExp(dirsep), dirs ) );
867
868   installFormat( new XmlFormat() );
869   installFormat( new IniFormat() );
870
871   setOption( "translators", QString( "%P_msg_%L.qm|%P_images.qm" ) );
872 }
873
874 /*!
875   \brief Destructs the resource manager object and free allocated memory.
876 */
877 QtxResourceMgr::~QtxResourceMgr()
878 {
879   QStringList prefList = myTranslator.keys();
880   for ( QStringList::const_iterator it = prefList.begin(); it != prefList.end(); ++it )
881     removeTranslators( *it );
882 }
883
884 /*!
885   \brief Returns the application name.
886 */
887 QString QtxResourceMgr::appName() const
888 {
889   return myAppName;
890 }
891
892 /*!
893   \brief Returns the checking of the existance flag. If its 'true' then resource
894          will be setted into the manager only if it doesn't exist or has different
895          value that existing value.
896 */
897 bool QtxResourceMgr::checkExisting() const
898 {
899   return myCheckExist;
900 }
901
902 /*!
903   \brief Sets the checking of the existance flag.
904   \param on - boolean value of the flag.
905 */
906 void QtxResourceMgr::setCheckExisting( const bool on )
907 {
908   myCheckExist = on;
909 }
910
911 /*!
912   \brief Returns the resource directories list except user home directory.
913 */
914 QStringList QtxResourceMgr::dirList() const
915 {
916   return myDirList;
917 }
918
919 /*!
920   \brief Initialise the manager. Prepare the resource containers and load resources.
921   \param autoLoad - if 'true' then all resources will be loaded.
922 */
923 void QtxResourceMgr::initialize( const bool autoLoad ) const
924 {
925   if ( !myResources.isEmpty() )
926     return;
927
928   QtxResourceMgr* that = (QtxResourceMgr*)this;
929
930   if ( !userFileName( appName() ).isEmpty() )
931     that->myResources.append( new Resources( this, userFileName( appName() ) ) );
932
933   for ( QStringList::const_iterator it = myDirList.begin(); it != myDirList.end(); ++it )
934   {
935     QString path = Qtx::addSlash( *it ) + globalFileName( appName() );
936     that->myResources.append( new Resources( this, path ) );
937   }
938
939   if ( autoLoad )
940     that->load();
941 }
942
943 /*!
944   \brief Return true if all loaded pixmaps are stored in internal map; by default: true
945 */
946 bool QtxResourceMgr::isPixmapCached() const
947 {
948   return myIsPixmapCached;
949 }
950
951 /*!
952   \brief Set true, if it is necessary to store all loaded pixmap in internal map
953   (it accelerates following calls of loadPixmap)
954 */
955 void QtxResourceMgr::setIsPixmapCached( const bool on )
956 {
957   myIsPixmapCached = on;
958 }
959
960 /*!
961   \brief Removes all resources from the manager.
962 */
963 void QtxResourceMgr::clear()
964 {
965   for ( ResListIterator it( myResources ); it.current(); ++it )
966     it.current()->clear();
967 }
968
969 /*!
970   Set state 'ignore user values'.
971   If it is true, then all resources loaded from user home directory is ignored
972 */
973 void QtxResourceMgr::setIgnoreUserValues( const bool val )
974 {
975   myIsIgnoreUserValues = val;
976 }
977
978 /*!
979   \return state 'ignore user values'
980 */
981 bool QtxResourceMgr::ignoreUserValues() const
982 {
983   return myIsIgnoreUserValues;
984 }
985
986 /*!
987   \brief Get the resource value as integer. Returns 'true' if it successfull otherwise
988          returns 'false'.
989   \param sect - Resource section name which contains resource.
990   \param name - Name of the resource.
991   \param iVal - Reference on the variable which should contains the resource output.
992 */
993 bool QtxResourceMgr::value( const QString& sect, const QString& name, int& iVal ) const
994 {
995   QString val;
996   if ( !value( sect, name, val, true ) )
997     return false;
998
999   bool ok;
1000   iVal = val.toInt( &ok );
1001
1002   return ok;
1003 }
1004
1005 /*!
1006   \brief Get the resource value as double. Returns 'true' if it successfull otherwise
1007          returns 'false'.
1008   \param sect - Resource section name which contains resource.
1009   \param name - Name of the resource.
1010   \param dVal - Reference on the variable which should contains the resource output.
1011 */
1012 bool QtxResourceMgr::value( const QString& sect, const QString& name, double& dVal ) const
1013 {
1014   QString val;
1015   if ( !value( sect, name, val, true ) )
1016     return false;
1017
1018   bool ok;
1019   dVal = val.toDouble( &ok );
1020
1021   return ok;
1022 }
1023
1024 /*!
1025   \brief Get the resource value as boolean. Returns 'true' if it successfull otherwise
1026          returns 'false'.
1027   \param sect - Resource section name which contains resource.
1028   \param name - Name of the resource.
1029   \param bVal - Reference on the variable which should contains the resource output.
1030 */
1031 bool QtxResourceMgr::value( const QString& sect, const QString& name, bool& bVal ) const
1032 {
1033   QString val;
1034   if ( !value( sect, name, val, true ) )
1035     return false;
1036
1037   static QMap<QString, bool> boolMap;
1038   if ( boolMap.isEmpty() )
1039   {
1040     boolMap["true"]  = boolMap["yes"] = boolMap["on"]  = true;
1041     boolMap["false"] = boolMap["no"]  = boolMap["off"] = false;
1042   }
1043
1044   val = val.lower();
1045   bool res = boolMap.contains( val );
1046   if ( res )
1047     bVal = boolMap[val];
1048   else
1049   {
1050     double num = val.toDouble( &res );
1051     if ( res )
1052       bVal = num != 0;
1053   }
1054
1055   return res;
1056 }
1057
1058 /*!
1059   \brief Get the resource value as color. Returns 'true' if it successfull otherwise
1060          returns 'false'.
1061   \param sect - Resource section name which contains resource.
1062   \param name - Name of the resource.
1063   \param cVal - Reference on the variable which should contains the resource output.
1064 */
1065 bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cVal ) const
1066 {
1067   QString val;
1068   if ( !value( sect, name, val, true ) )
1069     return false;
1070
1071   bool res = true;
1072   QStringList vals = QStringList::split( ",", val, true );
1073
1074   QIntList nums;
1075   for ( QStringList::const_iterator it = vals.begin(); it != vals.end() && res; ++it )
1076     nums.append( (*it).toInt( &res ) );
1077
1078   if ( res && nums.count() >= 3 )
1079     cVal.setRgb( nums[0], nums[1], nums[2] );
1080   else
1081   {
1082     int pack = val.toInt( &res );
1083     if ( res )
1084       Qtx::rgbSet( pack, cVal );
1085   }
1086
1087   return res;
1088 }
1089
1090 /*!
1091   \brief Get the resource value as font. Returns 'true' if it successfull otherwise
1092          returns 'false'.
1093   \param sect - Resource section name which contains resource.
1094   \param name - Name of the resource.
1095   \param fVal - Reference on the variable which should contains the resource output.
1096 */
1097 bool QtxResourceMgr::value( const QString& sect, const QString& name, QFont& fVal ) const
1098 {
1099   QString val;
1100   if ( !value( sect, name, val, true ) )
1101     return false;
1102
1103   QStringList fontDescr = QStringList::split( ",", val );
1104
1105   if ( fontDescr.count() < 2 )
1106     return false;
1107
1108   QString family = fontDescr[0];
1109   if ( family.isEmpty() )
1110     return false;
1111
1112   fVal = QFont( family );
1113
1114   for ( int i = 1; i < (int)fontDescr.count(); i++ )
1115   {
1116     QString curval = fontDescr[i].stripWhiteSpace().lower();
1117     if ( curval == QString( "bold" ) )
1118       fVal.setBold( true );
1119     else if ( curval == QString( "italic" ) )
1120       fVal.setItalic( true );
1121     else if ( curval == QString( "underline" ) )
1122       fVal.setUnderline( true );
1123     else
1124     {
1125       bool isOk = false;
1126       int ps = curval.toInt( &isOk );
1127       if ( isOk )
1128         fVal.setPointSize( ps );
1129     }
1130   }
1131
1132   return true;
1133 }
1134
1135 /*!
1136   \brief Get the resource value as string (native format). Returns 'true' if it
1137          successfull otherwise returns 'false'.
1138   \param sect  - Resource section name which contains resource.
1139   \param name  - Name of the resource.
1140   \param val   - Reference on the variable which should contains the resource output.
1141   \param subst - If 'true' then manager substitute reference on environment variables
1142                  and other resources by thier values. Default value of this parameter
1143                  is 'true'
1144 */
1145 bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& val, const bool subst ) const
1146 {
1147   initialize();
1148
1149   bool ok = false;
1150  
1151   ResListIterator it( myResources );
1152   if ( ignoreUserValues() )
1153     ++it;
1154
1155   for ( ; it.current() && !ok; ++it )
1156   {
1157     ok = it.current()->hasValue( sect, name );
1158     if ( ok )
1159       val = it.current()->value( sect, name, subst );
1160   }
1161
1162   return ok;
1163 }
1164
1165 /*!
1166   \brief Returns the integer resource value. If resource can not be found or converted
1167          then specified default value will be returned.
1168   \param sect  - Resource section name which contains resource.
1169   \param name  - Name of the resource.
1170   \param def   - Default resource value which will be used when resource not found.
1171 */
1172 int QtxResourceMgr::integerValue( const QString& sect, const QString& name, const int def ) const
1173 {
1174   int val;
1175   if ( !value( sect, name, val ) )
1176     val = def;
1177   return val;
1178 }
1179
1180 /*!
1181   \brief Returns the double resource value. If resource can not be found or converted
1182          then specified default value will be returned.
1183   \param sect  - Resource section name which contains resource.
1184   \param name  - Name of the resource.
1185   \param def   - Default resource value which will be used when resource not found.
1186 */
1187 double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, const double def ) const
1188 {
1189   double val;
1190   if ( !value( sect, name, val ) )
1191     val = def;
1192   return val;
1193 }
1194
1195 /*!
1196   \brief Returns the boolean resource value. If resource can not be found or converted
1197          then specified default value will be returned.
1198   \param sect  - Resource section name which contains resource.
1199   \param name  - Name of the resource.
1200   \param def   - Default resource value which will be used when resource not found.
1201 */
1202 bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, const bool def ) const
1203 {
1204   bool val;
1205   if ( !value( sect, name, val ) )
1206     val = def;
1207   return val;
1208 }
1209
1210 /*!
1211   \brief Returns the font resource value. If resource can not be found or converted
1212          then specified default value will be returned.
1213   \param sect  - Resource section name which contains resource.
1214   \param name  - Name of the resource.
1215   \param def   - Default resource value which will be used when resource not found.
1216 */
1217 QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const QFont& def ) const
1218 {
1219   QFont font;
1220   if( !value( sect, name, font ) )
1221     font = def;
1222   return font;
1223 }
1224
1225 /*!
1226   \brief Returns the color resource value. If resource can not be found or converted
1227          then specified default value will be returned.
1228   \param sect  - Resource section name which contains resource.
1229   \param name  - Name of the resource.
1230   \param def   - Default resource value which will be used when resource not found.
1231 */
1232 QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, const QColor& def ) const
1233 {
1234   QColor val;
1235   if ( !value( sect, name, val ) )
1236     val = def;
1237   return val;
1238 }
1239
1240 /*!
1241   \brief Returns the string resource value. If resource can not be found or converted
1242          then specified default value will be returned.
1243   \param sect  - Resource section name which contains resource.
1244   \param name  - Name of the resource.
1245   \param def   - Default resource value which will be used when resource not found.
1246 */
1247 QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, const QString& def ) const
1248 {
1249   QString val;
1250   if ( !value( sect, name, val ) )
1251     val = def;
1252   return val;
1253 }
1254
1255 /*!
1256   \brief Checks existance of the specified resource.
1257   \param sect  - Resource section name which contains resource.
1258   \param name  - Name of the resource.
1259 */
1260 bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
1261 {
1262   initialize();
1263
1264   bool ok = false;
1265   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
1266     ok = it.current()->hasValue( sect, name );
1267
1268   return ok;
1269 }
1270
1271 /*!
1272   \brief Checks existance of the specified resource section.
1273   \param sect  - Resource section name which contains resource.
1274 */
1275 bool QtxResourceMgr::hasSection( const QString& sect ) const
1276 {
1277   initialize();
1278
1279   bool ok = false;
1280   for ( ResListIterator it( myResources ); it.current() && !ok; ++it )
1281     ok = it.current()->hasSection( sect );
1282
1283   return ok;
1284 }
1285
1286 /*!
1287   \brief Sets the integer resource value.
1288   \param sect  - Resource section name.
1289   \param name  - Name of the resource.
1290   \param val   - Resource value.
1291 */
1292 void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val )
1293 {
1294   int res;
1295   if ( checkExisting() && value( sect, name, res ) && res == val )
1296     return;
1297
1298   setResource( sect, name, QString::number( val ) );
1299 }
1300
1301 /*!
1302   \brief Sets the double resource value.
1303   \param sect  - Resource section name.
1304   \param name  - Name of the resource.
1305   \param val   - Resource value.
1306 */
1307 void QtxResourceMgr::setValue( const QString& sect, const QString& name, double val )
1308 {
1309   double res;
1310   if ( checkExisting() && value( sect, name, res ) && res == val )
1311     return;
1312
1313   setResource( sect, name, QString::number( val, 'g', 12 ) );
1314 }
1315
1316 /*!
1317   \brief Sets the boolean resource value.
1318   \param sect  - Resource section name.
1319   \param name  - Name of the resource.
1320   \param val   - Resource value.
1321 */
1322 void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool val )
1323 {
1324   bool res;
1325   if ( checkExisting() && value( sect, name, res ) && res == val )
1326     return;
1327
1328   setResource( sect, name, QString( val ? "true" : "false" ) );
1329 }
1330
1331 /*!
1332   \brief Sets the color resource value.
1333   \param sect  - Resource section name.
1334   \param name  - Name of the resource.
1335   \param val   - Resource value.
1336 */
1337 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QColor& val )
1338 {
1339   QColor res;
1340   if ( checkExisting() && value( sect, name, res ) && res == val )
1341     return;
1342
1343   setResource( sect, name, QString( "%1, %2, %3" ).arg( val.red() ).arg( val.green() ).arg( val.blue() ) );
1344 }
1345
1346 /*!
1347   \brief Sets the font resource value.
1348   \param sect  - Resource section name.
1349   \param name  - Name of the resource.
1350   \param val   - Resource value.
1351 */
1352 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QFont& val )
1353 {
1354   QFont res;
1355   if ( checkExisting() && value( sect, name, res ) && res == val )
1356     return;
1357
1358   QStringList fontDescr;
1359   fontDescr.append( val.family() );
1360   if ( val.bold() )
1361     fontDescr.append( "Bold" );
1362   if ( val.italic() )
1363     fontDescr.append( "Italic" );
1364   if ( val.underline() )
1365     fontDescr.append( "Underline" );
1366   fontDescr.append( QString( "%1" ).arg( val.pointSize() ) );
1367
1368   setResource( sect, name, fontDescr.join( "," ) );
1369 }
1370
1371 /*!
1372   \brief Sets the string resource value.
1373   \param sect  - Resource section name.
1374   \param name  - Name of the resource.
1375   \param val   - Resource value.
1376 */
1377 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QString& val )
1378 {
1379   QString res;
1380   if ( checkExisting() && value( sect, name, res ) && res == val )
1381     return;
1382
1383   setResource( sect, name, val );
1384 }
1385
1386 /*!
1387   \brief Remove the all specified resource section.
1388   \param sect  - Resource section name.
1389 */
1390 void QtxResourceMgr::remove( const QString& sect )
1391 {
1392   initialize();
1393
1394   for ( ResListIterator it( myResources ); it.current(); ++it )
1395     it.current()->removeSection( sect );
1396 }
1397
1398 /*!
1399   \brief Remove the specified resource.
1400   \param sect  - Resource section name.
1401   \param name  - Name of the resource.
1402 */
1403 void QtxResourceMgr::remove( const QString& sect, const QString& name )
1404 {
1405   initialize();
1406
1407   for ( ResListIterator it( myResources ); it.current(); ++it )
1408     it.current()->removeValue( sect, name );
1409 }
1410
1411 /*!
1412   \brief Returns the current format which operates with resource files.
1413 */
1414 QString QtxResourceMgr::currentFormat() const
1415 {
1416   QString fmt;
1417   if ( !myFormats.isEmpty() )
1418     fmt = myFormats.getFirst()->format();
1419   return fmt;
1420 }
1421
1422 /*!
1423   \brief Sets the current format which operates with resource files.
1424   \param fmt - Resource format name.
1425 */
1426 void QtxResourceMgr::setCurrentFormat( const QString& fmt )
1427 {
1428   Format* form = format( fmt );
1429   if ( !form )
1430     return;
1431
1432   myFormats.remove( form );
1433   myFormats.prepend( form );
1434
1435   if ( myResources.isEmpty() )
1436     return;
1437
1438   ResListIterator resIt( myResources );
1439   if ( myResources.count() > myDirList.count() && resIt.current() ) {
1440     resIt.current()->setFile( userFileName( appName() ) );
1441     ++resIt;
1442   }
1443
1444   for ( QStringList::const_iterator it = myDirList.begin(); it != myDirList.end() && resIt.current(); ++it, ++resIt )
1445     resIt.current()->setFile( Qtx::addSlash( *it ) + globalFileName( appName() ) );
1446 }
1447
1448 /*!
1449   \brief Returns the resource format object by it name.
1450   \param fmt - Resource format name.
1451 */
1452 QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
1453 {
1454   Format* form = 0;
1455   for ( FormatListIterator it( myFormats ); it.current() && !form; ++it )
1456   {
1457     if ( it.current()->format() == fmt )
1458       form = it.current();
1459   }
1460
1461   return form;
1462 }
1463
1464 /*!
1465   \brief Add the resource format to the manager. Newly added become current.
1466   \param form - Resource format object.
1467 */
1468 void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
1469 {
1470   if ( !myFormats.contains( form ) )
1471     myFormats.prepend( form );
1472 }
1473
1474 /*!
1475   \brief Remove the resource format from the manager.
1476   \param form - Resource format object.
1477 */
1478 void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
1479 {
1480   myFormats.remove( form );
1481 }
1482
1483 /*!
1484   \brief Returns the string list of the resource format options names.
1485 */
1486 QStringList QtxResourceMgr::options() const
1487 {
1488   return myOptions.keys();
1489 }
1490
1491 /*!
1492   \brief Returns the string value for the specified option. If option doesn't exist
1493          then empty string will be returned.
1494   \param opt - Option name.
1495 */
1496 QString QtxResourceMgr::option( const QString& opt ) const
1497 {
1498   QString val;
1499   if ( myOptions.contains( opt ) )
1500     val = myOptions[opt];
1501   return val;
1502 }
1503
1504 /*!
1505   \brief Sets the string value for the specified option.
1506   \param opt - Option name.
1507   \param val - Option value.
1508 */
1509 void QtxResourceMgr::setOption( const QString& opt, const QString& val )
1510 {
1511   myOptions.insert( opt, val );
1512 }
1513
1514 /*!
1515   \brief Load the all resources from the resource files.
1516 */
1517 bool QtxResourceMgr::load()
1518 {
1519   initialize( false );
1520
1521   Format* fmt = format( currentFormat() );
1522   if ( !fmt )
1523     return false;
1524
1525   bool res = true;
1526   for ( ResListIterator it( myResources ); it.current(); ++it )
1527     res = fmt->load( it.current() ) && res;
1528
1529   return res;
1530 }
1531
1532 /*!
1533   \brief Import some file with resources
1534 */
1535 bool QtxResourceMgr::import( const QString& fname )
1536 {
1537   Format* fmt = format( currentFormat() );
1538   if ( !fmt )
1539     return false;
1540
1541   Resources* r = myResources.getFirst();
1542   if( !r )
1543     return false;
1544
1545   QString old = r->file();
1546   r->setFile( fname );
1547   bool res = fmt->load( r );
1548   r->setFile( old );
1549   return res;
1550 }
1551
1552 /*!
1553   \brief Save the changed resources in to the user resource file.
1554 */
1555 bool QtxResourceMgr::save()
1556 {
1557   initialize( false );
1558
1559   Format* fmt = format( currentFormat() );
1560   if ( !fmt )
1561     return false;
1562
1563   if ( myResources.isEmpty() )
1564     return true;
1565
1566   return fmt->save( myResources.getFirst() );
1567 }
1568
1569 /*!
1570   \brief Returns the string list of the existing section names..
1571 */
1572 QStringList QtxResourceMgr::sections() const
1573 {
1574   initialize();
1575
1576   QMap<QString, int> map;
1577   for ( ResListIterator it( myResources ); it.current(); ++it )
1578   {
1579     QStringList lst = it.current()->sections();
1580     for ( QStringList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
1581       map.insert( *itr, 0 );
1582   }
1583
1584   QStringList res;
1585   for ( QMap<QString, int>::ConstIterator iter = map.begin(); iter != map.end(); ++iter )
1586     res.append( iter.key() );
1587
1588   return res;
1589 }
1590
1591 /*!
1592   \brief Returns the string list of the existing resource names in the specified section.
1593   \param sec - Resource section name.
1594 */
1595 QStringList QtxResourceMgr::parameters( const QString& sec ) const
1596 {
1597   initialize();
1598
1599 #if defined(QTX_NO_INDEXED_MAP)
1600   typedef QMap<QString, int> PMap;
1601 #else
1602   typedef IMap<QString, int> PMap;
1603 #endif
1604   PMap pmap;
1605   ResListIterator it( myResources );
1606   it.toLast();
1607   for ( ; it.current(); --it ) {
1608     QStringList lst = it.current()->parameters( sec );
1609     for ( QStringList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
1610       pmap.insert( *itr, 0, false );
1611   }
1612
1613   QStringList res;
1614   for ( PMap::ConstIterator iter = pmap.begin(); iter != pmap.end(); ++iter )
1615     res.append( iter.key() );
1616
1617   return res;
1618 }
1619
1620 /*!
1621   \return path of file from directory built by parameter
1622   \return QString::null if built path doesn't exist
1623   \param sec - name of section
1624   \param prefix - name of parameter containing some path
1625   \param name - name of file
1626 */
1627 QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const QString& name ) const
1628 {
1629   QString res;
1630   for ( ResListIterator it( myResources ); it.current() && res.isEmpty(); ++it )
1631     res = it.current()->path( sect, prefix, name );
1632   return res;
1633 }
1634
1635 /*!
1636   \return section corresponding to resources paths
1637 */
1638 QString QtxResourceMgr::resSection() const
1639 {
1640   QString res = option( "res_section_name" );
1641   if ( res.isEmpty() )
1642     res = QString( "resources" );
1643   return res;
1644 }
1645
1646 /*!
1647   \return section corresponding to language settings
1648 */
1649 QString QtxResourceMgr::langSection() const
1650 {
1651   QString res = option( "lang_section_name" );
1652   if ( res.isEmpty() )
1653     res = QString( "language" );
1654   return res;
1655 }
1656
1657 /*!
1658   \return default image used when during loading the image file doesn't exist
1659 */
1660 QPixmap QtxResourceMgr::defaultPixmap() const
1661 {
1662   return myDefaultPix;
1663 }
1664
1665 /*!
1666   Set image as default image used when during loading the image file doesn't exist
1667   \param pix - image
1668 */
1669 void QtxResourceMgr::setDefaultPixmap( const QPixmap& pix )
1670 {
1671   myDefaultPix = pix;
1672 }
1673
1674 /*!
1675   \return image loaded from file 
1676   \param prefix - name of parameter containing some path
1677   \param name - name of file
1678 */
1679 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name ) const
1680 {
1681   return loadPixmap( prefix, name, true );
1682 }
1683
1684 /*!
1685   \return image loaded from file 
1686   \param prefix - name of parameter containing some path
1687   \param name - name of file
1688   \param useDef - indicates if it is possible to use default image returning by defaultPixmap() method.
1689   If it is false, the empty pixmap will be used as default
1690   \sa defaultPixmap()
1691 */
1692 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const bool useDef ) const
1693 {
1694   return loadPixmap( prefix, name, useDef ? defaultPixmap() : QPixmap() );
1695 }
1696
1697 /*!
1698   Finds in all sections an existing path corresponding to 'prefix' parameter
1699   and load image with name 'name' from this folder
1700
1701   \return image loaded from file 
1702   \param prefix - name of parameter containing some path
1703   \param name - name of file
1704   \param defPix - default image used when file doesn't exist
1705 */
1706 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const QPixmap& defPix ) const
1707 {
1708   initialize();
1709
1710   QPixmap pix;
1711   for ( ResListIterator it( myResources ); it.current() && pix.isNull(); ++it )
1712     pix = it.current()->loadPixmap( resSection(), prefix, name );
1713   if ( pix.isNull() )
1714     pix = defPix;
1715   return pix;
1716 }
1717
1718 /*!
1719   Loads translator for language
1720   Name of translator file is constructed by list returning by option "translators" or,
1721   if it is empty, by predefined pattern "%P_msg_%L.qm". It is recommended to used in translators
1722   name the strings %A, %P, %L whose will be replaced by application name, prefix and language name correspondingly
1723
1724   \param pref - name of parameter containing path to translator's file.
1725   If it is empty, the list of parameters from resource section ( resSection() )
1726   is used.
1727
1728   \param l - name of language. If it is empty, then value of parameter "language"
1729   from language section ( langSection() ) is used. If it is also empty, then
1730   predefined name "en" is used
1731
1732   \sa resSection(), langSection()
1733 */
1734 void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
1735 {
1736   initialize();
1737
1738   QMap<QChar, QString> substMap;
1739   substMap.insert( 'A', appName() );
1740
1741   QString lang = l;
1742   if ( lang.isEmpty() )
1743     value( langSection(), "language", lang );
1744
1745   if ( lang.isEmpty() )
1746   {
1747     lang = QString( "en" );
1748     qWarning( QString( "Language not specified. Assumed: %1" ).arg( lang ) );
1749   }
1750
1751   substMap.insert( 'L', lang );
1752
1753   QString trs;
1754   if ( value( langSection(), "translators", trs, false ) && !trs.isEmpty() )
1755   {
1756     QStringList translators    = QStringList::split( "|", option( "translators" ) );
1757     QStringList newTranslators = QStringList::split( "|", trs );
1758     for ( uint i = 0; i < newTranslators.count(); i++ )
1759       if ( translators.find( newTranslators[i] ) == translators.end() )
1760         translators += newTranslators[i];
1761     setOption( "translators", translators.join( "|" ) );
1762   }
1763
1764   QStringList trList = QStringList::split( "|", option( "translators" ) );
1765   if ( trList.isEmpty() )
1766   {
1767     trList.append( "%P_msg_%L.qm" );
1768     qWarning( QString( "Translators not defined. Assumed: %1" ).arg( trList.first() ) );
1769   }
1770
1771   QStringList prefixList;
1772   if ( !pref.isEmpty() )
1773     prefixList.append( pref );
1774   else
1775     prefixList = parameters( resSection() );
1776
1777   for ( QStringList::const_iterator iter = prefixList.begin(); iter != prefixList.end(); ++iter )
1778   {
1779     QString prefix = *iter;
1780     substMap.insert( 'P', prefix );
1781
1782     QStringList trs;
1783     for ( QStringList::const_iterator it = trList.begin(); it != trList.end(); ++it )
1784       trs.append( substMacro( *it, substMap ).stripWhiteSpace() );
1785
1786     loadTranslators( prefix, trs );
1787   }
1788 }
1789
1790 /*!
1791   Loads translators by path and list of files
1792
1793   \param prefix - value of this parameter must contain path
1794   \param translators - list of translators' files 
1795 */
1796 void QtxResourceMgr::loadTranslators( const QString& prefix, const QStringList& translators )
1797 {
1798   initialize();
1799
1800   QTranslator* trans = 0;
1801   ResListIterator it( myResources );
1802   it.toLast();
1803   for ( ; it.current(); --it )
1804   {
1805     for ( QStringList::const_iterator itr = translators.begin(); itr != translators.end(); ++itr )
1806     {
1807       trans = it.current()->loadTranslator( resSection(), prefix, *itr );
1808       if ( trans )
1809       {
1810         if ( !myTranslator[prefix].contains( trans ) )
1811           myTranslator[prefix].append( trans );
1812         qApp->installTranslator( trans );
1813       }
1814     }
1815   }
1816 }
1817
1818 /*!
1819   Loads translator by path and file name
1820
1821   \param prefix - value of this parameter must contain path
1822   \param name - name of translator file
1823 */
1824 void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name )
1825 {
1826   initialize();
1827
1828   QTranslator* trans = 0;
1829   ResListIterator it( myResources );
1830   it.toLast();
1831   for ( ; it.current(); --it )
1832   {
1833     trans = it.current()->loadTranslator( resSection(), prefix, name );
1834     if ( trans )
1835     {
1836       if ( !myTranslator[prefix].contains( trans ) )
1837         myTranslator[prefix].append( trans );
1838       qApp->installTranslator( trans );
1839     }
1840   }
1841 }
1842
1843 /*!
1844   Remove all translators corresponding to prefix
1845
1846   \param prefix - parameter containing path
1847 */
1848 void QtxResourceMgr::removeTranslators( const QString& prefix )
1849 {
1850   if ( !myTranslator.contains( prefix ) )
1851     return;
1852
1853   for ( TransListIterator it( myTranslator[prefix] ); it.current(); ++it )
1854   {
1855     qApp->removeTranslator( it.current() );
1856     delete it.current();
1857   }
1858
1859   myTranslator.remove( prefix );
1860 }
1861
1862 /*!
1863   Moves translators corresponding to prefix to the top of translator stack 
1864
1865   \param prefix - parameter containing path
1866 */
1867 void QtxResourceMgr::raiseTranslators( const QString& prefix )
1868 {
1869   if ( !myTranslator.contains( prefix ) )
1870     return;
1871
1872   for ( TransListIterator it( myTranslator[prefix] ); it.current(); ++it )
1873   {
1874     qApp->removeTranslator( it.current() );
1875     qApp->installTranslator( it.current() );
1876   }
1877 }
1878
1879 /*!
1880   Copies all resources to user resources, so that they will be saved in user home folder
1881 */
1882 void QtxResourceMgr::refresh()
1883 {
1884   QStringList sl = sections();
1885   for ( QStringList::const_iterator it = sl.begin(); it != sl.end(); ++it )
1886   {
1887     QStringList pl = parameters( *it );
1888     for ( QStringList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
1889       setResource( *it, *itr, stringValue( *it, *itr ) );
1890   }
1891 }
1892
1893 /*!
1894   \brief Sets the resource directories list except user home directory and clear resources
1895 */
1896 void QtxResourceMgr::setDirList( const QStringList& dl )
1897 {
1898   myDirList = dl;
1899   for ( ResListIterator it( myResources ); it.current(); ++it )
1900     delete it.current();
1901
1902   myResources.clear();
1903 }
1904
1905 /*!
1906   Sets resource value
1907   \param sect - name of section
1908   \param name - name of parameter
1909   \param val - string representation of value
1910 */
1911 void QtxResourceMgr::setResource( const QString& sect, const QString& name, const QString& val )
1912 {
1913   initialize();
1914
1915   if ( !myResources.isEmpty() )
1916     myResources.first()->setValue( sect, name, val );
1917 }
1918
1919 /*!
1920   \return name of resource file, which is being found in user home directory
1921   \param appName - name of application
1922   \param for_load - flag indicating that file will be used for loading (true) or for saving(false)
1923   It makes possible to use different resource files for loading and saving
1924 */
1925 QString QtxResourceMgr::userFileName( const QString& appName, const bool /*for_load*/ ) const
1926 {
1927   QString fileName;
1928   QString pathName = QDir::homeDirPath();
1929
1930 #ifdef WIN32
1931   fileName = QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
1932 #else
1933   fileName = QString( ".%1rc" ).arg( appName );
1934 #endif
1935
1936   if ( !fileName.isEmpty() )
1937     pathName = Qtx::addSlash( pathName ) + fileName;
1938
1939   return pathName;
1940 }
1941
1942 /*!
1943   \return name of resource file, which is being found in all resource directories, except user home
1944 */
1945 QString QtxResourceMgr::globalFileName( const QString& appName ) const
1946 {
1947   return QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
1948 }
1949
1950 /*!
1951   Replaced substrings by pattern %A, %B, etc by values from map
1952
1953   \param src - string to be processed
1954   \param substMap - map of values for replacing
1955 */
1956 QString QtxResourceMgr::substMacro( const QString& src, const QMap<QChar, QString>& substMap ) const
1957 {
1958   QString trg = src;
1959
1960   QRegExp rx( "%[A-Za-z%]" );
1961
1962   int idx = 0;
1963   while ( ( idx = rx.search( trg, idx ) ) >= 0 )
1964   {
1965     QChar spec = trg.at( idx + 1 );
1966     QString subst;
1967     if ( spec == '%' )
1968       subst = "%";
1969     else if ( substMap.contains( spec ) )
1970       subst = substMap[spec];
1971
1972     if ( !subst.isEmpty() )
1973     {
1974       trg.replace( idx, rx.matchedLength(), subst );
1975       idx += subst.length();
1976     }
1977     else
1978       idx += rx.matchedLength();
1979   }
1980
1981   return trg;
1982 }