1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: QtxResourceMgr.cxx
24 // Author: Alexander SOLOVYOV, Sergey TELKOV
26 #include "QtxResourceMgr.h"
27 #include "QtxTranslator.h"
34 #include <QTextStream>
35 #include <QApplication>
36 #include <QLibraryInfo>
39 #include <QDomDocument>
40 #include <QDomElement>
47 \class QtxResourceMgr::Resources
49 \brief Represents container for settings read from the resource file.
52 class QtxResourceMgr::Resources
55 Resources( QtxResourceMgr*, const QString& );
59 void setFile( const QString& );
61 QString value( const QString&, const QString&, const bool ) const;
62 void setValue( const QString&, const QString&, const QString& );
64 bool hasSection( const QString& ) const;
65 bool hasValue( const QString&, const QString& ) const;
67 void removeSection( const QString& );
68 void removeValue( const QString&, const QString& );
70 QPixmap loadPixmap( const QString&, const QString&, const QString& ) const;
71 QTranslator* loadTranslator( const QString&, const QString&, const QString& ) const;
73 QString makeSubstitution( const QString&, const QString&, const QString& ) const;
77 QStringList sections() const;
78 QStringList parameters( const QString& ) const;
80 QString path( const QString&, const QString&, const QString& ) const;
83 QtxResourceMgr* resMgr() const;
86 Section section( const QString& );
87 const Section section( const QString& ) const;
89 QString fileName( const QString&, const QString&, const QString& ) const;
92 typedef QMap<QString, Section> SectionMap;
95 QtxResourceMgr* myMgr; //!< resources manager
96 SectionMap mySections; //!< sections map
97 QString myFileName; //!< resources file name
98 QMap<QString,QPixmap> myPixmapCache; //!< pixmaps cache
100 friend class QtxResourceMgr::Format;
105 \param mgr parent resources manager
106 \param fileName resources file name
108 QtxResourceMgr::Resources::Resources( QtxResourceMgr* mgr, const QString& fileName )
110 myFileName( fileName )
117 QtxResourceMgr::Resources::~Resources()
122 \brief Get resources file name.
124 This file is used to load/save operations.
129 QString QtxResourceMgr::Resources::file() const
135 \brief Set resources file name.
139 void QtxResourceMgr::Resources::setFile( const QString& fn )
145 \brief Get string representation of parameter value.
146 \param sect section name
147 \param name parameter name
148 \param subst if \c true, perform variables substitution
149 \return parameter value or null QString if there is no such parameter
150 \sa setValue(), makeSubstitution()
152 QString QtxResourceMgr::Resources::value( const QString& sect, const QString& name, const bool subst ) const
156 if ( hasValue( sect, name ) )
158 val = section( sect )[name];
160 val = makeSubstitution( val, sect, name );
166 \brief Set parameter value.
167 \param sect section name
168 \param name parameter name
169 \param val parameter value
170 \sa value(), makeSubstitution()
172 void QtxResourceMgr::Resources::setValue( const QString& sect, const QString& name, const QString& val )
174 if ( !mySections.contains( sect ) )
175 mySections.insert( sect, Section() );
177 mySections[sect].insert( name, val );
181 \brief Check section existence.
182 \param sect section name
183 \return \c true if section exists
185 bool QtxResourceMgr::Resources::hasSection( const QString& sect ) const
187 return mySections.contains( sect );
191 \brief Check parameter existence.
192 \param sect section name
193 \param name parameter name
194 \return \c true if parameter exists in specified section
196 bool QtxResourceMgr::Resources::hasValue( const QString& sect, const QString& name ) const
198 return hasSection( sect ) && section( sect ).contains( name );
202 \brief Remove resourcs section.
203 \param sect secton name
205 void QtxResourceMgr::Resources::removeSection( const QString& sect )
207 mySections.remove( sect );
211 \brief Remove parameter from the section.
212 \param sect section name
213 \param name parameter name
215 void QtxResourceMgr::Resources::removeValue( const QString& sect, const QString& name )
217 if ( !mySections.contains( sect ) )
220 mySections[sect].remove( name );
222 if ( mySections[sect].isEmpty() )
223 mySections.remove( sect );
227 \brief Remove all sections.
229 void QtxResourceMgr::Resources::clear()
235 \brief Get all sections names.
236 \return list of section names
238 QStringList QtxResourceMgr::Resources::sections() const
240 return mySections.keys();
244 \brief Get all parameters name in specified section.
245 \param sec section name
246 \return list of settings names
248 QStringList QtxResourceMgr::Resources::parameters( const QString& sec ) const
250 if ( !hasSection( sec ) )
251 return QStringList();
253 return section( sec ).keys();
257 \brief Get absolute path to the file which name is defined by the parameter.
259 The file name is defined by \a name argument, while directory name is retrieved
260 from resources parameter \a prefix of section \a sec. Both directory and file name
261 can be relative. If the directory is relative, it is calculated from the initial
262 resources file name (see file()). Directory parameter can contain environment
263 variables, which are substituted automatically.
265 \param sec section name
266 \param prefix parameter containing directory name
267 \param name file name
268 \return absolute file path or null QString if file does not exist
269 \sa fileName(), file(), makeSubstitution()
271 QString QtxResourceMgr::Resources::path( const QString& sec, const QString& prefix, const QString& name ) const
273 QString filePath = fileName( sec, prefix, name );
274 if ( !filePath.isEmpty() )
276 if ( !QFileInfo( filePath ).exists() )
277 filePath = QString();
283 \brief Get resource manager
284 \return resource manager pointer
286 QtxResourceMgr* QtxResourceMgr::Resources::resMgr() const
292 \brief Get resources section by specified name.
294 If section does not exist it is created (empty).
296 \param sn section name
297 \return resources section
299 QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn )
301 if ( !mySections.contains( sn ) )
302 mySections.insert( sn, Section() );
304 return mySections[sn];
308 \brief Get resources section by specified name.
309 \param sn section name
310 \return resources section
312 const QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn ) const
314 return mySections[sn];
318 \brief Get file path.
320 The file name is defined by \a name argument, while directory name is retrieved
321 from resources parameter \a prefix of section \a sec. Both directory and file name
322 can be relative. If the directory is relative, it is calculated from the initial
323 resources file name (see file()). Directory parameter can contain environment
324 variables, which are substituted automatically.
325 File existence is not checked.
327 \param sec section name
328 \param prefix parameter containing directory name
329 \param name file name
330 \return absolute file path or null QString if \a prefix parameter
331 does not exist in section \sec
332 \sa path(), file(), makeSubstitution()
334 QString QtxResourceMgr::Resources::fileName( const QString& sect, const QString& prefix, const QString& name ) const
337 if ( !QFileInfo( name ).isRelative() )
343 if ( hasValue( sect, prefix ) )
345 path = value( sect, prefix, true );
346 if ( !path.isEmpty() )
348 if ( QFileInfo( path ).isRelative() )
349 path = Qtx::addSlash( Qtx::dir( myFileName, true ) ) + path;
351 path = Qtx::addSlash( path ) + name;
355 if( !path.isEmpty() )
357 QString fname = QDir::convertSeparators( path );
358 QFileInfo inf( fname );
359 fname = inf.absoluteFilePath();
366 \brief Load and return pixmap from external file.
368 If QtxResourceMgr::isPixmapCached() is \c true then cached pixmap is returned
369 (if it is already loaded), otherwise it is loaded from file.
370 If the file name is invalid, null pixmap is returned.
372 \param sect section name
373 \param prefix parameter containing resources directory name
374 \param name pixmap file name
375 \return pixmap loaded from file
377 QPixmap QtxResourceMgr::Resources::loadPixmap( const QString& sect, const QString& prefix, const QString& name ) const
379 QString fname = fileName( sect, prefix, name );
380 bool toCache = resMgr() ? resMgr()->isPixmapCached() : false;
382 if( toCache && myPixmapCache.contains( fname ) )
383 p = myPixmapCache[fname];
388 ( ( QMap<QString,QPixmap>& )myPixmapCache ).insert( fname, p );
394 \brief Load translator.
395 \param sect section name
396 \param prefix parameter containing resources directory
397 \param name translation file name
398 \return just created and loaded translator or 0 in case of error
400 QTranslator* QtxResourceMgr::Resources::loadTranslator( const QString& sect, const QString& prefix, const QString& name ) const
402 QTranslator* trans = new QtxTranslator( 0 );
403 QString fname = QDir::convertSeparators( fileName( sect, prefix, name ) );
404 if ( !trans->load( Qtx::file( fname, false ), Qtx::dir( fname ) ) )
413 \brief Substitute variables by their values.
415 Environment variable is substituted by its value. For other variables resource
416 manager tries to find value among defined resources parameters.
418 \param str string to be processed
419 \param sect section, where variables are searched
420 \param name name of variable which must be ignored during substitution
421 \return processed string (with all substitutions made)
423 QString QtxResourceMgr::Resources::makeSubstitution( const QString& str, const QString& sect, const QString& name ) const
427 QMap<QString, int> ignoreMap;
428 ignoreMap.insert( name, 0 );
430 int start( 0 ), len( 0 );
433 QString envName = Qtx::findEnvVar( res, start, len );
434 if ( envName.isNull() )
438 if ( ::getenv( envName.toLatin1() ) )
439 newStr = QString( ::getenv( envName.toLatin1() ) );
441 if ( newStr.isNull() )
443 if ( ignoreMap.contains( envName ) )
449 if ( hasValue( sect, envName ) )
450 newStr = value( sect, envName, false );
451 ignoreMap.insert( envName, 0 );
453 res.replace( start, len, newStr );
456 res.replace( "$$", "$" );
457 res.replace( "%%", "%" );
463 \class QtxResourceMgr::IniFormat
465 \brief Reader/writer for .ini resources files.
468 class QtxResourceMgr::IniFormat : public Format
475 virtual bool load( const QString&, QMap<QString, Section>& );
476 virtual bool save( const QString&, const QMap<QString, Section>& );
479 bool load( const QString&, QMap<QString, Section>&, QSet<QString>& );
485 QtxResourceMgr::IniFormat::IniFormat()
493 QtxResourceMgr::IniFormat::~IniFormat()
498 \brief Load resources from ini-file.
499 \param fname resources file name
500 \param secMap resources map to be filled in
501 \return \c true on success and \c false on error
503 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap )
505 QSet<QString> importHistory;
506 return load( fname, secMap, importHistory );
511 \brief Load resources from xml-file.
512 \param fname resources file name
513 \param secMap resources map to be filled in
514 \param importHistory list of already imported resources files (to prevent import loops)
515 \return \c true on success or \c false on error
517 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap, QSet<QString>& importHistory )
519 QString aFName = fname.trimmed();
520 if ( !QFileInfo( aFName ).exists() )
522 if ( QFileInfo( aFName + ".ini" ).exists() )
524 else if ( QFileInfo( aFName + ".INI" ).exists() )
527 return false; // file does not exist
529 QFileInfo aFinfo( aFName );
530 aFName = aFinfo.canonicalFilePath();
532 if ( !importHistory.contains( aFName ) )
533 importHistory.insert( aFName );
535 return true; // already imported (prevent import loops)
537 QFile file( aFName );
538 if ( !file.open( QFile::ReadOnly ) )
539 return false; // file is not accessible
541 QTextStream ts( &file );
548 QString separator = option( "separator" );
549 if ( separator.isNull() )
550 separator = QString( "=" );
552 QString comment = option( "comment" );
553 if ( comment.isNull() )
554 comment = QString( "#" );
558 data = ts.readLine();
564 data = data.trimmed();
565 if ( data.isEmpty() )
568 if ( data.startsWith( comment ) )
571 QRegExp rx( "^\\[([\\w\\s\\._]*)\\]$" );
572 if ( rx.indexIn( data ) != -1 )
574 section = rx.cap( 1 );
575 if ( section.isEmpty() )
578 qWarning() << "QtxResourceMgr: Empty section in line:" << line;
581 else if ( data.contains( separator ) && !section.isEmpty() )
583 int pos = data.indexOf( separator );
584 QString key = data.left( pos ).trimmed();
585 QString val = data.mid( pos + 1 ).trimmed();
586 secMap[section].insert( key, val );
588 else if ( section == "import" )
590 QString impFile = QDir::convertSeparators( Qtx::makeEnvVarSubst( data, Qtx::Always ) );
591 QFileInfo impFInfo( impFile );
592 if ( impFInfo.isRelative() )
593 impFInfo.setFile( aFinfo.absoluteDir(), impFile );
595 QMap<QString, Section> impMap;
596 if ( !load( impFInfo.absoluteFilePath(), impMap, importHistory ) )
598 qDebug() << "QtxResourceMgr: Error with importing file:" << data;
602 QMap<QString, Section>::const_iterator it = impMap.constBegin();
603 for ( ; it != impMap.constEnd() ; ++it )
605 if ( !secMap.contains( it.key() ) )
607 // insert full section
608 secMap.insert( it.key(), it.value() );
612 // insert all parameters from the section
613 Section::ConstIterator paramIt = it.value().begin();
614 for ( ; paramIt != it.value().end() ; ++paramIt )
616 if ( !secMap[it.key()].contains( paramIt.key() ) )
617 secMap[it.key()].insert( paramIt.key(), paramIt.value() );
626 if ( section.isEmpty() )
627 qWarning() << "QtxResourceMgr: Current section is empty";
629 qWarning() << "QtxResourceMgr: Error in line:" << line;
639 \brief Save resources to the ini-file.
640 \param fname resources file name
641 \param secMap resources map
642 \return \c true on success and \c false on error
644 bool QtxResourceMgr::IniFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
646 if ( !Qtx::mkDir( QFileInfo( fname ).absolutePath() ) )
650 if ( !file.open( QFile::WriteOnly ) )
653 QTextStream ts( &file );
655 ts << "# This file is automatically created by SALOME application." << endl;
656 ts << "# Changes made in this file can be lost!" << endl;
660 for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end() && res; ++it )
662 QStringList data( QString( "[%1]" ).arg( it.key() ) );
663 for ( Section::ConstIterator iter = it.value().begin(); iter != it.value().end(); ++iter )
664 data.append( iter.key() + " = " + iter.value() );
667 for ( QStringList::ConstIterator itr = data.begin(); itr != data.end(); ++itr )
677 \class QtxResourceMgr::XmlFormat
679 \brief Reader/writer for .xml resources files.
682 class QtxResourceMgr::XmlFormat : public Format
689 virtual bool load( const QString&, QMap<QString, Section>& );
690 virtual bool save( const QString&, const QMap<QString, Section>& );
693 QString docTag() const;
694 QString sectionTag() const;
695 QString parameterTag() const;
696 QString importTag() const;
697 QString nameAttribute() const;
698 QString valueAttribute() const;
700 bool load( const QString&, QMap<QString, Section>&, QSet<QString>& );
706 QtxResourceMgr::XmlFormat::XmlFormat()
714 QtxResourceMgr::XmlFormat::~XmlFormat()
719 \brief Load resources from xml-file.
720 \param fname resources file name
721 \param secMap resources map to be filled in
722 \return \c true on success and \c false on error
724 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap )
726 QSet<QString> importHistory;
727 return load( fname, secMap, importHistory );
731 \brief Load resources from xml-file.
732 \param fname resources file name
733 \param secMap resources map to be filled in
734 \param importHistory list of already imported resources files (to prevent import loops)
735 \return \c true on success and \c false on error
737 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap, QSet<QString>& importHistory )
739 QString aFName = fname.trimmed();
740 if ( !QFileInfo( aFName ).exists() )
742 if ( QFileInfo( aFName + ".xml" ).exists() )
744 else if ( QFileInfo( aFName + ".XML" ).exists() )
747 return false; // file does not exist
749 QFileInfo aFinfo( aFName );
750 aFName = aFinfo.canonicalFilePath();
752 if ( !importHistory.contains( aFName ) )
753 importHistory.insert( aFName );
755 return true; // already imported (prevent import loops)
761 QFile file( aFName );
762 if ( !file.open( QFile::ReadOnly ) )
764 qDebug() << "QtxResourceMgr: File is not accessible:" << aFName;
770 res = doc.setContent( &file );
775 qDebug() << "QtxResourceMgr: File is empty:" << aFName;
779 QDomElement root = doc.documentElement();
780 if ( root.isNull() || root.tagName() != docTag() )
782 qDebug() << "QtxResourceMgr: Invalid root in file:" << aFName;
786 QDomNode sectNode = root.firstChild();
787 while ( res && !sectNode.isNull() )
789 res = sectNode.isElement();
792 QDomElement sectElem = sectNode.toElement();
793 if ( sectElem.tagName() == sectionTag() && sectElem.hasAttribute( nameAttribute() ) )
795 QString section = sectElem.attribute( nameAttribute() );
796 QDomNode paramNode = sectNode.firstChild();
797 while ( res && !paramNode.isNull() )
799 res = paramNode.isElement();
802 QDomElement paramElem = paramNode.toElement();
803 if ( paramElem.tagName() == parameterTag() &&
804 paramElem.hasAttribute( nameAttribute() ) && paramElem.hasAttribute( valueAttribute() ) )
806 QString paramName = paramElem.attribute( nameAttribute() );
807 QString paramValue = paramElem.attribute( valueAttribute() );
808 secMap[section].insert( paramName, paramValue );
812 qDebug() << "QtxResourceMgr: Invalid parameter element in file:" << aFName;
818 res = paramNode.isComment();
820 qDebug() << "QtxResourceMgr: Node is neither element nor comment in file:" << aFName;
823 paramNode = paramNode.nextSibling();
826 else if ( sectElem.tagName() == importTag() && sectElem.hasAttribute( nameAttribute() ) )
828 QString impFile = QDir::convertSeparators( Qtx::makeEnvVarSubst( sectElem.attribute( nameAttribute() ), Qtx::Always ) );
829 QFileInfo impFInfo( impFile );
830 if ( impFInfo.isRelative() )
831 impFInfo.setFile( aFinfo.absoluteDir(), impFile );
833 QMap<QString, Section> impMap;
834 if ( !load( impFInfo.absoluteFilePath(), impMap, importHistory ) )
836 qDebug() << "QtxResourceMgr: Error with importing file:" << sectElem.attribute( nameAttribute() );
840 QMap<QString, Section>::const_iterator it = impMap.constBegin();
841 for ( ; it != impMap.constEnd() ; ++it )
843 if ( !secMap.contains( it.key() ) )
845 // insert full section
846 secMap.insert( it.key(), it.value() );
850 // insert all parameters from the section
851 Section::ConstIterator paramIt = it.value().begin();
852 for ( ; paramIt != it.value().end() ; ++paramIt )
854 if ( !secMap[it.key()].contains( paramIt.key() ) )
855 secMap[it.key()].insert( paramIt.key(), paramIt.value() );
863 qDebug() << "QtxResourceMgr: Invalid section in file:" << aFName;
869 res = sectNode.isComment(); // if it's a comment -- let it be, pass it..
871 qDebug() << "QtxResourceMgr: Node is neither element nor comment in file:" << aFName;
874 sectNode = sectNode.nextSibling();
880 qDebug() << "QtxResourceMgr: File" << fname << "is loaded successfully";
885 \brief Save resources to the xml-file.
886 \param fname resources file name
887 \param secMap resources map
888 \return \c true on success and \c false on error
890 bool QtxResourceMgr::XmlFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
896 if ( !Qtx::mkDir( QFileInfo( fname ).absolutePath() ) )
900 if ( !file.open( QFile::WriteOnly ) )
903 QDomDocument doc( docTag() );
904 QDomComment comment = doc.createComment( "\nThis file is automatically created by SALOME application.\nChanges made in this file can be lost!\n" );
905 doc.appendChild( comment );
906 QDomElement root = doc.createElement( docTag() );
907 doc.appendChild( root );
909 for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end(); ++it )
911 QDomElement sect = doc.createElement( sectionTag() );
912 sect.setAttribute( nameAttribute(), it.key() );
913 root.appendChild( sect );
914 for ( Section::ConstIterator iter = it.value().begin(); iter != it.value().end(); ++iter )
916 QDomElement val = doc.createElement( parameterTag() );
917 val.setAttribute( nameAttribute(), iter.key() );
918 val.setAttribute( valueAttribute(), iter.value() );
919 sect.appendChild( val );
923 QTextStream ts( &file );
924 QStringList docStr = doc.toString().split( "\n" );
925 for ( QStringList::ConstIterator itr = docStr.begin(); itr != docStr.end(); ++itr )
936 \brief Get document tag name
937 \return XML document tag name
939 QString QtxResourceMgr::XmlFormat::docTag() const
941 QString tag = option( "doc_tag" );
943 tag = QString( "document" );
948 \brief Get section tag name
949 \return XML section tag name
951 QString QtxResourceMgr::XmlFormat::sectionTag() const
953 QString tag = option( "section_tag" );
955 tag = QString( "section" );
960 \brief Get parameter tag name
961 \return XML parameter tag name
963 QString QtxResourceMgr::XmlFormat::parameterTag() const
965 QString tag = option( "parameter_tag" );
967 tag = QString( "parameter" );
972 \brief Get import tag name
973 \return XML import tag name
975 QString QtxResourceMgr::XmlFormat::importTag() const
977 QString tag = option( "import_tag" );
979 tag = QString( "import" );
984 \brief Get parameter tag's "name" attribute name
985 \return XML parameter tag's "name" attribute name
987 QString QtxResourceMgr::XmlFormat::nameAttribute() const
989 QString str = option( "name_attribute" );
991 str = QString( "name" );
996 \brief Get parameter tag's "value" attribute name
997 \return XML parameter tag's "value" attribute name
999 QString QtxResourceMgr::XmlFormat::valueAttribute() const
1001 QString str = option( "value_attribute" );
1002 if ( str.isEmpty() )
1003 str = QString( "value" );
1008 \class QtxResourceMgr::Format
1009 \brief Generic resources files reader/writer class.
1014 \param fmt format name (for example, "xml" or "ini")
1016 QtxResourceMgr::Format::Format( const QString& fmt )
1024 QtxResourceMgr::Format::~Format()
1029 \brief Get the format name.
1032 QString QtxResourceMgr::Format::format() const
1038 \brief Get options names.
1039 \return list of the format options
1041 QStringList QtxResourceMgr::Format::options() const
1043 return myOpt.keys();
1047 \brief Get the value of the option with specified name.
1049 If option doesn't exist then null QString is returned.
1051 \param opt option name
1052 \return option value
1054 QString QtxResourceMgr::Format::option( const QString& opt ) const
1057 if ( myOpt.contains( opt ) )
1063 \brief Set the value of the option with specified name.
1064 \param opt option name
1065 \param val option value
1067 void QtxResourceMgr::Format::setOption( const QString& opt, const QString& val )
1069 myOpt.insert( opt, val );
1073 \brief Load resources from the resource file.
1074 \param res resources object
1075 \return \c true on success and \c false on error
1077 bool QtxResourceMgr::Format::load( Resources* res )
1082 QMap<QString, Section> sections;
1083 bool status = load( res->myFileName, sections );
1085 res->mySections = sections;
1087 qDebug() << "QtxResourceMgr: Can't load resource file:" << res->myFileName;
1093 \brief Save resources to the resource file.
1094 \param res resources object
1095 \return \c true on success and \c false on error
1097 bool QtxResourceMgr::Format::save( Resources* res )
1102 Qtx::mkDir( Qtx::dir( res->myFileName ) );
1104 QtxResourceMgr* mgr = res->resMgr();
1105 QString name = mgr ? mgr->userFileName( mgr->appName(), false ) : res->myFileName;
1106 return save( name, res->mySections );
1110 \fn virtual bool QtxResourceMgr::Format::load( const QString& fname,
1111 QMap<QString, Section>& secMap )
1112 \brief Load resources from the specified resources file.
1114 Should be implemented in the successors.
1116 \param fname resources file name
1117 \param secMap resources map to be filled in
1118 \return \c true on success and \c false on error
1122 \fn virtual bool QtxResourceMgr::Format::save( const QString& fname,
1123 const QMap<QString, Section>& secMap )
1125 \brief Save resources to the specified resources file.
1127 Should be implemented in the successors.
1129 \param fname resources file name
1130 \param secMap resources map
1131 \return \c true on success and \c false on error
1135 \class QtxResourceMgr
1136 \brief Application resources manager.
1138 This class can be used to define settings, save/load settings and
1139 application preferences to the resource file(s), load translation files
1140 (internationalization mechanism), load pixmaps and other resources from
1141 external files, etc.
1143 Currently it supports .ini and .xml resources file formats. To implement
1144 own resources file format, inherit from the Format class and implement virtual
1145 Format::load() and Format::save() methods.
1147 Resources manager is initialized by the (symbolic) name of the application.
1148 The parameter \a resVarTemplate specifies the template for the environment
1149 variable which should point to the resource directory or list of directories.
1150 Environment variable name is calculated by substitution of "%1" substring in
1151 the \a resVarTemplate parameter (if it contains such substring) by the
1152 application name (\a appName).
1153 By default, \a resVarTemplate is set to "%1Resources". For example, if the application name
1154 is "MyApp", the environment variable "MyAppResources" will be inspected in this case.
1156 Resource manager can handle several global application configuration files and
1157 one user configuration file. Location of global configuration files is defined
1158 by the environment variable (see above) and these files are always read-only.
1159 The name of the global configuration files is retrieved by calling virtual method
1160 globalFileName() which can be redefined in the QtxResourceMgr class successors.
1161 User configuration file always situated in the user's home directory. It's name
1162 is defined by calling virtual method userFileName() which can be also redefined
1163 in the QtxResourceMgr class successors. This is the only file which the preferences
1164 changed by the user during the application session are written to (usually
1165 when the application closes).
1167 Resources environment variable should contain one or several resource directories
1168 (separated by ";" symbol on Windows and ":" or ";" on Linux). Each resource directory
1169 can contain application global configuration file. The user configuration file has
1170 the highest priority, for the global configuration files the priority is decreasing from
1171 left to right, i.e. the first directory in the directoris list, defined by the
1172 resources environment variable has higher priority. Priority has the meaning when
1173 searching requested resources (application preference, pixmap file name, translation
1176 When retrieving preferences, it is sometimes helpful to ignore values coming from the
1177 user preference file and take into account only global preferences.
1178 To do this, use setWorkingMode() method passing QtxResourceMgr::IgnoreUserValues enumerator
1181 Resources manager operates with such terms like options, sections and parameters.
1182 Parametets are named application resources, for example, application preferences like
1183 integer, double, boolean or string values, pictures, font and color definitions, etc.
1184 Parameters are organized inside the resources files into the named groups - sections.
1185 Options are special kind of resoures which allow customizing resource files interpreting.
1186 For example, by default language settings are defined in the resource file in the
1187 section "language". It is possible to change this section name by setting "language"
1188 option to another value (see setOption()).
1190 Retrieving preferences values can be done by using one of value() methods, each returns
1191 \c true if the corresponding preference is found. Another way is to use integerValue(),
1192 doubleValue(), etc methods, which allow specifying default value which is used if the
1193 specified preference is not found. Removing of preferences or sections can be done using
1194 remove(const QString& sect) or remove(const QString& sect, const QString& name) methods.
1195 To add the preference or to change exiting preference value use setValue() methods family.
1196 Methods hasSection() and hasValue() can be used to check existence of section or
1197 preference (in the specified section). List of all sections can be retrieved with the
1198 sections() method, and list of all settings names in some specified section can be
1199 obtained with parameters() method.
1201 Pixmaps can be loaded with the loadPixmap() methods. If the specified pixmap is not found,
1202 the default one is returned. Default pixmap can be set by setDefaultPixmap().
1204 One of the key feature of the resources manager is support of application
1205 internationalization mechanism. Translation files for the specified language can be loaded
1206 with loadLanguage() method.
1210 \brief Constructs the resource manager.
1211 \param appName application name
1212 \param resVarTemplate resource environment variable pattern
1214 QtxResourceMgr::QtxResourceMgr( const QString& appName, const QString& resVarTemplate )
1215 : myAppName( appName ),
1216 myCheckExist( true ),
1218 myIsPixmapCached( true ),
1219 myHasUserValues( true ),
1220 myWorkingMode( AllowUserValues )
1222 QString envVar = !resVarTemplate.isEmpty() ? resVarTemplate : QString( "%1Resources" );
1223 if ( envVar.contains( "%1" ) )
1224 envVar = envVar.arg( appName );
1227 if ( ::getenv( envVar.toLatin1() ) )
1228 dirs = ::getenv( envVar.toLatin1() );
1230 QString dirsep = ";"; // for Windows: ";" is used as directories separator
1232 QString dirsep = "[:|;]"; // for Linux: both ":" and ";" can be used
1234 setDirList( dirs.split( QRegExp( dirsep ), QString::SkipEmptyParts ) );
1236 installFormat( new XmlFormat() );
1237 installFormat( new IniFormat() );
1239 setOption( "translators", QString( "%P_msg_%L.qm|%P_images.qm" ) );
1245 Destroy the resource manager and free allocated memory.
1247 QtxResourceMgr::~QtxResourceMgr()
1249 QStringList prefList = myTranslator.keys();
1250 for ( QStringList::ConstIterator it = prefList.begin(); it != prefList.end(); ++it )
1251 removeTranslators( *it );
1253 qDeleteAll( myResources );
1254 qDeleteAll( myFormats );
1256 delete myDefaultPix;
1260 \brief Get the application name.
1261 \return application name
1263 QString QtxResourceMgr::appName() const
1269 \brief Get the "check existance" flag
1271 If this flag is \c true then preference can be set (with setValue() method)
1272 only if it doesn't exist or if the value is changed.
1274 \return \c true if "check existance" flag is set
1276 bool QtxResourceMgr::checkExisting() const
1278 return myCheckExist;
1282 \brief Set the "check existance" flag.
1283 \param on new flag value
1285 void QtxResourceMgr::setCheckExisting( const bool on )
1291 \brief Get the resource directories list.
1293 Home user directory (where the user application configuration file is situated)
1294 is not included. This is that directories list defined by the application
1295 resources environment variable.
1297 \return list of directories names
1299 QStringList QtxResourceMgr::dirList() const
1305 \brief Initialise resources manager.
1307 Prepare the resources containers and load resources (if \a autoLoad is \c true).
1309 \param autoLoad if \c true (default) then all resources are loaded
1311 void QtxResourceMgr::initialize( const bool autoLoad ) const
1313 if ( !myResources.isEmpty() )
1316 QtxResourceMgr* that = (QtxResourceMgr*)this;
1318 if ( !userFileName( appName() ).isEmpty() )
1319 that->myResources.append( new Resources( that, userFileName( appName() ) ) );
1321 that->myHasUserValues = myResources.count() > 0;
1323 for ( QStringList::ConstIterator it = myDirList.begin(); it != myDirList.end(); ++it )
1325 QString path = Qtx::addSlash( *it ) + globalFileName( appName() );
1326 that->myResources.append( new Resources( that, path ) );
1334 \brief Get "cached pixmaps" option value.
1336 Resources manager allows possibility to cache loaded pixmaps that allow to
1337 improve application performance. This feature is turned on by default - all
1338 loaded pixmaps are stored in the internal map. Switching of this feature on/off
1339 can be done by setIsPixmapCached() method.
1341 \return \c true if pixmap cache is turned on
1342 \sa setIsPixmapCached()
1344 bool QtxResourceMgr::isPixmapCached() const
1346 return myIsPixmapCached;
1350 \brief Switch "cached pixmaps" option on/off.
1351 \param on enable pixmap cache if \c true and disable it if \c false
1352 \sa isPixmapCached()
1354 void QtxResourceMgr::setIsPixmapCached( const bool on )
1356 myIsPixmapCached = on;
1360 \brief Remove all resources from the resources manager.
1362 void QtxResourceMgr::clear()
1364 for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
1369 \brief Get current working mode.
1371 \return current working mode
1372 \sa setWorkingMode(), value(), hasValue(), hasSection(), setValue()
1374 QtxResourceMgr::WorkingMode QtxResourceMgr::workingMode() const
1376 return myWorkingMode;
1380 \brief Set resource manager's working mode.
1382 The resource manager can operate in the following working modes:
1383 * AllowUserValues : methods values(), hasValue(), hasSection() take into account user values (default)
1384 * IgnoreUserValues : methods values(), hasValue(), hasSection() do not take into account user values
1386 Note, that setValue() method always put the value to the user settings file.
1388 \param mode new working mode
1389 \sa workingMode(), value(), hasValue(), hasSection(), setValue()
1391 void QtxResourceMgr::setWorkingMode( WorkingMode mode )
1393 myWorkingMode = mode;
1397 \brief Get interger parameter value.
1398 \param sect section name
1399 \param name parameter name
1400 \param iVal parameter to return resulting integer value
1401 \return \c true if parameter is found and \c false if parameter is not found
1402 (in this case \a iVal value is undefined)
1404 bool QtxResourceMgr::value( const QString& sect, const QString& name, int& iVal ) const
1407 if ( !value( sect, name, val, true ) )
1411 iVal = val.toInt( &ok );
1417 \brief Get double parameter value.
1418 \param sect section name
1419 \param name parameter name
1420 \param dVal parameter to return resulting double value
1421 \return \c true if parameter is found and \c false if parameter is not found
1422 (in this case \a dVal value is undefined)
1424 bool QtxResourceMgr::value( const QString& sect, const QString& name, double& dVal ) const
1427 if ( !value( sect, name, val, true ) )
1431 dVal = val.toDouble( &ok );
1437 \brief Get boolean parameter value.
1438 \param sect section name
1439 \param name parameter name
1440 \param bVal parameter to return resulting boolean value
1441 \return \c true if parameter is found and \c false if parameter is not found
1442 (in this case \a bVal value is undefined)
1444 bool QtxResourceMgr::value( const QString& sect, const QString& name, bool& bVal ) const
1447 if ( !value( sect, name, val, true ) )
1450 static QMap<QString, bool> boolMap;
1451 if ( boolMap.isEmpty() )
1453 boolMap["true"] = boolMap["yes"] = boolMap["on"] = true;
1454 boolMap["false"] = boolMap["no"] = boolMap["off"] = false;
1457 val = val.toLower();
1458 bool res = boolMap.contains( val );
1460 bVal = boolMap[val];
1463 double num = val.toDouble( &res );
1472 \brief Get color parameter value.
1473 \param sect section name
1474 \param name parameter name
1475 \param cVal parameter to return resulting color value
1476 \return \c true if parameter is found and \c false if parameter is not found
1477 (in this case \a cVal value is undefined)
1479 bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cVal ) const
1482 if ( !value( sect, name, val, true ) )
1485 return Qtx::stringToColor( val, cVal );
1489 \brief Get font parameter value.
1490 \param sect section name
1491 \param name parameter name
1492 \param fVal parameter to return resulting font value
1493 \return \c true if parameter is found and \c false if parameter is not found
1494 (in this case \a fVal value is undefined)
1496 bool QtxResourceMgr::value( const QString& sect, const QString& name, QFont& fVal ) const
1499 if ( !value( sect, name, val, true ) )
1502 QStringList fontDescr = val.split( ",", QString::SkipEmptyParts );
1504 if ( fontDescr.count() < 2 )
1507 QString family = fontDescr[0];
1508 if ( family.isEmpty() )
1511 fVal = QFont( family );
1513 for ( int i = 1; i < (int)fontDescr.count(); i++ )
1515 QString curval = fontDescr[i].trimmed().toLower();
1516 if ( curval == QString( "bold" ) )
1517 fVal.setBold( true );
1518 else if ( curval == QString( "italic" ) )
1519 fVal.setItalic( true );
1520 else if ( curval == QString( "underline" ) )
1521 fVal.setUnderline( true );
1522 else if ( curval == QString( "shadow" ) || curval == QString( "overline" ) )
1523 fVal.setOverline( true );
1527 int ps = curval.toInt( &isOk );
1529 fVal.setPointSize( ps );
1537 \brief Get byte array parameter value.
1538 \param sect section name
1539 \param name parameter name
1540 \param baVal parameter to return resulting byte array value
1541 \return \c true if parameter is found and \c false if parameter is not found
1542 (in this case \a baVal value is undefined)
1544 bool QtxResourceMgr::value( const QString& sect, const QString& name, QByteArray& baVal ) const
1547 if ( !value( sect, name, val, true ) )
1551 QStringList lst = val.split( QRegExp( "[\\s|,]" ), QString::SkipEmptyParts );
1552 for ( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it )
1556 if ( str.startsWith( "#" ) )
1562 int num = str.toInt( &ok, base );
1563 if ( !ok || num < 0 || num > 255 )
1566 baVal.append( (char)num );
1568 return !baVal.isEmpty();
1572 \brief Get linear gradient parameter value.
1573 \param sect section name
1574 \param name parameter name
1575 \param gVal parameter to return resulting linear gradient value
1576 \return \c true if parameter is found and \c false if parameter is not found
1577 (in this case \a gVal value is undefined)
1579 bool QtxResourceMgr::value( const QString& sect, const QString& name, QLinearGradient& gVal ) const
1582 if ( !value( sect, name, val, true ) )
1585 return Qtx::stringToLinearGradient( val, gVal );
1589 \brief Get radial gradient parameter value.
1590 \param sect section name
1591 \param name parameter name
1592 \param gVal parameter to return resulting radial gradient value
1593 \return \c true if parameter is found and \c false if parameter is not found
1594 (in this case \a gVal value is undefined)
1596 bool QtxResourceMgr::value( const QString& sect, const QString& name, QRadialGradient& gVal ) const
1599 if ( !value( sect, name, val, true ) )
1602 return Qtx::stringToRadialGradient( val, gVal );
1606 \brief Get conical gradient parameter value.
1607 \param sect section name
1608 \param name parameter name
1609 \param gVal parameter to return resulting conical gradient value
1610 \return \c true if parameter is found and \c false if parameter is not found
1611 (in this case \a gVal value is undefined)
1613 bool QtxResourceMgr::value( const QString& sect, const QString& name, QConicalGradient& gVal ) const
1616 if ( !value( sect, name, val, true ) )
1619 return Qtx::stringToConicalGradient( val, gVal );
1623 \brief Get background parameter value.
1624 \param sect section name
1625 \param name parameter name
1626 \param bgVal parameter to return resulting background value
1627 \return \c true if parameter is found and \c false if parameter is not found
1628 (in this case \a bgVal value is undefined)
1630 bool QtxResourceMgr::value( const QString& sect, const QString& name, Qtx::BackgroundData& bgVal ) const
1633 if ( !value( sect, name, val, true ) )
1636 bgVal = Qtx::stringToBackground( val );
1637 return bgVal.isValid();
1641 \brief Get string parameter value (native format).
1642 \param sect section name
1643 \param name parameter name
1644 \param val parameter to return resulting byte array value
1645 \param subst if \c true perform environment variables substitution
1646 \return \c true if parameter is found and \c false if parameter is not found
1647 (in this case \a val value is undefined)
1649 bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& val, const bool subst ) const
1655 ResList::ConstIterator it = myResources.begin();
1656 if ( myHasUserValues && workingMode() == IgnoreUserValues )
1659 for ( ; it != myResources.end() && !ok; ++it )
1661 ok = (*it)->hasValue( sect, name );
1663 val = (*it)->value( sect, name, subst );
1670 \brief Get interger parameter value.
1672 If the specified parameter is not found or can not be converted to the integer value,
1673 the specified default value is returned instead.
1675 \param sect section name
1676 \param name parameter name
1677 \param def default value
1678 \return parameter value (or default value if parameter is not found)
1680 int QtxResourceMgr::integerValue( const QString& sect, const QString& name, const int def ) const
1683 if ( !value( sect, name, val ) )
1689 \brief Get double parameter value.
1691 If the specified parameter is not found or can not be converted to the double value,
1692 the specified default value is returned instead.
1694 \param sect section name
1695 \param name parameter name
1696 \param def default value
1697 \return parameter value (or default value if parameter is not found)
1699 double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, const double def ) const
1702 if ( !value( sect, name, val ) )
1708 \brief Get boolean parameter value.
1710 If the specified parameter is not found or can not be converted to the boolean value,
1711 the specified default value is returned instead.
1713 \param sect section name
1714 \param name parameter name
1715 \param def default value
1716 \return parameter value (or default value if parameter is not found)
1718 bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, const bool def ) const
1721 if ( !value( sect, name, val ) )
1727 \brief Get font parameter value.
1729 If the specified parameter is not found or can not be converted to the font value,
1730 the specified default value is returned instead.
1732 \param sect section name
1733 \param name parameter name
1734 \param def default value
1735 \return parameter value (or default value if parameter is not found)
1737 QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const QFont& def ) const
1740 if( !value( sect, name, font ) )
1746 \brief Get color parameter value.
1748 If the specified parameter is not found or can not be converted to the color value,
1749 the specified default value is returned instead.
1751 \param sect section name
1752 \param name parameter name
1753 \param def default value
1754 \return parameter value (or default value if parameter is not found)
1756 QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, const QColor& def ) const
1759 if ( !value( sect, name, val ) )
1765 \brief Get string parameter value.
1767 If the specified parameter is not found, the specified default value is returned instead.
1769 \param sect section name
1770 \param name parameter name
1771 \param def default value
1772 \return parameter value (or default value if parameter is not found)
1774 QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, const QString& def ) const
1777 if ( !value( sect, name, val ) )
1783 \brief Get byte array parameter value.
1785 If the specified parameter is not found, the specified default value is returned instead.
1787 \param sect section name
1788 \param name parameter name
1789 \param def default value
1790 \return parameter value (or default value if parameter is not found)
1792 QByteArray QtxResourceMgr::byteArrayValue( const QString& sect, const QString& name, const QByteArray& def ) const
1795 if ( !value( sect, name, val ) )
1801 \brief Get linear gradient parameter value.
1803 If the specified parameter is not found, the specified default value is returned instead.
1805 \param sect section name
1806 \param name parameter name
1807 \param def default value
1808 \return parameter value (or default value if parameter is not found)
1810 QLinearGradient QtxResourceMgr::linearGradientValue( const QString& sect, const QString& name, const QLinearGradient& def ) const
1812 QLinearGradient val;
1813 if ( !value( sect, name, val ) )
1819 \brief Get radial gradient parameter value.
1821 If the specified parameter is not found, the specified default value is returned instead.
1823 \param sect section name
1824 \param name parameter name
1825 \param def default value
1826 \return parameter value (or default value if parameter is not found)
1828 QRadialGradient QtxResourceMgr::radialGradientValue( const QString& sect, const QString& name, const QRadialGradient& def ) const
1830 QRadialGradient val;
1831 if ( !value( sect, name, val ) )
1837 \brief Get conical gradient parameter value.
1839 If the specified parameter is not found, the specified default value is returned instead.
1841 \param sect section name
1842 \param name parameter name
1843 \param def default value
1844 \return parameter value (or default value if parameter is not found)
1846 QConicalGradient QtxResourceMgr::conicalGradientValue( const QString& sect, const QString& name, const QConicalGradient& def ) const
1848 QConicalGradient val;
1849 if ( !value( sect, name, val ) )
1855 \brief Get background parameter value.
1857 If the specified parameter is not found, the specified default value is returned instead.
1859 \param sect section name
1860 \param name parameter name
1861 \param def default value
1862 \return parameter value (or default value if parameter is not found)
1864 Qtx::BackgroundData QtxResourceMgr::backgroundValue( const QString& sect, const QString& name, const Qtx::BackgroundData& def ) const
1866 Qtx::BackgroundData val;
1867 if ( !value( sect, name, val ) )
1873 \brief Check parameter existence.
1874 \param sect section name
1875 \param name parameter name
1876 \return \c true if parameter exists in specified section
1878 bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
1884 ResList::ConstIterator it = myResources.begin();
1885 if ( myHasUserValues && workingMode() == IgnoreUserValues )
1888 for ( ; it != myResources.end() && !ok; ++it )
1889 ok = (*it)->hasValue( sect, name );
1895 \brief Check section existence.
1896 \param sect section name
1897 \return \c true if section exists
1899 bool QtxResourceMgr::hasSection( const QString& sect ) const
1905 ResList::ConstIterator it = myResources.begin();
1906 if ( myHasUserValues && workingMode() == IgnoreUserValues )
1909 for ( ; it != myResources.end() && !ok; ++it )
1910 ok = (*it)->hasSection( sect );
1916 \brief Set integer parameter value.
1917 \param sect section name
1918 \param name parameter name
1919 \param val parameter value
1921 void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val )
1924 if ( checkExisting() && value( sect, name, res ) && res == val )
1927 setResource( sect, name, QString::number( val ) );
1931 \brief Set double parameter value.
1932 \param sect section name
1933 \param name parameter name
1934 \param val parameter value
1936 void QtxResourceMgr::setValue( const QString& sect, const QString& name, double val )
1939 if ( checkExisting() && value( sect, name, res ) && res == val )
1942 setResource( sect, name, QString::number( val, 'g', 12 ) );
1946 \brief Set boolean parameter value.
1947 \param sect section name
1948 \param name parameter name
1949 \param val parameter value
1951 void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool val )
1954 if ( checkExisting() && value( sect, name, res ) && res == val )
1957 setResource( sect, name, QString( val ? "true" : "false" ) );
1961 \brief Set color parameter value.
1962 \param sect section name
1963 \param name parameter name
1964 \param val parameter value
1966 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QColor& val )
1969 if ( checkExisting() && value( sect, name, res ) && res == val )
1972 setResource( sect, name, Qtx::colorToString( val ) );
1976 \brief Set font parameter value.
1977 \param sect section name
1978 \param name parameter name
1979 \param val parameter value
1981 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QFont& val )
1984 if ( checkExisting() && value( sect, name, res ) && res == val )
1987 QStringList fontDescr;
1988 fontDescr.append( val.family() );
1990 fontDescr.append( "Bold" );
1992 fontDescr.append( "Italic" );
1993 if ( val.underline() )
1994 fontDescr.append( "Underline" );
1995 if ( val.overline() )
1996 fontDescr.append( "Overline" );
1997 fontDescr.append( QString( "%1" ).arg( val.pointSize() ) );
1999 setResource( sect, name, fontDescr.join( "," ) );
2003 \brief Set string parameter value.
2004 \param sect section name
2005 \param name parameter name
2006 \param val parameter value
2008 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QString& val )
2011 if ( checkExisting() && value( sect, name, res ) && res == val )
2014 setResource( sect, name, val );
2018 \brief Set byte array parameter value.
2019 \param sect section name
2020 \param name parameter name
2021 \param val parameter value
2023 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QByteArray& val )
2026 if ( checkExisting() && value( sect, name, res ) && res == val )
2031 for ( int i = 0; i < val.size(); i++ )
2033 ::sprintf( buf, "#%02X", (unsigned char)val.at( i ) );
2034 lst.append( QString( buf ) );
2036 setResource( sect, name, lst.join( " " ) );
2040 \brief Set linear gradient parameter value.
2041 \param sect section name
2042 \param name parameter name
2043 \param val parameter value
2045 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QLinearGradient& val )
2047 QLinearGradient res;
2048 if ( checkExisting() && value( sect, name, res ) && res == val )
2051 setResource( sect, name, Qtx::gradientToString( val ) );
2055 \brief Set radial gradient parameter value.
2056 \param sect section name
2057 \param name parameter name
2058 \param val parameter value
2060 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QRadialGradient& val )
2062 QRadialGradient res;
2063 if ( checkExisting() && value( sect, name, res ) && res == val )
2066 setResource( sect, name, Qtx::gradientToString( val ) );
2070 \brief Set conical gradient parameter value.
2071 \param sect section name
2072 \param name parameter name
2073 \param val parameter value
2075 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QConicalGradient& val )
2077 QConicalGradient res;
2078 if ( checkExisting() && value( sect, name, res ) && res == val )
2081 setResource( sect, name, Qtx::gradientToString( val ) );
2085 \brief Set background parameter value.
2086 \param sect section name
2087 \param name parameter name
2088 \param val parameter value
2090 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const Qtx::BackgroundData& val )
2092 Qtx::BackgroundData res;
2093 if ( checkExisting() && value( sect, name, res ) && res == val )
2096 setResource( sect, name, Qtx::backgroundToString( val ) );
2100 \brief Remove resources section.
2101 \param sect section name
2103 void QtxResourceMgr::remove( const QString& sect )
2107 for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2108 (*it)->removeSection( sect );
2112 \brief Remove the specified parameter.
2113 \param sect section name
2114 \param name parameter name
2116 void QtxResourceMgr::remove( const QString& sect, const QString& name )
2120 for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2121 (*it)->removeValue( sect, name );
2125 \brief Get current configuration files format.
2126 \return configuration files format name
2128 QString QtxResourceMgr::currentFormat() const
2131 if ( !myFormats.isEmpty() )
2132 fmt = myFormats[0]->format();
2137 \brief Set current configuration files format.
2138 \param fmt configuration files format name
2140 void QtxResourceMgr::setCurrentFormat( const QString& fmt )
2142 Format* form = format( fmt );
2146 myFormats.removeAll( form );
2147 myFormats.prepend( form );
2149 if ( myResources.isEmpty() )
2152 ResList::Iterator resIt = myResources.begin();
2153 if ( myResources.count() > myDirList.count() && resIt != myResources.end() )
2155 (*resIt)->setFile( userFileName( appName() ) );
2159 for ( QStringList::ConstIterator it = myDirList.begin(); it != myDirList.end() && resIt != myResources.end(); ++it, ++resIt )
2160 (*resIt)->setFile( Qtx::addSlash( *it ) + globalFileName( appName() ) );
2164 \brief Get configuration files format by specified format name.
2165 \param fmt configuration files format name
2166 \return format object or 0 if format is not defined
2168 QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
2171 for ( FormatList::ConstIterator it = myFormats.begin(); it != myFormats.end() && !form; ++it )
2173 if ( (*it)->format() == fmt )
2181 \brief Install configuration files format.
2183 Added format becomes current.
2185 \param form format object to be installed
2187 void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
2189 if ( !myFormats.contains( form ) )
2190 myFormats.prepend( form );
2194 \brief Remove configuration files format.
2195 \param form format object to be uninstalled
2197 void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
2199 myFormats.removeAll( form );
2203 \brief Get resource format options names.
2204 \return list of options names
2206 QStringList QtxResourceMgr::options() const
2208 return myOptions.keys();
2212 \brief Get the string value of the specified resources format option.
2214 If option does not exist, null QString is returned.
2216 \param opt option name
2217 \return option value
2218 \sa setOption(), options()
2220 QString QtxResourceMgr::option( const QString& opt ) const
2223 if ( myOptions.contains( opt ) )
2224 val = myOptions[opt];
2229 \brief Set the string value of the specified resources format option.
2230 \param opt option name
2231 \param val option value
2232 \sa option(), options()
2234 void QtxResourceMgr::setOption( const QString& opt, const QString& val )
2236 myOptions.insert( opt, val );
2240 \brief Load all resources from all resource files (global and user).
2241 \return \c true on success and \c false on error
2244 bool QtxResourceMgr::load()
2246 initialize( false );
2248 Format* fmt = format( currentFormat() );
2253 for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2254 res = fmt->load( *it ) && res;
2260 \brief Import resources from specified resource file.
2261 \param fname resources file name
2262 \return \c true on success and \c false on error
2264 bool QtxResourceMgr::import( const QString& fname )
2266 Format* fmt = format( currentFormat() );
2270 if ( myResources.isEmpty() || !myHasUserValues )
2273 Resources* r = myResources[0];
2277 QString old = r->file();
2278 r->setFile( fname );
2279 bool res = fmt->load( r );
2285 \brief Save all resources to the user resource files.
2286 \return \c true on success and \c false on error
2288 bool QtxResourceMgr::save()
2290 initialize( false );
2292 Format* fmt = format( currentFormat() );
2296 if ( myResources.isEmpty() || !myHasUserValues )
2299 bool result = fmt->save( myResources[0] );
2307 \brief Get all sections names.
2308 \return list of section names
2310 QStringList QtxResourceMgr::sections() const
2314 QMap<QString, int> map;
2316 ResList::ConstIterator it = myResources.begin();
2317 if ( myHasUserValues && workingMode() == IgnoreUserValues )
2320 for ( ; it != myResources.end(); ++it )
2322 QStringList lst = (*it)->sections();
2323 for ( QStringList::ConstIterator itr = lst.begin(); itr != lst.end(); ++itr )
2324 map.insert( *itr, 0 );
2331 \brief Get all sections names matching specified regular expression.
2332 \param re searched regular expression
2333 \return list of sections names
2335 QStringList QtxResourceMgr::sections(const QRegExp& re) const
2337 return sections().filter( re );
2341 \brief Get all sections names with the prefix specified by passed
2342 list of parent sections names.
2344 Sub-sections are separated inside the section name by the sections
2345 separator token, for example "splash:color:label".
2347 \param names parent sub-sections names
2348 \return list of sections names
2350 QStringList QtxResourceMgr::sections(const QStringList& names) const
2352 QStringList nm = names;
2354 QRegExp re( QString( "^%1$" ).arg( nm.join( sectionsToken() ) ) );
2355 return sections( re );
2359 \brief Get list of sub-sections names for the specified parent section name.
2361 Sub-sections are separated inside the section name by the sections
2362 separator token, for example "splash:color:label".
2364 \param section parent sub-section name
2365 \param full if \c true return full names of child sub-sections, if \c false,
2366 return only top-level sub-sections names
2367 \return list of sub-sections names
2369 QStringList QtxResourceMgr::subSections(const QString& section, const bool full) const
2371 QStringList names = sections( QStringList() << section );
2372 QMutableListIterator<QString> it( names );
2373 while ( it.hasNext() ) {
2374 QString name = it.next().mid( section.size() + 1 ).trimmed();
2375 if ( name.isEmpty() ) {
2379 if ( !full ) name = name.split( sectionsToken() ).first();
2380 it.setValue( name );
2382 names.removeDuplicates();
2388 \brief Get all parameters name in specified section.
2389 \param sec section name
2390 \return list of settings names
2392 QStringList QtxResourceMgr::parameters( const QString& sec ) const
2396 #if defined(QTX_NO_INDEXED_MAP)
2397 typedef QMap<QString, int> PMap;
2399 typedef IMap<QString, int> PMap;
2403 Resources* ur = !myResources.isEmpty() && workingMode() == IgnoreUserValues ? myResources[0] : 0;
2405 QListIterator<Resources*> it( myResources );
2407 while ( it.hasPrevious() )
2409 Resources* r = it.previous();
2410 if ( r == ur ) break;
2411 QStringList lst = r->parameters( sec );
2412 for ( QStringList::ConstIterator itr = lst.begin(); itr != lst.end(); ++itr )
2413 #if defined(QTX_NO_INDEXED_MAP)
2414 if ( !pmap.contains( *itr ) ) pmap.insert( *itr, 0 );
2416 pmap.insert( *itr, 0, false );
2424 \brief Get all parameters name in specified
2425 list of sub-sections names.
2427 Sub-sections are separated inside the section name by the sections
2428 separator token, for example "splash:color:label".
2430 \param names parent sub-sections names
2431 \return list of settings names
2433 QStringList QtxResourceMgr::parameters( const QStringList& names ) const
2435 return parameters( names.join( sectionsToken() ) );
2439 \brief Get absolute path to the file which name is defined by the parameter.
2441 The file name is defined by \a name argument, while directory name is retrieved
2442 from resources parameter \a prefix of section \a sec. Both directory and file name
2443 can be relative. If the directory is relative, it is calculated from the initial
2444 resources file name. Directory parameter can contain environment
2445 variables, which are substituted automatically.
2447 \param sec section name
2448 \param prefix parameter containing directory name
2449 \param name file name
2450 \return absolute file path or null QString if file does not exist
2452 QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const QString& name ) const
2456 ResList::ConstIterator it = myResources.begin();
2457 if ( myHasUserValues && workingMode() == IgnoreUserValues )
2460 for ( ; it != myResources.end() && res.isEmpty(); ++it )
2461 res = (*it)->path( sect, prefix, name );
2466 \brief Get application resources section name.
2468 By default, application resources section name is "resources" but
2469 it can be changed by setting the "res_section_name" resources manager option.
2471 \return section corresponding to the resources directories
2472 \sa option(), setOption()
2474 QString QtxResourceMgr::resSection() const
2476 QString res = option( "res_section_name" );
2477 if ( res.isEmpty() )
2478 res = QString( "resources" );
2483 \brief Get application language section name.
2485 By default, application language section name is "language" but
2486 it can be changed by setting the "lang_section_name" resources manager option.
2488 \return section corresponding to the application language settings
2489 \sa option(), setOption()
2491 QString QtxResourceMgr::langSection() const
2493 QString res = option( "lang_section_name" );
2494 if ( res.isEmpty() )
2495 res = QString( "language" );
2500 \brief Get sections separator token.
2502 By default, sections separator token is colon symbol ":" but
2503 it can be changed by setting the "section_token" resources manager option.
2505 \return string corresponding to the current section separator token
2506 \sa option(), setOption()
2508 QString QtxResourceMgr::sectionsToken() const
2510 QString res = option( "section_token" );
2511 if ( res.isEmpty() )
2512 res = QString( ":" );
2517 \brief Get default pixmap.
2519 Default pixmap is used when requested pixmap resource is not found.
2521 \return default pixmap
2522 \sa setDefaultPixmap(), loadPixmap()
2524 QPixmap QtxResourceMgr::defaultPixmap() const
2527 if ( myDefaultPix && !myDefaultPix->isNull() )
2528 res = *myDefaultPix;
2533 \brief Set default pixmap.
2535 Default pixmap is used when requested pixmap resource is not found.
2537 \param pix default pixmap
2538 \sa defaultPixmap(), loadPixmap()
2540 void QtxResourceMgr::setDefaultPixmap( const QPixmap& pix )
2542 delete myDefaultPix;
2546 myDefaultPix = new QPixmap( pix );
2550 \brief Load pixmap resource.
2551 \param prefix parameter which refers to the resources directory (directories)
2552 \param name pixmap file name
2553 \return pixmap loaded from the file
2554 \sa defaultPixmap(), setDefaultPixmap()
2556 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name ) const
2558 return loadPixmap( prefix, name, true );
2562 \brief Load pixmap resource.
2564 \param prefix parameter which refers to the resources directory (directories)
2565 \param name pixmap file name
2566 \param useDef if \c false, default pixmap is not returned if resource is not found,
2567 in this case null pixmap is returned instead
2568 \return pixmap loaded from the file
2569 \sa defaultPixmap(), setDefaultPixmap()
2571 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const bool useDef ) const
2573 return loadPixmap( prefix, name, useDef ? defaultPixmap() : QPixmap() );
2577 \brief Load pixmap resource.
2579 \param prefix parameter which refers to the resources directory (directories)
2580 \param name pixmap file name
2581 \param defPix default which should be used if the resource file doesn't exist
2582 \return pixmap loaded from the file
2583 \sa defaultPixmap(), setDefaultPixmap()
2585 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const QPixmap& defPix ) const
2591 ResList::ConstIterator it = myResources.begin();
2592 if ( myHasUserValues && workingMode() == IgnoreUserValues )
2595 for ( ; it != myResources.end() && pix.isNull(); ++it )
2596 pix = (*it)->loadPixmap( resSection(), prefix, name );
2603 \brief Load translation files according to the specified language.
2605 Names of the translation files are calculated according to the pattern specified
2606 by the "translators" option (this option is read from the section "language" of resources files).
2607 By default, "%P_msg_%L.qm" pattern is used.
2608 Keywords \%A, \%P, \%L in the pattern are substituted by the application name, prefix and language name
2610 For example, for prefix "SUIT" and language "en", all translation files "SUIT_msg_en.qm" are searched and
2613 If prefix is empty or null string, all translation files specified in the "resources" section of resources
2614 files are loaded (actually, the section is retrieved from resSection() method).
2615 If language is not specified, it is retrieved from the langSection() method, and if the latest is also empty,
2616 by default "en" (English) language is used.
2617 By default, settings from the user preferences file are also loaded (if user resource file is valid,
2618 see userFileName()). To avoid loading user settings, pass \c false as first parameter.
2620 \param pref parameter which defines translation context (for example, package name)
2621 \param l language name
2623 \sa resSection(), langSection(), loadTranslators()
2625 void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
2629 QMap<QChar, QString> substMap;
2630 substMap.insert( 'A', appName() );
2633 if ( lang.isEmpty() )
2634 value( langSection(), "language", lang );
2636 if ( lang.isEmpty() )
2638 lang = QString( "en" );
2639 qWarning() << "QtxResourceMgr: Language not specified. Assumed:" << lang;
2642 substMap.insert( 'L', lang );
2645 if ( value( langSection(), "translators", trs, false ) && !trs.isEmpty() )
2647 QStringList translators = option( "translators" ).split( "|", QString::SkipEmptyParts );
2648 QStringList newTranslators = trs.split( "|", QString::SkipEmptyParts );
2649 for ( int i = 0; i < (int)newTranslators.count(); i++ )
2651 if ( translators.indexOf( newTranslators[i] ) < 0 )
2652 translators += newTranslators[i];
2654 setOption( "translators", translators.join( "|" ) );
2657 QStringList trList = option( "translators" ).split( "|", QString::SkipEmptyParts );
2658 if ( trList.isEmpty() )
2660 trList.append( "%P_msg_%L.qm" );
2661 qWarning() << "QtxResourceMgr: Translators not defined. Assumed:" << trList[0];
2664 QStringList prefixList;
2665 if ( !pref.isEmpty() )
2666 prefixList.append( pref );
2668 prefixList = parameters( resSection() );
2670 if ( pref.isEmpty() && lang != "en" ) {
2671 // load Qt resources
2672 QString qt_translations = QLibraryInfo::location( QLibraryInfo::TranslationsPath );
2673 QString qt_dir_trpath;
2674 if ( ::getenv( "QTDIR" ) )
2675 qt_dir_trpath = QString( ::getenv( "QTDIR" ) );
2676 if ( !qt_dir_trpath.isEmpty() )
2677 qt_dir_trpath = QDir( qt_dir_trpath ).absoluteFilePath( "translations" );
2679 QTranslator* trans = new QtxTranslator( 0 );
2680 if ( trans->load( QString("qt_%1").arg( lang ), qt_translations ) || trans->load( QString("qt_%1").arg( lang ), qt_dir_trpath ) )
2681 QApplication::instance()->installTranslator( trans );
2684 for ( QStringList::ConstIterator iter = prefixList.begin(); iter != prefixList.end(); ++iter )
2686 QString prefix = *iter;
2687 substMap.insert( 'P', prefix );
2690 for ( QStringList::ConstIterator it = trList.begin(); it != trList.end(); ++it )
2691 trs.append( substMacro( *it, substMap ).trimmed() );
2693 loadTranslators( prefix, trs );
2698 \brief Load translation files for the specified translation context.
2699 \param prefix parameter which defines translation context (for example, package name)
2700 \param translators list of translation files
2703 void QtxResourceMgr::loadTranslators( const QString& prefix, const QStringList& translators )
2709 ResList::ConstIterator iter = myResources.begin();
2710 if ( myHasUserValues && workingMode() == IgnoreUserValues )
2713 for ( ; iter != myResources.end(); ++iter )
2714 lst.prepend( *iter );
2716 QTranslator* trans = 0;
2718 for ( ResList::Iterator it = lst.begin(); it != lst.end(); ++it )
2720 for ( QStringList::ConstIterator itr = translators.begin(); itr != translators.end(); ++itr )
2722 trans = (*it)->loadTranslator( resSection(), prefix, *itr );
2725 if ( !myTranslator[prefix].contains( trans ) )
2726 myTranslator[prefix].append( trans );
2727 QApplication::instance()->installTranslator( trans );
2734 \brief Load translation file.
2735 \param prefix parameter which defines translation context (for example, package name)
2736 \param name translator file name
2737 \sa loadLanguage(), loadTranslators()
2739 void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name )
2743 QTranslator* trans = 0;
2745 Resources* ur = !myResources.isEmpty() && workingMode() == IgnoreUserValues ? myResources[0] : 0;
2747 QListIterator<Resources*> it( myResources );
2749 while ( it.hasPrevious() )
2751 Resources* r = it.previous();
2752 if ( r == ur ) break;
2754 trans = r->loadTranslator( resSection(), prefix, name );
2757 if ( !myTranslator[prefix].contains( trans ) )
2758 myTranslator[prefix].append( trans );
2759 QApplication::instance()->installTranslator( trans );
2765 \brief Remove all translators corresponding to the specified translation context.
2766 \param prefix parameter which defines translation context (for example, package name)
2768 void QtxResourceMgr::removeTranslators( const QString& prefix )
2770 if ( !myTranslator.contains( prefix ) )
2773 for ( TransList::Iterator it = myTranslator[prefix].begin(); it != myTranslator[prefix].end(); ++it )
2775 QApplication::instance()->removeTranslator( *it );
2779 myTranslator.remove( prefix );
2783 \brief Move all translators corresponding to the specified translation context
2784 to the top of translators stack (increase their priority).
2785 \param prefix parameter which defines translation context (for example, package name)
2787 void QtxResourceMgr::raiseTranslators( const QString& prefix )
2789 if ( !myTranslator.contains( prefix ) )
2792 for ( TransList::Iterator it = myTranslator[prefix].begin(); it != myTranslator[prefix].end(); ++it )
2794 QApplication::instance()->removeTranslator( *it );
2795 QApplication::instance()->installTranslator( *it );
2800 \brief Copy all parameters to the user resources in order to
2801 saved them lately in the user home folder.
2803 void QtxResourceMgr::refresh()
2805 QStringList sl = sections();
2806 for ( QStringList::ConstIterator it = sl.begin(); it != sl.end(); ++it )
2808 QStringList pl = parameters( *it );
2809 for ( QStringList::ConstIterator itr = pl.begin(); itr != pl.end(); ++itr )
2810 setResource( *it, *itr, stringValue( *it, *itr ) );
2815 \brief Set the resource directories (where global confguration files are searched).
2817 This function also clears all currently set resources.
2819 \param dl directories list
2821 void QtxResourceMgr::setDirList( const QStringList& dl )
2824 for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2827 myResources.clear();
2831 \brief Set parameter value.
2832 \param sect section name
2833 \param name parameter name
2834 \param val parameter value
2836 void QtxResourceMgr::setResource( const QString& sect, const QString& name, const QString& val )
2840 if ( !myResources.isEmpty() && myHasUserValues )
2841 myResources.first()->setValue( sect, name, val );
2845 \brief Get user configuration file name.
2847 This method can be redefined in the successor class to customize the user configuration file name.
2848 User configuration file is always situated in the user's home directory. By default .<appName>rc
2849 file is used on Linux (e.g. .MyApprc) and <appName>.<format> under Windows (e.g. MyApp.xml).
2851 Parameter \a for_load (not used in default implementation) specifies the usage mode, i.e. if
2852 user configuration file is opened for reading or writing. This allows customizing a way of application
2853 resources initializing (for example, if the user configuraion file includes version number and there is
2854 no file corresponding to this version in the user's home directory, it could be good idea to try
2855 the configuration file from the previous versions of the application).
2857 \param appName application name
2858 \param for_load boolean flag indicating that file is opened for loading or saving (not used in default implementation)
2859 \return user configuration file name
2860 \sa globalFileName()
2862 QString QtxResourceMgr::userFileName( const QString& appName, const bool /*for_load*/ ) const
2865 QString pathName = QDir::homePath();
2867 QString cfgAppName = QApplication::applicationName();
2868 if ( !cfgAppName.isEmpty() )
2869 pathName = Qtx::addSlash( Qtx::addSlash( pathName ) + QString( ".config" ) ) + cfgAppName;
2872 fileName = QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
2874 fileName = QString( "%1rc" ).arg( appName );
2875 // VSR 24/09/2012: issue 0021781: do not prepend filename with "."
2876 // when user file is stored in ~/.config/<appname> directory
2877 if ( cfgAppName.isEmpty() )
2878 fileName.prepend( "." );
2881 if ( !fileName.isEmpty() )
2882 pathName = Qtx::addSlash( pathName ) + fileName;
2888 \brief Get global configuration file name.
2890 This method can be redefined in the successor class to customize the global configuration file name.
2891 Global configuration files are searched in the directories specified by the application resources
2892 environment variable (e.g. MyAppResources). By default <appName>.<format> file name is used
2895 \param appName application name
2896 \return global configuration file name
2899 QString QtxResourceMgr::globalFileName( const QString& appName ) const
2901 return QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
2905 \brief This function is called after user configuration file is saved.
2906 Can be redefined in the successor classes, default implementation does nothing.
2908 void QtxResourceMgr::saved()
2913 \brief Perform substitution of the patterns like \%A, \%B, etc by values from the map.
2915 Used by loadLanguage().
2917 \param src sring to be processed
2918 \param substMap map of values for replacing
2919 \return processed string
2921 QString QtxResourceMgr::substMacro( const QString& src, const QMap<QChar, QString>& substMap ) const
2925 QRegExp rx( "%[A-Za-z%]" );
2928 while ( ( idx = rx.indexIn( trg, idx ) ) >= 0 )
2930 QChar spec = trg.at( idx + 1 );
2934 else if ( substMap.contains( spec ) )
2935 subst = substMap[spec];
2937 if ( !subst.isEmpty() )
2939 trg.replace( idx, rx.matchedLength(), subst );
2940 idx += subst.length();
2943 idx += rx.matchedLength();