Back to index

salome-gui  6.5.0
QtxResourceMgr.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File:      QtxResourceMgr.cxx
00024 // Author:    Alexander SOLOVYOV, Sergey TELKOV
00025 //
00026 #include "QtxResourceMgr.h"
00027 #include "QtxTranslator.h"
00028 
00029 #include <QSet>
00030 #include <QDir>
00031 #include <QFile>
00032 #include <QFileInfo>
00033 #include <QRegExp>
00034 #include <QTextStream>
00035 #include <QApplication>
00036 #include <QLibraryInfo>
00037 #include <QtDebug>
00038 #ifndef QT_NO_DOM
00039 #include <QDomDocument>
00040 #include <QDomElement>
00041 #include <QDomNode>
00042 #endif
00043 
00044 #include <stdlib.h>
00045 
00052 class QtxResourceMgr::Resources
00053 {
00054 public:
00055   Resources( QtxResourceMgr*, const QString& );
00056   virtual ~Resources();
00057 
00058   QString                file() const;
00059   void                   setFile( const QString& );
00060 
00061   QString                value( const QString&, const QString&, const bool ) const;
00062   void                   setValue( const QString&, const QString&, const QString& );
00063 
00064   bool                   hasSection( const QString& ) const;
00065   bool                   hasValue( const QString&, const QString& ) const;
00066 
00067   void                   removeSection( const QString& );
00068   void                   removeValue( const QString&, const QString& );
00069 
00070   QPixmap                loadPixmap( const QString&, const QString&, const QString& ) const;
00071   QTranslator*           loadTranslator( const QString&, const QString&, const QString& ) const;
00072 
00073   QString                makeSubstitution( const QString&, const QString&, const QString& ) const;
00074 
00075   void                   clear();
00076 
00077   QStringList            sections() const;
00078   QStringList            parameters( const QString& ) const;
00079 
00080   QString                path( const QString&, const QString&, const QString& ) const;
00081 
00082 protected:
00083   QtxResourceMgr*        resMgr() const;
00084 
00085 private:
00086   Section                section( const QString& );
00087   const Section          section( const QString& ) const;
00088 
00089   QString                fileName( const QString&, const QString&, const QString& ) const;
00090 
00091 private:
00092   typedef QMap<QString, Section> SectionMap;
00093 
00094 private:
00095   QtxResourceMgr*        myMgr;             
00096   SectionMap             mySections;        
00097   QString                myFileName;        
00098   QMap<QString,QPixmap>  myPixmapCache;     
00099 
00100   friend class QtxResourceMgr::Format;
00101 };
00102 
00108 QtxResourceMgr::Resources::Resources( QtxResourceMgr* mgr, const QString& fileName )
00109 : myMgr( mgr ),
00110   myFileName( fileName )
00111 {
00112 }
00113 
00117 QtxResourceMgr::Resources::~Resources()
00118 {
00119 }
00120 
00129 QString QtxResourceMgr::Resources::file() const
00130 {
00131   return myFileName;
00132 }
00133 
00139 void QtxResourceMgr::Resources::setFile( const QString& fn )
00140 {
00141   myFileName = fn;
00142 }
00143 
00152 QString QtxResourceMgr::Resources::value( const QString& sect, const QString& name, const bool subst ) const
00153 {
00154   QString val;
00155 
00156   if ( hasValue( sect, name ) )
00157   {
00158     val = section( sect )[name];
00159     if ( subst )
00160       val = makeSubstitution( val, sect, name );
00161   }
00162   return val;
00163 }
00164 
00172 void QtxResourceMgr::Resources::setValue( const QString& sect, const QString& name, const QString& val )
00173 {
00174   if ( !mySections.contains( sect ) )
00175     mySections.insert( sect, Section() );
00176 
00177   mySections[sect].insert( name, val );
00178 }
00179 
00185 bool QtxResourceMgr::Resources::hasSection( const QString& sect ) const
00186 {
00187   return mySections.contains( sect );
00188 }
00189 
00196 bool QtxResourceMgr::Resources::hasValue( const QString& sect, const QString& name ) const
00197 {
00198   return hasSection( sect ) && section( sect ).contains( name );
00199 }
00200 
00205 void QtxResourceMgr::Resources::removeSection( const QString& sect )
00206 {
00207   mySections.remove( sect );
00208 }
00209 
00215 void QtxResourceMgr::Resources::removeValue( const QString& sect, const QString& name )
00216 {
00217   if ( !mySections.contains( sect ) )
00218     return;
00219 
00220   mySections[sect].remove( name );
00221 
00222   if ( mySections[sect].isEmpty() )
00223     mySections.remove( sect );
00224 }
00225 
00229 void QtxResourceMgr::Resources::clear()
00230 {
00231   mySections.clear();
00232 }
00233 
00238 QStringList QtxResourceMgr::Resources::sections() const
00239 {
00240   return mySections.keys();
00241 }
00242 
00248 QStringList QtxResourceMgr::Resources::parameters( const QString& sec ) const
00249 {
00250   if ( !hasSection( sec ) )
00251     return QStringList();
00252 
00253   return section( sec ).keys();
00254 }
00255 
00271 QString QtxResourceMgr::Resources::path( const QString& sec, const QString& prefix, const QString& name ) const
00272 {
00273   QString filePath = fileName( sec, prefix, name );
00274   if ( !filePath.isEmpty() )
00275   {
00276     if ( !QFileInfo( filePath ).exists() )
00277       filePath = QString();
00278   }
00279   return filePath;
00280 }
00281 
00286 QtxResourceMgr* QtxResourceMgr::Resources::resMgr() const
00287 {
00288   return myMgr;
00289 }
00290 
00299 QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn )
00300 {
00301   if ( !mySections.contains( sn ) )
00302     mySections.insert( sn, Section() );
00303 
00304   return mySections[sn];
00305 }
00306 
00312 const QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn ) const
00313 {
00314   return mySections[sn];
00315 }
00316 
00334 QString QtxResourceMgr::Resources::fileName( const QString& sect, const QString& prefix, const QString& name ) const
00335 {
00336   QString path;
00337   if ( hasValue( sect, prefix ) )
00338   {
00339     path = value( sect, prefix, true );
00340     if ( !path.isEmpty() )
00341     {
00342       if ( QFileInfo( path ).isRelative() )
00343         path = Qtx::addSlash( Qtx::dir( myFileName, true ) ) + path;
00344 
00345       path = Qtx::addSlash( path ) + name;
00346     }
00347   }
00348   if( !path.isEmpty() )
00349   {
00350     QString fname = QDir::convertSeparators( path );
00351     QFileInfo inf( fname );
00352     fname = inf.absoluteFilePath();
00353     return fname;
00354   }
00355   return QString();
00356 }
00357 
00370 QPixmap QtxResourceMgr::Resources::loadPixmap( const QString& sect, const QString& prefix, const QString& name ) const
00371 {
00372   QString fname = fileName( sect, prefix, name );
00373   bool toCache = resMgr() ? resMgr()->isPixmapCached() : false;
00374   QPixmap p;
00375   if( toCache && myPixmapCache.contains( fname ) )
00376     p = myPixmapCache[fname];
00377   else
00378   {
00379     p.load( fname );
00380     if( toCache )
00381       ( ( QMap<QString,QPixmap>& )myPixmapCache ).insert( fname, p );
00382   }
00383   return p;
00384 }
00385 
00393 QTranslator* QtxResourceMgr::Resources::loadTranslator( const QString& sect, const QString& prefix, const QString& name ) const
00394 {
00395   QTranslator* trans = new QtxTranslator( 0 );
00396   QString fname = QDir::convertSeparators( fileName( sect, prefix, name ) );
00397   if ( !trans->load( Qtx::file( fname, false ), Qtx::dir( fname ) ) )
00398   {
00399     delete trans;
00400     trans = 0;
00401   }
00402   return trans;
00403 }
00404 
00416 QString QtxResourceMgr::Resources::makeSubstitution( const QString& str, const QString& sect, const QString& name ) const
00417 {
00418   QString res = str;
00419 
00420   QMap<QString, int> ignoreMap;
00421   ignoreMap.insert( name, 0 );
00422 
00423   int start( 0 ), len( 0 );
00424   while ( true )
00425   {
00426     QString envName = Qtx::findEnvVar( res, start, len );
00427     if ( envName.isNull() )
00428       break;
00429 
00430     QString newStr;
00431     if ( ::getenv( envName.toLatin1() ) )
00432       newStr = QString( ::getenv( envName.toLatin1() ) );
00433 
00434     if ( newStr.isNull() )
00435     {
00436       if ( ignoreMap.contains( envName ) )
00437       {
00438         start += len;
00439         continue;
00440       }
00441 
00442       if ( hasValue( sect, envName ) )
00443         newStr = value( sect, envName, false );
00444       ignoreMap.insert( envName, 0 );
00445     }
00446     res.replace( start, len, newStr );
00447   }
00448 
00449   res.replace( "$$", "$" );
00450   res.replace( "%%", "%" );
00451 
00452   return res;
00453 }
00454 
00461 class QtxResourceMgr::IniFormat : public Format
00462 {
00463 public:
00464   IniFormat();
00465   ~IniFormat();
00466 
00467 protected:
00468   virtual bool load( const QString&, QMap<QString, Section>& );
00469   virtual bool save( const QString&, const QMap<QString, Section>& );
00470 
00471 private:
00472   bool         load( const QString&, QMap<QString, Section>&, QSet<QString>& );
00473 };
00474 
00478 QtxResourceMgr::IniFormat::IniFormat()
00479 : Format( "ini" )
00480 {
00481 }
00482 
00486 QtxResourceMgr::IniFormat::~IniFormat()
00487 {
00488 }
00489 
00496 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap )
00497 {
00498   QSet<QString> importHistory;
00499   return load( fname, secMap, importHistory );
00500 }
00501 
00502 
00510 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap, QSet<QString>& importHistory )
00511 {
00512   QString aFName = fname.trimmed();
00513   if ( !QFileInfo( aFName ).exists() )
00514   {
00515     if ( QFileInfo( aFName + ".ini" ).exists() )
00516       aFName += ".ini";
00517     else if ( QFileInfo( aFName + ".INI" ).exists() )
00518       aFName += ".INI";
00519     else
00520       return false; // file does not exist
00521   }
00522   QFileInfo aFinfo( aFName );
00523   aFName = aFinfo.canonicalFilePath();
00524 
00525   if ( !importHistory.contains( aFName ) )
00526     importHistory.insert( aFName );
00527   else
00528     return true;   // already imported (prevent import loops)
00529 
00530   QFile file( aFName );
00531   if ( !file.open( QFile::ReadOnly ) )
00532     return false;  // file is not accessible
00533 
00534   QTextStream ts( &file );
00535 
00536   QString data;
00537   int line = 0;
00538   bool res = true;
00539   QString section;
00540 
00541   QString separator = option( "separator" );
00542   if ( separator.isNull() )
00543     separator = QString( "=" );
00544 
00545   QString comment = option( "comment" );
00546   if ( comment.isNull() )
00547     comment = QString( "#" );
00548 
00549   while ( true )
00550   {
00551     data = ts.readLine();
00552     line++;
00553 
00554     if ( data.isNull() )
00555       break;
00556 
00557     data = data.trimmed();
00558     if ( data.isEmpty() )
00559       continue;
00560 
00561     if ( data.startsWith( comment ) )
00562       continue;
00563 
00564     QRegExp rx( "^\\[([\\w\\s\\._]*)\\]$" );
00565     if ( rx.indexIn( data ) != -1 )
00566     {
00567       section = rx.cap( 1 );
00568       if ( section.isEmpty() )
00569       {
00570         res = false;
00571         qWarning() << "QtxResourceMgr: Empty section in line:" << line;
00572       }
00573     }
00574     else if ( data.contains( separator ) && !section.isEmpty() )
00575     {
00576       int pos = data.indexOf( separator );
00577       QString key = data.left( pos ).trimmed();
00578       QString val = data.mid( pos + 1 ).trimmed();
00579       secMap[section].insert( key, val );
00580     }
00581     else if ( section == "import" )
00582     {
00583       QString impFile = QDir::convertSeparators( Qtx::makeEnvVarSubst( data, Qtx::Always ) );
00584       QFileInfo impFInfo( impFile );
00585       if ( impFInfo.isRelative() )
00586              impFInfo.setFile( aFinfo.absoluteDir(), impFile );
00587     
00588       QMap<QString, Section> impMap;
00589       if ( !load( impFInfo.absoluteFilePath(), impMap, importHistory ) )
00590       {
00591         qDebug() << "QtxResourceMgr: Error with importing file:" << data;
00592       }
00593       else 
00594       {
00595              QMap<QString, Section>::const_iterator it = impMap.constBegin();
00596              for ( ; it != impMap.constEnd() ; ++it )
00597              { 
00598                 if ( !secMap.contains( it.key() ) )
00599                 {
00600                    // insert full section
00601                    secMap.insert( it.key(), it.value() );
00602                 }
00603                 else
00604                 {
00605                    // insert all parameters from the section
00606                    Section::ConstIterator paramIt = it.value().begin();
00607                    for ( ; paramIt != it.value().end() ; ++paramIt )
00608                    {
00609                       if ( !secMap[it.key()].contains( paramIt.key() ) )
00610                              secMap[it.key()].insert( paramIt.key(), paramIt.value() );
00611                    }
00612                 }
00613              }
00614       }
00615     }
00616     else
00617     {
00618       res = false;
00619       if ( section.isEmpty() )
00620              qWarning() << "QtxResourceMgr: Current section is empty";
00621       else
00622              qWarning() << "QtxResourceMgr: Error in line:" << line;
00623     }
00624   }
00625 
00626   file.close();
00627 
00628   return res; 
00629 }
00630 
00637 bool QtxResourceMgr::IniFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
00638 {
00639   if ( !Qtx::mkDir( QFileInfo( fname ).absolutePath() ) )
00640     return false;
00641 
00642   QFile file( fname );
00643   if ( !file.open( QFile::WriteOnly ) )
00644     return false;
00645 
00646   QTextStream ts( &file );
00647 
00648   bool res = true;
00649   for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end() && res; ++it )
00650   {
00651     QStringList data( QString( "[%1]" ).arg( it.key() ) );
00652     for ( Section::ConstIterator iter = it.value().begin(); iter != it.value().end(); ++iter )
00653       data.append( iter.key() + " = " + iter.value() );
00654     data.append( "" );
00655 
00656     for ( QStringList::ConstIterator itr = data.begin(); itr != data.end(); ++itr )
00657       ts << *itr << endl;
00658   }
00659 
00660   file.close();
00661 
00662   return res;
00663 }
00664 
00671 class QtxResourceMgr::XmlFormat : public Format
00672 {
00673 public:
00674   XmlFormat();
00675   ~XmlFormat();
00676 
00677 protected:
00678   virtual bool load( const QString&, QMap<QString, Section>& );
00679   virtual bool save( const QString&, const QMap<QString, Section>& );
00680 
00681 private:
00682   QString      docTag() const;
00683   QString      sectionTag() const;
00684   QString      parameterTag() const;
00685   QString      importTag() const;
00686   QString      nameAttribute() const;
00687   QString      valueAttribute() const;
00688 
00689   bool         load( const QString&, QMap<QString, Section>&, QSet<QString>& );
00690 };
00691 
00695 QtxResourceMgr::XmlFormat::XmlFormat()
00696 : Format( "xml" )
00697 {
00698 }
00699 
00703 QtxResourceMgr::XmlFormat::~XmlFormat()
00704 {
00705 }
00706 
00713 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap )
00714 {
00715   QSet<QString> importHistory;
00716   return load( fname, secMap, importHistory );
00717 }
00718 
00726 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap, QSet<QString>& importHistory )
00727 {
00728   QString aFName = fname.trimmed();
00729   if ( !QFileInfo( aFName ).exists() )
00730   {
00731     if ( QFileInfo( aFName + ".xml" ).exists() )
00732       aFName += ".xml";
00733     else if ( QFileInfo( aFName + ".XML" ).exists() )
00734       aFName += ".XML";
00735     else
00736       return false; // file does not exist
00737   }
00738   QFileInfo aFinfo( aFName );
00739   aFName = aFinfo.canonicalFilePath();
00740 
00741   if ( !importHistory.contains(  aFName ) )
00742     importHistory.insert( aFName );
00743   else
00744     return true;   // already imported (prevent import loops)
00745 
00746   bool res = false;
00747 
00748 #ifndef QT_NO_DOM
00749 
00750   QFile file( aFName );
00751   if ( !file.open( QFile::ReadOnly ) )
00752   {
00753     qDebug() << "QtxResourceMgr: File is not accessible:" << aFName;
00754     return false;
00755   }
00756 
00757   QDomDocument doc;
00758 
00759   res = doc.setContent( &file );
00760   file.close();
00761 
00762   if ( !res )
00763   {
00764     qDebug() << "QtxResourceMgr: File is empty:" << aFName;
00765     return false;
00766   }
00767 
00768   QDomElement root = doc.documentElement();
00769   if ( root.isNull() || root.tagName() != docTag() )
00770   {
00771     qDebug() << "QtxResourceMgr: Invalid root in file:" << aFName;
00772     return false;
00773   }
00774 
00775   QDomNode sectNode = root.firstChild();
00776   while ( res && !sectNode.isNull() )
00777   {
00778     res = sectNode.isElement();
00779     if ( res )
00780     {
00781       QDomElement sectElem = sectNode.toElement();
00782       if ( sectElem.tagName() == sectionTag() && sectElem.hasAttribute( nameAttribute() ) )
00783       {
00784         QString section = sectElem.attribute( nameAttribute() );
00785         QDomNode paramNode = sectNode.firstChild();
00786         while ( res && !paramNode.isNull() )
00787         {
00788           res = paramNode.isElement();
00789           if ( res )
00790           {
00791             QDomElement paramElem = paramNode.toElement();
00792             if ( paramElem.tagName() == parameterTag() &&
00793                  paramElem.hasAttribute( nameAttribute() ) && paramElem.hasAttribute( valueAttribute() ) )
00794             {
00795               QString paramName = paramElem.attribute( nameAttribute() );
00796               QString paramValue = paramElem.attribute( valueAttribute() );
00797               secMap[section].insert( paramName, paramValue );
00798             }
00799             else
00800             {
00801               qDebug() << "QtxResourceMgr: Invalid parameter element in file:" << aFName;
00802               res = false;
00803             }
00804           }
00805           else
00806           {
00807             res = paramNode.isComment();
00808             if ( !res )
00809               qDebug() << "QtxResourceMgr: Node is neither element nor comment in file:" << aFName;
00810           }
00811 
00812           paramNode = paramNode.nextSibling();
00813         }
00814       }
00815       else if ( sectElem.tagName() == importTag() && sectElem.hasAttribute( nameAttribute() ) )
00816       {
00817          QString impFile = QDir::convertSeparators( Qtx::makeEnvVarSubst( sectElem.attribute( nameAttribute() ), Qtx::Always ) );
00818              QFileInfo impFInfo( impFile );
00819              if ( impFInfo.isRelative() )
00820                 impFInfo.setFile( aFinfo.absoluteDir(), impFile );
00821 
00822         QMap<QString, Section> impMap;
00823         if ( !load( impFInfo.absoluteFilePath(), impMap, importHistory ) )
00824             {
00825             qDebug() << "QtxResourceMgr: Error with importing file:" << sectElem.attribute( nameAttribute() );
00826             }
00827             else
00828             {
00829                 QMap<QString, Section>::const_iterator it = impMap.constBegin();
00830                 for ( ; it != impMap.constEnd() ; ++it )
00831                 {
00832                    if ( !secMap.contains( it.key() ) )
00833                    {
00834                       // insert full section
00835                       secMap.insert( it.key(), it.value() );
00836                    }
00837                    else
00838                    {
00839                       // insert all parameters from the section
00840                       Section::ConstIterator paramIt = it.value().begin();
00841                       for ( ; paramIt != it.value().end() ; ++paramIt )
00842                       {
00843                              if ( !secMap[it.key()].contains( paramIt.key() ) )
00844                                 secMap[it.key()].insert( paramIt.key(), paramIt.value() );
00845                       }
00846                    }
00847                 }
00848          }
00849       }
00850       else
00851       {
00852          qDebug() << "QtxResourceMgr: Invalid section in file:" << aFName;
00853          res = false;
00854       }
00855     }
00856     else
00857     {
00858       res = sectNode.isComment(); // if it's a comment -- let it be, pass it..
00859       if ( !res )
00860         qDebug() << "QtxResourceMgr: Node is neither element nor comment in file:" << aFName;
00861     }
00862 
00863     sectNode = sectNode.nextSibling();
00864   }
00865 
00866 #endif
00867   
00868   if ( res )
00869     qDebug() << "QtxResourceMgr: File" << fname << "is loaded successfully";
00870   return res;
00871 }
00872 
00879 bool QtxResourceMgr::XmlFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
00880 {
00881   bool res = false;
00882 
00883 #ifndef QT_NO_DOM
00884 
00885   if ( !Qtx::mkDir( QFileInfo( fname ).absolutePath() ) )
00886     return false;
00887 
00888   QFile file( fname );
00889   if ( !file.open( QFile::WriteOnly ) )
00890     return false;
00891 
00892   QDomDocument doc( docTag() );
00893   QDomElement root = doc.createElement( docTag() );
00894   doc.appendChild( root );
00895 
00896   for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end(); ++it )
00897   {
00898     QDomElement sect = doc.createElement( sectionTag() );
00899     sect.setAttribute( nameAttribute(), it.key() );
00900     root.appendChild( sect );
00901     for ( Section::ConstIterator iter = it.value().begin(); iter != it.value().end(); ++iter )
00902     {
00903       QDomElement val = doc.createElement( parameterTag() );
00904       val.setAttribute( nameAttribute(), iter.key() );
00905       val.setAttribute( valueAttribute(), iter.value() );
00906       sect.appendChild( val );
00907     }
00908   }
00909 
00910   QTextStream ts( &file );
00911   QStringList docStr = doc.toString().split( "\n" );
00912   for ( QStringList::ConstIterator itr = docStr.begin(); itr != docStr.end(); ++itr )
00913     ts << *itr << endl;
00914 
00915   file.close();
00916 
00917 #endif
00918 
00919   return res;
00920 }
00921 
00926 QString QtxResourceMgr::XmlFormat::docTag() const
00927 {
00928   QString tag = option( "doc_tag" );
00929   if ( tag.isEmpty() )
00930     tag = QString( "document" );
00931   return tag;
00932 }
00933 
00938 QString QtxResourceMgr::XmlFormat::sectionTag() const
00939 {
00940   QString tag = option( "section_tag" );
00941   if ( tag.isEmpty() )
00942     tag = QString( "section" );
00943   return tag;
00944 }
00945 
00950 QString QtxResourceMgr::XmlFormat::parameterTag() const
00951 {
00952   QString tag = option( "parameter_tag" );
00953   if ( tag.isEmpty() )
00954     tag = QString( "parameter" );
00955   return tag;
00956 }
00957 
00962 QString QtxResourceMgr::XmlFormat::importTag() const
00963 {
00964   QString tag = option( "import_tag" );
00965   if ( tag.isEmpty() )
00966    tag = QString( "import" );
00967   return tag;
00968 }
00969 
00974 QString QtxResourceMgr::XmlFormat::nameAttribute() const
00975 {
00976   QString str = option( "name_attribute" );
00977   if ( str.isEmpty() )
00978     str = QString( "name" );
00979   return str;
00980 }
00981 
00986 QString QtxResourceMgr::XmlFormat::valueAttribute() const
00987 {
00988   QString str = option( "value_attribute" );
00989   if ( str.isEmpty() )
00990     str = QString( "value" );
00991   return str;
00992 }
00993 
01003 QtxResourceMgr::Format::Format( const QString& fmt )
01004 : myFmt( fmt )
01005 {
01006 }
01007 
01011 QtxResourceMgr::Format::~Format()
01012 {
01013 }
01014 
01019 QString QtxResourceMgr::Format::format() const
01020 {
01021   return myFmt;
01022 }
01023 
01028 QStringList QtxResourceMgr::Format::options() const
01029 {
01030   return myOpt.keys();
01031 }
01032 
01041 QString QtxResourceMgr::Format::option( const QString& opt ) const
01042 {
01043   QString val;
01044   if ( myOpt.contains( opt ) )
01045     val = myOpt[opt];
01046   return val;
01047 }
01048 
01054 void QtxResourceMgr::Format::setOption( const QString& opt, const QString& val )
01055 {
01056   myOpt.insert( opt, val );
01057 }
01058 
01064 bool QtxResourceMgr::Format::load( Resources* res )
01065 {
01066   if ( !res )
01067     return false;
01068 
01069   QMap<QString, Section> sections;
01070   bool status = load( res->myFileName, sections );
01071   if ( status )
01072     res->mySections = sections;
01073   else
01074     qDebug() << "QtxResourceMgr: Can't load resource file:" << res->myFileName;
01075 
01076   return status;
01077 }
01078 
01084 bool QtxResourceMgr::Format::save( Resources* res )
01085 {
01086   if ( !res )
01087     return false;
01088 
01089   Qtx::mkDir( Qtx::dir( res->myFileName ) );
01090 
01091   QtxResourceMgr* mgr = res->resMgr();
01092   QString name = mgr ? mgr->userFileName( mgr->appName(), false ) : res->myFileName;
01093   return save( name, res->mySections );
01094 }
01095 
01201 QtxResourceMgr::QtxResourceMgr( const QString& appName, const QString& resVarTemplate )
01202 : myAppName( appName ),
01203   myCheckExist( true ),
01204   myDefaultPix( 0 ),
01205   myIsPixmapCached( true ),
01206   myHasUserValues( true ),
01207   myWorkingMode( AllowUserValues )
01208 {
01209   QString envVar = !resVarTemplate.isEmpty() ? resVarTemplate : QString( "%1Resources" );
01210   if ( envVar.contains( "%1" ) )
01211     envVar = envVar.arg( appName );
01212 
01213   QString dirs;
01214   if ( ::getenv( envVar.toLatin1() ) )
01215     dirs = ::getenv( envVar.toLatin1() );
01216 #ifdef WIN32
01217   QString dirsep = ";";      // for Windows: ";" is used as directories separator
01218 #else
01219   QString dirsep = "[:|;]";  // for Linux: both ":" and ";" can be used
01220 #endif
01221   setDirList( dirs.split( QRegExp( dirsep ), QString::SkipEmptyParts ) );
01222 
01223   installFormat( new XmlFormat() );
01224   installFormat( new IniFormat() );
01225 
01226   setOption( "translators", QString( "%P_msg_%L.qm|%P_images.qm" ) );
01227 }
01228 
01234 QtxResourceMgr::~QtxResourceMgr()
01235 {
01236   QStringList prefList = myTranslator.keys();
01237   for ( QStringList::ConstIterator it = prefList.begin(); it != prefList.end(); ++it )
01238     removeTranslators( *it );
01239 
01240   qDeleteAll( myResources );
01241   qDeleteAll( myFormats );
01242 
01243   delete myDefaultPix;
01244 }
01245 
01250 QString QtxResourceMgr::appName() const
01251 {
01252   return myAppName;
01253 }
01254 
01263 bool QtxResourceMgr::checkExisting() const
01264 {
01265   return myCheckExist;
01266 }
01267 
01272 void QtxResourceMgr::setCheckExisting( const bool on )
01273 {
01274   myCheckExist = on;
01275 }
01276 
01286 QStringList QtxResourceMgr::dirList() const
01287 {
01288   return myDirList;
01289 }
01290 
01298 void QtxResourceMgr::initialize( const bool autoLoad ) const
01299 {
01300   if ( !myResources.isEmpty() )
01301     return;
01302 
01303   QtxResourceMgr* that = (QtxResourceMgr*)this;
01304 
01305   if ( !userFileName( appName() ).isEmpty() )
01306     that->myResources.append( new Resources( that, userFileName( appName() ) ) );
01307 
01308   that->myHasUserValues = myResources.count() > 0;
01309 
01310   for ( QStringList::ConstIterator it = myDirList.begin(); it != myDirList.end(); ++it )
01311   {
01312     QString path = Qtx::addSlash( *it ) + globalFileName( appName() );
01313     that->myResources.append( new Resources( that, path ) );
01314   }
01315 
01316   if ( autoLoad )
01317     that->load();
01318 }
01319 
01331 bool QtxResourceMgr::isPixmapCached() const
01332 {
01333   return myIsPixmapCached;
01334 }
01335 
01341 void QtxResourceMgr::setIsPixmapCached( const bool on )
01342 {
01343   myIsPixmapCached = on;
01344 }
01345 
01349 void QtxResourceMgr::clear()
01350 {
01351   for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
01352     (*it)->clear();
01353 }
01354 
01361 QtxResourceMgr::WorkingMode QtxResourceMgr::workingMode() const
01362 {
01363   return myWorkingMode;
01364 }
01365 
01378 void QtxResourceMgr::setWorkingMode( WorkingMode mode )
01379 {
01380   myWorkingMode = mode;
01381 }
01382 
01391 bool QtxResourceMgr::value( const QString& sect, const QString& name, int& iVal ) const
01392 {
01393   QString val;
01394   if ( !value( sect, name, val, true ) )
01395     return false;
01396 
01397   bool ok;
01398   iVal = val.toInt( &ok );
01399 
01400   return ok;
01401 }
01402 
01411 bool QtxResourceMgr::value( const QString& sect, const QString& name, double& dVal ) const
01412 {
01413   QString val;
01414   if ( !value( sect, name, val, true ) )
01415     return false;
01416 
01417   bool ok;
01418   dVal = val.toDouble( &ok );
01419 
01420   return ok;
01421 }
01422 
01431 bool QtxResourceMgr::value( const QString& sect, const QString& name, bool& bVal ) const
01432 {
01433   QString val;
01434   if ( !value( sect, name, val, true ) )
01435     return false;
01436 
01437   static QMap<QString, bool> boolMap;
01438   if ( boolMap.isEmpty() )
01439   {
01440     boolMap["true"]  = boolMap["yes"] = boolMap["on"]  = true;
01441     boolMap["false"] = boolMap["no"]  = boolMap["off"] = false;
01442   }
01443 
01444   val = val.toLower();
01445   bool res = boolMap.contains( val );
01446   if ( res )
01447     bVal = boolMap[val];
01448   else
01449   {
01450     double num = val.toDouble( &res );
01451     if ( res )
01452       bVal = num != 0;
01453   }
01454 
01455   return res;
01456 }
01457 
01466 bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cVal ) const
01467 {
01468   QString val;
01469   if ( !value( sect, name, val, true ) )
01470     return false;
01471 
01472   return Qtx::stringToColor( val, cVal );
01473 }
01474 
01483 bool QtxResourceMgr::value( const QString& sect, const QString& name, QFont& fVal ) const
01484 {
01485   QString val;
01486   if ( !value( sect, name, val, true ) )
01487     return false;
01488 
01489   QStringList fontDescr = val.split( ",", QString::SkipEmptyParts );
01490 
01491   if ( fontDescr.count() < 2 )
01492     return false;
01493 
01494   QString family = fontDescr[0];
01495   if ( family.isEmpty() )
01496     return false;
01497 
01498   fVal = QFont( family );
01499 
01500   for ( int i = 1; i < (int)fontDescr.count(); i++ )
01501   {
01502     QString curval = fontDescr[i].trimmed().toLower();
01503     if ( curval == QString( "bold" ) )
01504       fVal.setBold( true );
01505     else if ( curval == QString( "italic" ) )
01506       fVal.setItalic( true );
01507     else if ( curval == QString( "underline" ) )
01508       fVal.setUnderline( true );
01509     else if ( curval == QString( "shadow" ) || curval == QString( "overline" ) )
01510       fVal.setOverline( true );
01511     else
01512     {
01513       bool isOk = false;
01514       int ps = curval.toInt( &isOk );
01515       if ( isOk )
01516         fVal.setPointSize( ps );
01517     }
01518   }
01519 
01520   return true;
01521 }
01522 
01531 bool QtxResourceMgr::value( const QString& sect, const QString& name, QByteArray& baVal ) const
01532 {
01533   QString val;
01534   if ( !value( sect, name, val, true ) )
01535     return false;
01536 
01537   baVal.clear();
01538   QStringList lst = val.split( QRegExp( "[\\s|,]" ), QString::SkipEmptyParts );
01539   for ( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it )
01540   {
01541     int base = 10;
01542     QString str = *it;
01543     if ( str.startsWith( "#" ) )
01544     {
01545       base = 16;
01546       str = str.mid( 1 );
01547     }
01548     bool ok = false;
01549     int num = str.toInt( &ok, base );
01550     if ( !ok || num < 0 || num > 255 )
01551       continue;
01552 
01553     baVal.append( (char)num );
01554   }
01555   return !baVal.isEmpty();
01556 }
01557 
01566 bool QtxResourceMgr::value( const QString& sect, const QString& name, QLinearGradient& gVal ) const
01567 {
01568   QString val;
01569   if ( !value( sect, name, val, true ) )
01570     return false;
01571 
01572   return Qtx::stringToLinearGradient( val, gVal );
01573 }
01574 
01583 bool QtxResourceMgr::value( const QString& sect, const QString& name, QRadialGradient& gVal ) const
01584 {
01585   QString val;
01586   if ( !value( sect, name, val, true ) )
01587     return false;
01588 
01589   return Qtx::stringToRadialGradient( val, gVal );
01590 }
01591 
01600 bool QtxResourceMgr::value( const QString& sect, const QString& name, QConicalGradient& gVal ) const
01601 {
01602   QString val;
01603   if ( !value( sect, name, val, true ) )
01604     return false;
01605 
01606   return Qtx::stringToConicalGradient( val, gVal );
01607 }
01608 
01617 bool QtxResourceMgr::value( const QString& sect, const QString& name, Qtx::BackgroundData& bgVal ) const
01618 {
01619   QString val;
01620   if ( !value( sect, name, val, true ) )
01621     return false;
01622 
01623   bgVal = Qtx::stringToBackground( val );
01624   return bgVal.isValid();
01625 }
01626 
01636 bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& val, const bool subst ) const
01637 {
01638   initialize();
01639 
01640   bool ok = false;
01641  
01642   ResList::ConstIterator it = myResources.begin();
01643   if ( myHasUserValues && workingMode() == IgnoreUserValues )
01644     ++it;
01645 
01646   for ( ; it != myResources.end() && !ok; ++it )
01647   {
01648     ok = (*it)->hasValue( sect, name );
01649     if ( ok )
01650       val = (*it)->value( sect, name, subst );
01651   }
01652 
01653   return ok;
01654 }
01655 
01667 int QtxResourceMgr::integerValue( const QString& sect, const QString& name, const int def ) const
01668 {
01669   int val;
01670   if ( !value( sect, name, val ) )
01671     val = def;
01672   return val;
01673 }
01674 
01686 double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, const double def ) const
01687 {
01688   double val;
01689   if ( !value( sect, name, val ) )
01690     val = def;
01691   return val;
01692 }
01693 
01705 bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, const bool def ) const
01706 {
01707   bool val;
01708   if ( !value( sect, name, val ) )
01709     val = def;
01710   return val;
01711 }
01712 
01724 QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const QFont& def ) const
01725 {
01726   QFont font;
01727   if( !value( sect, name, font ) )
01728     font = def;
01729   return font;
01730 }
01731 
01743 QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, const QColor& def ) const
01744 {
01745   QColor val;
01746   if ( !value( sect, name, val ) )
01747     val = def;
01748   return val;
01749 }
01750 
01761 QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, const QString& def ) const
01762 {
01763   QString val;
01764   if ( !value( sect, name, val ) )
01765     val = def;
01766   return val;
01767 }
01768 
01779 QByteArray QtxResourceMgr::byteArrayValue( const QString& sect, const QString& name, const QByteArray& def ) const
01780 {
01781   QByteArray val;
01782   if ( !value( sect, name, val ) )
01783     val = def;
01784   return val;
01785 }
01786 
01797 QLinearGradient QtxResourceMgr::linearGradientValue( const QString& sect, const QString& name, const QLinearGradient& def ) const
01798 {
01799   QLinearGradient val;
01800   if ( !value( sect, name, val ) )
01801     val = def;
01802   return val;
01803 }
01804 
01815 QRadialGradient QtxResourceMgr::radialGradientValue( const QString& sect, const QString& name, const QRadialGradient& def ) const
01816 {
01817   QRadialGradient val;
01818   if ( !value( sect, name, val ) )
01819     val = def;
01820   return val;
01821 }
01822 
01833 QConicalGradient QtxResourceMgr::conicalGradientValue( const QString& sect, const QString& name, const QConicalGradient& def ) const
01834 {
01835   QConicalGradient val;
01836   if ( !value( sect, name, val ) )
01837     val = def;
01838   return val;
01839 }
01840 
01851 Qtx::BackgroundData QtxResourceMgr::backgroundValue( const QString& sect, const QString& name, const Qtx::BackgroundData& def ) const
01852 {
01853   Qtx::BackgroundData val;
01854   if ( !value( sect, name, val ) )
01855     val = def;
01856   return val;
01857 }
01858 
01865 bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
01866 {
01867   initialize();
01868 
01869   bool ok = false;
01870 
01871   ResList::ConstIterator it = myResources.begin();
01872   if ( myHasUserValues && workingMode() == IgnoreUserValues )
01873     ++it;
01874 
01875   for ( ; it != myResources.end() && !ok; ++it )
01876     ok = (*it)->hasValue( sect, name );
01877 
01878   return ok;
01879 }
01880 
01886 bool QtxResourceMgr::hasSection( const QString& sect ) const
01887 {
01888   initialize();
01889 
01890   bool ok = false;
01891 
01892   ResList::ConstIterator it = myResources.begin();
01893   if ( myHasUserValues && workingMode() == IgnoreUserValues )
01894     ++it;
01895 
01896   for ( ; it != myResources.end() && !ok; ++it )
01897     ok = (*it)->hasSection( sect );
01898 
01899   return ok;
01900 }
01901 
01908 void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val )
01909 {
01910   int res;
01911   if ( checkExisting() && value( sect, name, res ) && res == val )
01912     return;
01913 
01914   setResource( sect, name, QString::number( val ) );
01915 }
01916 
01923 void QtxResourceMgr::setValue( const QString& sect, const QString& name, double val )
01924 {
01925   double res;
01926   if ( checkExisting() && value( sect, name, res ) && res == val )
01927     return;
01928 
01929   setResource( sect, name, QString::number( val, 'g', 12 ) );
01930 }
01931 
01938 void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool val )
01939 {
01940   bool res;
01941   if ( checkExisting() && value( sect, name, res ) && res == val )
01942     return;
01943 
01944   setResource( sect, name, QString( val ? "true" : "false" ) );
01945 }
01946 
01953 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QColor& val )
01954 {
01955   QColor res;
01956   if ( checkExisting() && value( sect, name, res ) && res == val )
01957     return;
01958 
01959   setResource( sect, name, Qtx::colorToString( val ) );
01960 }
01961 
01968 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QFont& val )
01969 {
01970   QFont res;
01971   if ( checkExisting() && value( sect, name, res ) && res == val )
01972     return;
01973 
01974   QStringList fontDescr;
01975   fontDescr.append( val.family() );
01976   if ( val.bold() )
01977     fontDescr.append( "Bold" );
01978   if ( val.italic() )
01979     fontDescr.append( "Italic" );
01980   if ( val.underline() )
01981     fontDescr.append( "Underline" );
01982   if ( val.overline() )
01983     fontDescr.append( "Overline" );
01984   fontDescr.append( QString( "%1" ).arg( val.pointSize() ) );
01985 
01986   setResource( sect, name, fontDescr.join( "," ) );
01987 }
01988 
01995 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QString& val )
01996 {
01997   QString res;
01998   if ( checkExisting() && value( sect, name, res ) && res == val )
01999     return;
02000 
02001   setResource( sect, name, val );
02002 }
02003 
02010 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QByteArray& val )
02011 {
02012   QByteArray res;
02013   if ( checkExisting() && value( sect, name, res ) && res == val )
02014     return;
02015 
02016   char buf[8];
02017   QStringList lst;
02018   for ( int i = 0; i < val.size();  i++ )
02019   {
02020     ::sprintf( buf, "#%02X", (unsigned char)val.at( i ) );
02021     lst.append( QString( buf ) );
02022   }
02023   setResource( sect, name, lst.join( " " ) );
02024 }
02025 
02032 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QLinearGradient& val )
02033 {
02034   QLinearGradient res;
02035   if ( checkExisting() && value( sect, name, res ) && res == val )
02036     return;
02037 
02038   setResource( sect, name, Qtx::gradientToString( val ) );
02039 }
02040 
02047 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QRadialGradient& val )
02048 {
02049   QRadialGradient res;
02050   if ( checkExisting() && value( sect, name, res ) && res == val )
02051     return;
02052 
02053   setResource( sect, name, Qtx::gradientToString( val ) );
02054 }
02055 
02062 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QConicalGradient& val )
02063 {
02064   QConicalGradient res;
02065   if ( checkExisting() && value( sect, name, res ) && res == val )
02066     return;
02067 
02068   setResource( sect, name, Qtx::gradientToString( val ) );
02069 }
02070 
02077 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const Qtx::BackgroundData& val )
02078 {
02079   Qtx::BackgroundData res;
02080   if ( checkExisting() && value( sect, name, res ) && res == val )
02081     return;
02082 
02083   setResource( sect, name, Qtx::backgroundToString( val ) );
02084 }
02085 
02090 void QtxResourceMgr::remove( const QString& sect )
02091 {
02092   initialize();
02093 
02094   for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
02095     (*it)->removeSection( sect );
02096 }
02097 
02103 void QtxResourceMgr::remove( const QString& sect, const QString& name )
02104 {
02105   initialize();
02106 
02107   for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
02108     (*it)->removeValue( sect, name );
02109 }
02110 
02115 QString QtxResourceMgr::currentFormat() const
02116 {
02117   QString fmt;
02118   if ( !myFormats.isEmpty() )
02119     fmt = myFormats[0]->format();
02120   return fmt;
02121 }
02122 
02127 void QtxResourceMgr::setCurrentFormat( const QString& fmt )
02128 {
02129   Format* form = format( fmt );
02130   if ( !form )
02131     return;
02132 
02133   myFormats.removeAll( form );
02134   myFormats.prepend( form );
02135 
02136   if ( myResources.isEmpty() )
02137     return;
02138 
02139   ResList::Iterator resIt = myResources.begin();
02140   if ( myResources.count() > myDirList.count() && resIt != myResources.end() )
02141   {
02142     (*resIt)->setFile( userFileName( appName() ) );
02143     ++resIt;
02144   }
02145 
02146   for ( QStringList::ConstIterator it = myDirList.begin(); it != myDirList.end() && resIt != myResources.end(); ++it, ++resIt )
02147     (*resIt)->setFile( Qtx::addSlash( *it ) + globalFileName( appName() ) );
02148 }
02149 
02155 QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
02156 {
02157   Format* form = 0;
02158   for ( FormatList::ConstIterator it = myFormats.begin(); it != myFormats.end() && !form; ++it )
02159   {
02160     if ( (*it)->format() == fmt )
02161       form = *it;
02162   }
02163 
02164   return form;
02165 }
02166 
02174 void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
02175 {
02176   if ( !myFormats.contains( form ) )
02177     myFormats.prepend( form );
02178 }
02179 
02184 void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
02185 {
02186   myFormats.removeAll( form );
02187 }
02188 
02193 QStringList QtxResourceMgr::options() const
02194 {
02195   return myOptions.keys();
02196 }
02197 
02207 QString QtxResourceMgr::option( const QString& opt ) const
02208 {
02209   QString val;
02210   if ( myOptions.contains( opt ) )
02211     val = myOptions[opt];
02212   return val;
02213 }
02214 
02221 void QtxResourceMgr::setOption( const QString& opt, const QString& val )
02222 {
02223   myOptions.insert( opt, val );
02224 }
02225 
02231 bool QtxResourceMgr::load()
02232 {
02233   initialize( false );
02234 
02235   Format* fmt = format( currentFormat() );
02236   if ( !fmt )
02237     return false;
02238 
02239   bool res = true;
02240   for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
02241     res = fmt->load( *it ) && res;
02242 
02243   return res;
02244 }
02245 
02251 bool QtxResourceMgr::import( const QString& fname )
02252 {
02253   Format* fmt = format( currentFormat() );
02254   if ( !fmt )
02255     return false;
02256 
02257   if ( myResources.isEmpty() || !myHasUserValues )
02258     return false;
02259 
02260   Resources* r = myResources[0];
02261   if ( !r )
02262     return false;
02263 
02264   QString old = r->file();
02265   r->setFile( fname );
02266   bool res = fmt->load( r );
02267   r->setFile( old );
02268   return res;
02269 }
02270 
02275 bool QtxResourceMgr::save()
02276 {
02277   initialize( false );
02278 
02279   Format* fmt = format( currentFormat() );
02280   if ( !fmt )
02281     return false;
02282 
02283   if ( myResources.isEmpty() || !myHasUserValues )
02284     return true;
02285 
02286   return fmt->save( myResources[0] );
02287 }
02288 
02293 QStringList QtxResourceMgr::sections() const
02294 {
02295   initialize();
02296 
02297   QMap<QString, int> map;
02298 
02299   ResList::ConstIterator it = myResources.begin();
02300   if ( myHasUserValues && workingMode() == IgnoreUserValues )
02301     ++it;
02302 
02303   for ( ; it != myResources.end(); ++it )
02304   {
02305     QStringList lst = (*it)->sections();
02306     for ( QStringList::ConstIterator itr = lst.begin(); itr != lst.end(); ++itr )
02307       map.insert( *itr, 0 );
02308   }
02309 
02310   return map.keys();
02311 }
02312 
02318 QStringList QtxResourceMgr::sections(const QRegExp& re) const
02319 {
02320   return sections().filter( re );
02321 }
02322 
02333 QStringList QtxResourceMgr::sections(const QStringList& names) const
02334 {
02335   QStringList nm = names;
02336   nm << ".+";
02337   QRegExp re( QString( "^%1$" ).arg( nm.join( sectionsToken() ) ) );
02338   return sections( re );
02339 }
02340 
02352 QStringList QtxResourceMgr::subSections(const QString& section, const bool full) const
02353 {
02354   QStringList names = sections( QStringList() << section );
02355   QMutableListIterator<QString> it( names );
02356   while ( it.hasNext() ) {
02357     QString name = it.next().mid( section.size() + 1 ).trimmed();
02358     if ( name.isEmpty() ) {
02359       it.remove();
02360       continue;
02361     }
02362     if ( !full ) name = name.split( sectionsToken() ).first();
02363     it.setValue( name );
02364   }
02365   names.removeDuplicates();
02366   names.sort();
02367   return names;
02368 }
02369 
02375 QStringList QtxResourceMgr::parameters( const QString& sec ) const
02376 {
02377   initialize();
02378 
02379 #if defined(QTX_NO_INDEXED_MAP)
02380   typedef QMap<QString, int> PMap;
02381 #else
02382   typedef IMap<QString, int> PMap;
02383 #endif
02384   PMap pmap;
02385   
02386   Resources* ur = !myResources.isEmpty() && workingMode() == IgnoreUserValues ? myResources[0] : 0;
02387   
02388   QListIterator<Resources*> it( myResources );
02389   it.toBack();
02390   while ( it.hasPrevious() )
02391   {
02392     Resources* r = it.previous();
02393     if ( r == ur ) break;
02394     QStringList lst = r->parameters( sec );
02395     for ( QStringList::ConstIterator itr = lst.begin(); itr != lst.end(); ++itr )
02396 #if defined(QTX_NO_INDEXED_MAP)
02397       if ( !pmap.contains( *itr ) ) pmap.insert( *itr, 0 );
02398 #else
02399       pmap.insert( *itr, 0, false );
02400 #endif
02401   }
02402 
02403   return pmap.keys();
02404 }
02405 
02416 QStringList QtxResourceMgr::parameters( const QStringList& names ) const
02417 {
02418   return parameters( names.join( sectionsToken() ) );
02419 }
02420 
02435 QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const QString& name ) const
02436 {
02437   QString res;
02438 
02439   ResList::ConstIterator it = myResources.begin();
02440   if ( myHasUserValues && workingMode() == IgnoreUserValues )
02441     ++it;
02442 
02443   for ( ; it != myResources.end() && res.isEmpty(); ++it )
02444     res = (*it)->path( sect, prefix, name );
02445   return res;
02446 }
02447 
02457 QString QtxResourceMgr::resSection() const
02458 {
02459   QString res = option( "res_section_name" );
02460   if ( res.isEmpty() )
02461     res = QString( "resources" );
02462   return res;
02463 }
02464 
02474 QString QtxResourceMgr::langSection() const
02475 {
02476   QString res = option( "lang_section_name" );
02477   if ( res.isEmpty() )
02478     res = QString( "language" );
02479   return res;
02480 }
02481 
02491 QString QtxResourceMgr::sectionsToken() const
02492 {
02493   QString res = option( "section_token" );
02494   if ( res.isEmpty() )
02495     res = QString( ":" );
02496   return res;
02497 }
02498 
02507 QPixmap QtxResourceMgr::defaultPixmap() const
02508 {
02509   QPixmap res;
02510   if ( myDefaultPix && !myDefaultPix->isNull() )
02511     res = *myDefaultPix;
02512   return res;
02513 }
02514 
02523 void QtxResourceMgr::setDefaultPixmap( const QPixmap& pix )
02524 {
02525   delete myDefaultPix;
02526   if ( pix.isNull() )
02527     myDefaultPix = 0;
02528   else
02529     myDefaultPix = new QPixmap( pix );
02530 }
02531 
02539 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name ) const
02540 {
02541   return loadPixmap( prefix, name, true );
02542 }
02543 
02554 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const bool useDef ) const
02555 {
02556   return loadPixmap( prefix, name, useDef ? defaultPixmap() : QPixmap() );
02557 }
02558 
02568 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const QPixmap& defPix ) const
02569 {
02570   initialize();
02571 
02572   QPixmap pix;
02573 
02574   ResList::ConstIterator it = myResources.begin();
02575   if ( myHasUserValues && workingMode() == IgnoreUserValues )
02576     ++it;
02577 
02578   for ( ; it != myResources.end() && pix.isNull(); ++it )
02579     pix = (*it)->loadPixmap( resSection(), prefix, name );
02580   if ( pix.isNull() )
02581     pix = defPix;
02582   return pix;
02583 }
02584 
02608 void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
02609 {
02610   initialize( true );
02611 
02612   QMap<QChar, QString> substMap;
02613   substMap.insert( 'A', appName() );
02614 
02615   QString lang = l;
02616   if ( lang.isEmpty() )
02617     value( langSection(), "language", lang );
02618 
02619   if ( lang.isEmpty() )
02620   {
02621     lang = QString( "en" );
02622     qWarning() << "QtxResourceMgr: Language not specified. Assumed:" << lang;
02623   }
02624 
02625   substMap.insert( 'L', lang );
02626 
02627   QString trs;
02628   if ( value( langSection(), "translators", trs, false ) && !trs.isEmpty() )
02629   {
02630     QStringList translators    = option( "translators" ).split( "|", QString::SkipEmptyParts );
02631     QStringList newTranslators = trs.split( "|", QString::SkipEmptyParts );
02632     for ( int i = 0; i < (int)newTranslators.count(); i++ )
02633     {
02634       if ( translators.indexOf( newTranslators[i] ) < 0 )
02635         translators += newTranslators[i];
02636     }
02637     setOption( "translators", translators.join( "|" ) );
02638   }
02639 
02640   QStringList trList = option( "translators" ).split( "|", QString::SkipEmptyParts );
02641   if ( trList.isEmpty() )
02642   {
02643     trList.append( "%P_msg_%L.qm" );
02644     qWarning() << "QtxResourceMgr: Translators not defined. Assumed:" << trList[0];
02645   }
02646 
02647   QStringList prefixList;
02648   if ( !pref.isEmpty() )
02649     prefixList.append( pref );
02650   else
02651     prefixList = parameters( resSection() );
02652 
02653   if ( pref.isEmpty() && lang != "en" ) {
02654     // load Qt resources
02655     QString qt_translations = QLibraryInfo::location( QLibraryInfo::TranslationsPath );
02656     QString qt_dir_trpath;
02657     if ( ::getenv( "QTDIR" ) )
02658       qt_dir_trpath = QString( ::getenv( "QTDIR" ) );
02659     if ( !qt_dir_trpath.isEmpty() )
02660       qt_dir_trpath = QDir( qt_dir_trpath ).absoluteFilePath( "translations" );
02661 
02662     QTranslator* trans = new QtxTranslator( 0 );
02663     if ( trans->load( QString("qt_%1").arg( lang ), qt_translations ) || trans->load( QString("qt_%1").arg( lang ), qt_dir_trpath ) )
02664       QApplication::instance()->installTranslator( trans );
02665   }
02666 
02667   for ( QStringList::ConstIterator iter = prefixList.begin(); iter != prefixList.end(); ++iter )
02668   {
02669     QString prefix = *iter;
02670     substMap.insert( 'P', prefix );
02671 
02672     QStringList trs;
02673     for ( QStringList::ConstIterator it = trList.begin(); it != trList.end(); ++it )
02674       trs.append( substMacro( *it, substMap ).trimmed() );
02675 
02676     loadTranslators( prefix, trs );
02677   }
02678 }
02679 
02686 void QtxResourceMgr::loadTranslators( const QString& prefix, const QStringList& translators )
02687 {
02688   initialize();
02689 
02690   ResList lst;
02691 
02692   ResList::ConstIterator iter = myResources.begin();
02693   if ( myHasUserValues && workingMode() == IgnoreUserValues )
02694     ++iter;
02695 
02696   for ( ; iter != myResources.end(); ++iter )
02697     lst.prepend( *iter );
02698 
02699   QTranslator* trans = 0;
02700   
02701   for ( ResList::Iterator it = lst.begin(); it != lst.end(); ++it )
02702   {
02703     for ( QStringList::ConstIterator itr = translators.begin(); itr != translators.end(); ++itr )
02704     {
02705       trans = (*it)->loadTranslator( resSection(), prefix, *itr );
02706       if ( trans )
02707       {
02708         if ( !myTranslator[prefix].contains( trans ) )
02709           myTranslator[prefix].append( trans );
02710         QApplication::instance()->installTranslator( trans );
02711       }
02712     }
02713   }
02714 }
02715 
02722 void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name )
02723 {
02724   initialize();
02725 
02726   QTranslator* trans = 0;
02727 
02728   Resources* ur = !myResources.isEmpty() && workingMode() == IgnoreUserValues ? myResources[0] : 0;
02729   
02730   QListIterator<Resources*> it( myResources );
02731   it.toBack();
02732   while ( it.hasPrevious() )
02733   {
02734     Resources* r = it.previous();
02735     if ( r == ur ) break;
02736 
02737     trans = r->loadTranslator( resSection(), prefix, name );
02738     if ( trans )
02739     {
02740       if ( !myTranslator[prefix].contains( trans ) )
02741         myTranslator[prefix].append( trans );
02742       QApplication::instance()->installTranslator( trans );
02743     }
02744   }
02745 }
02746 
02751 void QtxResourceMgr::removeTranslators( const QString& prefix )
02752 {
02753   if ( !myTranslator.contains( prefix ) )
02754     return;
02755 
02756   for ( TransList::Iterator it = myTranslator[prefix].begin(); it != myTranslator[prefix].end(); ++it )
02757   {
02758     QApplication::instance()->removeTranslator( *it );
02759     delete *it;
02760   }
02761 
02762   myTranslator.remove( prefix );
02763 }
02764 
02770 void QtxResourceMgr::raiseTranslators( const QString& prefix )
02771 {
02772   if ( !myTranslator.contains( prefix ) )
02773     return;
02774 
02775   for ( TransList::Iterator it = myTranslator[prefix].begin(); it != myTranslator[prefix].end(); ++it )
02776   {
02777     QApplication::instance()->removeTranslator( *it );
02778     QApplication::instance()->installTranslator( *it );
02779   }
02780 }
02781 
02786 void QtxResourceMgr::refresh()
02787 {
02788   QStringList sl = sections();
02789   for ( QStringList::ConstIterator it = sl.begin(); it != sl.end(); ++it )
02790   {
02791     QStringList pl = parameters( *it );
02792     for ( QStringList::ConstIterator itr = pl.begin(); itr != pl.end(); ++itr )
02793       setResource( *it, *itr, stringValue( *it, *itr ) );
02794   }
02795 }
02796 
02804 void QtxResourceMgr::setDirList( const QStringList& dl )
02805 {
02806   myDirList = dl;
02807   for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
02808     delete *it;
02809 
02810   myResources.clear();
02811 }
02812 
02819 void QtxResourceMgr::setResource( const QString& sect, const QString& name, const QString& val )
02820 {
02821   initialize();
02822 
02823   if ( !myResources.isEmpty() && myHasUserValues )
02824     myResources.first()->setValue( sect, name, val );
02825 }
02826 
02845 QString QtxResourceMgr::userFileName( const QString& appName, const bool /*for_load*/ ) const
02846 {
02847   QString fileName;
02848   QString pathName = QDir::homePath();
02849 
02850   QString cfgAppName = QApplication::applicationName();
02851   if ( !cfgAppName.isEmpty() )
02852     pathName = Qtx::addSlash( Qtx::addSlash( pathName ) + QString( ".config" ) ) + cfgAppName;
02853 
02854 #ifdef WIN32
02855   fileName = QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
02856 #else
02857   fileName = QString( ".%1rc" ).arg( appName );
02858 #endif
02859 
02860   if ( !fileName.isEmpty() )
02861     pathName = Qtx::addSlash( pathName ) + fileName;
02862 
02863   return pathName;
02864 }
02865 
02878 QString QtxResourceMgr::globalFileName( const QString& appName ) const
02879 {
02880   return QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
02881 }
02882 
02892 QString QtxResourceMgr::substMacro( const QString& src, const QMap<QChar, QString>& substMap ) const
02893 {
02894   QString trg = src;
02895 
02896   QRegExp rx( "%[A-Za-z%]" );
02897 
02898   int idx = 0;
02899   while ( ( idx = rx.indexIn( trg, idx ) ) >= 0 )
02900   {
02901     QChar spec = trg.at( idx + 1 );
02902     QString subst;
02903     if ( spec == '%' )
02904       subst = "%";
02905     else if ( substMap.contains( spec ) )
02906       subst = substMap[spec];
02907 
02908     if ( !subst.isEmpty() )
02909     {
02910       trg.replace( idx, rx.matchedLength(), subst );
02911       idx += subst.length();
02912     }
02913     else
02914       idx += rx.matchedLength();
02915   }
02916 
02917   return trg;
02918 }