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>
46 /* XPM for the default pixmap */
47 static const char* pixmap_not_found_xpm[] = {
69 QPixmap* QtxResourceMgr::myDefaultPix = NULL;
72 \class QtxResourceMgr::Resources
74 \brief Represents container for settings read from the resource file.
77 class QtxResourceMgr::Resources
80 Resources( QtxResourceMgr*, const QString& );
84 void setFile( const QString& );
86 QString value( const QString&, const QString&, const bool ) const;
87 void setValue( const QString&, const QString&, const QString& );
89 bool hasSection( const QString& ) const;
90 bool hasValue( const QString&, const QString& ) const;
92 void removeSection( const QString& );
93 void removeValue( const QString&, const QString& );
95 QPixmap loadPixmap( const QString&, const QString&, const QString& ) const;
96 QTranslator* loadTranslator( const QString&, const QString&, const QString& ) const;
98 QString makeSubstitution( const QString&, const QString&, const QString& ) const;
102 QStringList sections() const;
103 QStringList parameters( const QString& ) const;
105 QString path( const QString&, const QString&, const QString& ) const;
108 QtxResourceMgr* resMgr() const;
111 Section section( const QString& );
112 const Section section( const QString& ) const;
114 QString fileName( const QString&, const QString&, const QString& ) const;
117 typedef QMap<QString, Section> SectionMap;
120 QtxResourceMgr* myMgr; //!< resources manager
121 SectionMap mySections; //!< sections map
122 QString myFileName; //!< resources file name
123 QMap<QString,QPixmap> myPixmapCache; //!< pixmaps cache
125 friend class QtxResourceMgr::Format;
130 \param mgr parent resources manager
131 \param fileName resources file name
133 QtxResourceMgr::Resources::Resources( QtxResourceMgr* mgr, const QString& fileName )
135 myFileName( fileName )
142 QtxResourceMgr::Resources::~Resources()
147 \brief Get resources file name.
149 This file is used to load/save operations.
154 QString QtxResourceMgr::Resources::file() const
160 \brief Set resources file name.
164 void QtxResourceMgr::Resources::setFile( const QString& fn )
170 \brief Get string representation of parameter value.
171 \param sect section name
172 \param name parameter name
173 \param subst if \c true, perform variables substitution
174 \return parameter value or null QString if there is no such parameter
175 \sa setValue(), makeSubstitution()
177 QString QtxResourceMgr::Resources::value( const QString& sect, const QString& name, const bool subst ) const
181 if ( hasValue( sect, name ) )
183 val = section( sect )[name];
185 val = makeSubstitution( val, sect, name );
191 \brief Set parameter value.
192 \param sect section name
193 \param name parameter name
194 \param val parameter value
195 \sa value(), makeSubstitution()
197 void QtxResourceMgr::Resources::setValue( const QString& sect, const QString& name, const QString& val )
199 if ( !mySections.contains( sect ) )
200 mySections.insert( sect, Section() );
202 mySections[sect].insert( name, val );
206 \brief Check section existence.
207 \param sect section name
208 \return \c true if section exists
210 bool QtxResourceMgr::Resources::hasSection( const QString& sect ) const
212 return mySections.contains( sect );
216 \brief Check parameter existence.
217 \param sect section name
218 \param name parameter name
219 \return \c true if parameter exists in specified section
221 bool QtxResourceMgr::Resources::hasValue( const QString& sect, const QString& name ) const
223 return hasSection( sect ) && section( sect ).contains( name );
227 \brief Remove resourcs section.
228 \param sect secton name
230 void QtxResourceMgr::Resources::removeSection( const QString& sect )
232 mySections.remove( sect );
236 \brief Remove parameter from the section.
237 \param sect section name
238 \param name parameter name
240 void QtxResourceMgr::Resources::removeValue( const QString& sect, const QString& name )
242 if ( !mySections.contains( sect ) )
245 mySections[sect].remove( name );
247 if ( mySections[sect].isEmpty() )
248 mySections.remove( sect );
252 \brief Remove all sections.
254 void QtxResourceMgr::Resources::clear()
260 \brief Get all sections names.
261 \return list of section names
263 QStringList QtxResourceMgr::Resources::sections() const
265 return mySections.keys();
269 \brief Get all parameters name in specified section.
270 \param sec section name
271 \return list of settings names
273 QStringList QtxResourceMgr::Resources::parameters( const QString& sec ) const
275 if ( !hasSection( sec ) )
276 return QStringList();
278 return section( sec ).keys();
282 \brief Get absolute path to the file which name is defined by the parameter.
284 The file name is defined by \a name argument, while directory name is retrieved
285 from resources parameter \a prefix of section \a sec. Both directory and file name
286 can be relative. If the directory is relative, it is calculated from the initial
287 resources file name (see file()). Directory parameter can contain environment
288 variables, which are substituted automatically.
290 \param sec section name
291 \param prefix parameter containing directory name
292 \param name file name
293 \return absolute file path or null QString if file does not exist
294 \sa fileName(), file(), makeSubstitution()
296 QString QtxResourceMgr::Resources::path( const QString& sec, const QString& prefix, const QString& name ) const
298 QString filePath = fileName( sec, prefix, name );
299 if ( !filePath.isEmpty() )
301 if ( !QFileInfo( filePath ).exists() )
302 filePath = QString();
308 \brief Get resource manager
309 \return resource manager pointer
311 QtxResourceMgr* QtxResourceMgr::Resources::resMgr() const
317 \brief Get resources section by specified name.
319 If section does not exist it is created (empty).
321 \param sn section name
322 \return resources section
324 QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn )
326 if ( !mySections.contains( sn ) )
327 mySections.insert( sn, Section() );
329 return mySections[sn];
333 \brief Get resources section by specified name.
334 \param sn section name
335 \return resources section
337 const QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn ) const
339 return mySections[sn];
343 \brief Get file path.
345 The file name is defined by \a name argument, while directory name is retrieved
346 from resources parameter \a prefix of section \a sec. Both directory and file name
347 can be relative. If the directory is relative, it is calculated from the initial
348 resources file name (see file()). Directory parameter can contain environment
349 variables, which are substituted automatically.
350 File existence is not checked.
352 \param sec section name
353 \param prefix parameter containing directory name
354 \param name file name
355 \return absolute file path or null QString if \a prefix parameter
356 does not exist in section \sec
357 \sa path(), file(), makeSubstitution()
359 QString QtxResourceMgr::Resources::fileName( const QString& sect, const QString& prefix, const QString& name ) const
362 if ( !QFileInfo( name ).isRelative() )
368 if ( hasValue( sect, prefix ) )
370 path = value( sect, prefix, true );
371 if ( !path.isEmpty() )
373 if ( QFileInfo( path ).isRelative() )
374 path = Qtx::addSlash( Qtx::dir( myFileName, true ) ) + path;
376 path = Qtx::addSlash( path ) + name;
380 if( !path.isEmpty() )
382 QString fname = QDir::convertSeparators( path );
383 QFileInfo inf( fname );
384 fname = inf.absoluteFilePath();
391 \brief Load and return pixmap from external file.
393 If QtxResourceMgr::isPixmapCached() is \c true then cached pixmap is returned
394 (if it is already loaded), otherwise it is loaded from file.
395 If the file name is invalid, null pixmap is returned.
397 \param sect section name
398 \param prefix parameter containing resources directory name
399 \param name pixmap file name
400 \return pixmap loaded from file
402 QPixmap QtxResourceMgr::Resources::loadPixmap( const QString& sect, const QString& prefix, const QString& name ) const
404 QString fname = fileName( sect, prefix, name );
405 bool toCache = resMgr() ? resMgr()->isPixmapCached() : false;
407 if( toCache && myPixmapCache.contains( fname ) )
408 p = myPixmapCache[fname];
413 ( ( QMap<QString,QPixmap>& )myPixmapCache ).insert( fname, p );
419 \brief Load translator.
420 \param sect section name
421 \param prefix parameter containing resources directory
422 \param name translation file name
423 \return just created and loaded translator or 0 in case of error
425 QTranslator* QtxResourceMgr::Resources::loadTranslator( const QString& sect, const QString& prefix, const QString& name ) const
427 QTranslator* trans = new QtxTranslator( 0 );
428 QString fname = QDir::convertSeparators( fileName( sect, prefix, name ) );
429 if ( !trans->load( Qtx::file( fname, false ), Qtx::dir( fname ) ) )
438 \brief Substitute variables by their values.
440 Environment variable is substituted by its value. For other variables resource
441 manager tries to find value among defined resources parameters.
443 \param str string to be processed
444 \param sect section, where variables are searched
445 \param name name of variable which must be ignored during substitution
446 \return processed string (with all substitutions made)
448 QString QtxResourceMgr::Resources::makeSubstitution( const QString& str, const QString& sect, const QString& name ) const
452 QMap<QString, int> ignoreMap;
453 ignoreMap.insert( name, 0 );
455 int start( 0 ), len( 0 );
458 QString envName = Qtx::findEnvVar( res, start, len );
459 if ( envName.isNull() )
463 if ( ::getenv( envName.toLatin1() ) )
464 newStr = QString( ::getenv( envName.toLatin1() ) );
466 if ( newStr.isNull() )
468 if ( ignoreMap.contains( envName ) )
474 if ( hasValue( sect, envName ) )
475 newStr = value( sect, envName, false );
476 ignoreMap.insert( envName, 0 );
478 res.replace( start, len, newStr );
481 res.replace( "$$", "$" );
482 res.replace( "%%", "%" );
488 \class QtxResourceMgr::IniFormat
490 \brief Reader/writer for .ini resources files.
493 class QtxResourceMgr::IniFormat : public Format
500 virtual bool load( const QString&, QMap<QString, Section>& );
501 virtual bool save( const QString&, const QMap<QString, Section>& );
504 bool load( const QString&, QMap<QString, Section>&, QSet<QString>& );
510 QtxResourceMgr::IniFormat::IniFormat()
518 QtxResourceMgr::IniFormat::~IniFormat()
523 \brief Load resources from ini-file.
524 \param fname resources file name
525 \param secMap resources map to be filled in
526 \return \c true on success and \c false on error
528 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap )
530 QSet<QString> importHistory;
531 return load( fname, secMap, importHistory );
536 \brief Load resources from xml-file.
537 \param fname resources file name
538 \param secMap resources map to be filled in
539 \param importHistory list of already imported resources files (to prevent import loops)
540 \return \c true on success or \c false on error
542 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap, QSet<QString>& importHistory )
544 QString aFName = fname.trimmed();
545 if ( !QFileInfo( aFName ).exists() )
547 if ( QFileInfo( aFName + ".ini" ).exists() )
549 else if ( QFileInfo( aFName + ".INI" ).exists() )
552 return false; // file does not exist
554 QFileInfo aFinfo( aFName );
555 aFName = aFinfo.canonicalFilePath();
557 if ( !importHistory.contains( aFName ) )
558 importHistory.insert( aFName );
560 return true; // already imported (prevent import loops)
562 QFile file( aFName );
563 if ( !file.open( QFile::ReadOnly ) )
564 return false; // file is not accessible
566 QTextStream ts( &file );
573 QString separator = option( "separator" );
574 if ( separator.isNull() )
575 separator = QString( "=" );
577 QString comment = option( "comment" );
578 if ( comment.isNull() )
579 comment = QString( "#" );
583 data = ts.readLine();
589 data = data.trimmed();
590 if ( data.isEmpty() )
593 if ( data.startsWith( comment ) )
596 QRegExp rx( "^\\[([\\w\\s\\._]*)\\]$" );
597 if ( rx.indexIn( data ) != -1 )
599 section = rx.cap( 1 );
600 if ( section.isEmpty() )
603 qWarning() << "QtxResourceMgr: Empty section in line:" << line;
606 else if ( data.contains( separator ) && !section.isEmpty() )
608 int pos = data.indexOf( separator );
609 QString key = data.left( pos ).trimmed();
610 QString val = data.mid( pos + 1 ).trimmed();
611 secMap[section].insert( key, val );
613 else if ( section == "import" )
615 QString impFile = QDir::convertSeparators( Qtx::makeEnvVarSubst( data, Qtx::Always ) );
616 QFileInfo impFInfo( impFile );
617 if ( impFInfo.isRelative() )
618 impFInfo.setFile( aFinfo.absoluteDir(), impFile );
620 QMap<QString, Section> impMap;
621 if ( !load( impFInfo.absoluteFilePath(), impMap, importHistory ) )
623 qDebug() << "QtxResourceMgr: Error with importing file:" << data;
627 QMap<QString, Section>::const_iterator it = impMap.constBegin();
628 for ( ; it != impMap.constEnd() ; ++it )
630 if ( !secMap.contains( it.key() ) )
632 // insert full section
633 secMap.insert( it.key(), it.value() );
637 // insert all parameters from the section
638 Section::ConstIterator paramIt = it.value().begin();
639 for ( ; paramIt != it.value().end() ; ++paramIt )
641 if ( !secMap[it.key()].contains( paramIt.key() ) )
642 secMap[it.key()].insert( paramIt.key(), paramIt.value() );
651 if ( section.isEmpty() )
652 qWarning() << "QtxResourceMgr: Current section is empty";
654 qWarning() << "QtxResourceMgr: Error in line:" << line;
664 \brief Save resources to the ini-file.
665 \param fname resources file name
666 \param secMap resources map
667 \return \c true on success and \c false on error
669 bool QtxResourceMgr::IniFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
671 if ( !Qtx::mkDir( QFileInfo( fname ).absolutePath() ) )
675 if ( !file.open( QFile::WriteOnly ) )
678 QTextStream ts( &file );
680 ts << "# This file is automatically created by SALOME application." << endl;
681 ts << "# Changes made in this file can be lost!" << endl;
685 for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end() && res; ++it )
687 QStringList data( QString( "[%1]" ).arg( it.key() ) );
688 for ( Section::ConstIterator iter = it.value().begin(); iter != it.value().end(); ++iter )
689 data.append( iter.key() + " = " + iter.value() );
692 for ( QStringList::ConstIterator itr = data.begin(); itr != data.end(); ++itr )
702 \class QtxResourceMgr::XmlFormat
704 \brief Reader/writer for .xml resources files.
707 class QtxResourceMgr::XmlFormat : public Format
714 virtual bool load( const QString&, QMap<QString, Section>& );
715 virtual bool save( const QString&, const QMap<QString, Section>& );
718 QString docTag() const;
719 QString sectionTag() const;
720 QString parameterTag() const;
721 QString importTag() const;
722 QString nameAttribute() const;
723 QString valueAttribute() const;
725 bool load( const QString&, QMap<QString, Section>&, QSet<QString>& );
731 QtxResourceMgr::XmlFormat::XmlFormat()
739 QtxResourceMgr::XmlFormat::~XmlFormat()
744 \brief Load resources from xml-file.
745 \param fname resources file name
746 \param secMap resources map to be filled in
747 \return \c true on success and \c false on error
749 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap )
751 QSet<QString> importHistory;
752 return load( fname, secMap, importHistory );
756 \brief Load resources from xml-file.
757 \param fname resources file name
758 \param secMap resources map to be filled in
759 \param importHistory list of already imported resources files (to prevent import loops)
760 \return \c true on success and \c false on error
762 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap, QSet<QString>& importHistory )
764 QString aFName = fname.trimmed();
765 if ( !QFileInfo( aFName ).exists() )
767 if ( QFileInfo( aFName + ".xml" ).exists() )
769 else if ( QFileInfo( aFName + ".XML" ).exists() )
772 return false; // file does not exist
774 QFileInfo aFinfo( aFName );
775 aFName = aFinfo.canonicalFilePath();
777 if ( !importHistory.contains( aFName ) )
778 importHistory.insert( aFName );
780 return true; // already imported (prevent import loops)
786 QFile file( aFName );
787 if ( !file.open( QFile::ReadOnly ) )
789 qDebug() << "QtxResourceMgr: File is not accessible:" << aFName;
795 res = doc.setContent( &file );
800 qDebug() << "QtxResourceMgr: File is empty:" << aFName;
804 QDomElement root = doc.documentElement();
805 if ( root.isNull() || root.tagName() != docTag() )
807 qDebug() << "QtxResourceMgr: Invalid root in file:" << aFName;
811 QDomNode sectNode = root.firstChild();
812 while ( res && !sectNode.isNull() )
814 res = sectNode.isElement();
817 QDomElement sectElem = sectNode.toElement();
818 if ( sectElem.tagName() == sectionTag() && sectElem.hasAttribute( nameAttribute() ) )
820 QString section = sectElem.attribute( nameAttribute() );
821 QDomNode paramNode = sectNode.firstChild();
822 while ( res && !paramNode.isNull() )
824 res = paramNode.isElement();
827 QDomElement paramElem = paramNode.toElement();
828 if ( paramElem.tagName() == parameterTag() &&
829 paramElem.hasAttribute( nameAttribute() ) && paramElem.hasAttribute( valueAttribute() ) )
831 QString paramName = paramElem.attribute( nameAttribute() );
832 QString paramValue = paramElem.attribute( valueAttribute() );
833 secMap[section].insert( paramName, paramValue );
837 qDebug() << "QtxResourceMgr: Invalid parameter element in file:" << aFName;
843 res = paramNode.isComment();
845 qDebug() << "QtxResourceMgr: Node is neither element nor comment in file:" << aFName;
848 paramNode = paramNode.nextSibling();
851 else if ( sectElem.tagName() == importTag() && sectElem.hasAttribute( nameAttribute() ) )
853 QString impFile = QDir::convertSeparators( Qtx::makeEnvVarSubst( sectElem.attribute( nameAttribute() ), Qtx::Always ) );
854 QFileInfo impFInfo( impFile );
855 if ( impFInfo.isRelative() )
856 impFInfo.setFile( aFinfo.absoluteDir(), impFile );
858 QMap<QString, Section> impMap;
859 if ( !load( impFInfo.absoluteFilePath(), impMap, importHistory ) )
861 qDebug() << "QtxResourceMgr: Error with importing file:" << sectElem.attribute( nameAttribute() );
865 QMap<QString, Section>::const_iterator it = impMap.constBegin();
866 for ( ; it != impMap.constEnd() ; ++it )
868 if ( !secMap.contains( it.key() ) )
870 // insert full section
871 secMap.insert( it.key(), it.value() );
875 // insert all parameters from the section
876 Section::ConstIterator paramIt = it.value().begin();
877 for ( ; paramIt != it.value().end() ; ++paramIt )
879 if ( !secMap[it.key()].contains( paramIt.key() ) )
880 secMap[it.key()].insert( paramIt.key(), paramIt.value() );
888 qDebug() << "QtxResourceMgr: Invalid section in file:" << aFName;
894 res = sectNode.isComment(); // if it's a comment -- let it be, pass it..
896 qDebug() << "QtxResourceMgr: Node is neither element nor comment in file:" << aFName;
899 sectNode = sectNode.nextSibling();
905 qDebug() << "QtxResourceMgr: File" << fname << "is loaded successfully";
910 \brief Save resources to the xml-file.
911 \param fname resources file name
912 \param secMap resources map
913 \return \c true on success and \c false on error
915 bool QtxResourceMgr::XmlFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
921 if ( !Qtx::mkDir( QFileInfo( fname ).absolutePath() ) )
925 if ( !file.open( QFile::WriteOnly ) )
928 QDomDocument doc( docTag() );
929 QDomComment comment = doc.createComment( "\nThis file is automatically created by SALOME application.\nChanges made in this file can be lost!\n" );
930 doc.appendChild( comment );
931 QDomElement root = doc.createElement( docTag() );
932 doc.appendChild( root );
934 for ( QMap<QString, Section>::ConstIterator it = secMap.begin(); it != secMap.end(); ++it )
936 QDomElement sect = doc.createElement( sectionTag() );
937 sect.setAttribute( nameAttribute(), it.key() );
938 root.appendChild( sect );
939 for ( Section::ConstIterator iter = it.value().begin(); iter != it.value().end(); ++iter )
941 QDomElement val = doc.createElement( parameterTag() );
942 val.setAttribute( nameAttribute(), iter.key() );
943 val.setAttribute( valueAttribute(), iter.value() );
944 sect.appendChild( val );
948 QTextStream ts( &file );
949 QStringList docStr = doc.toString().split( "\n" );
950 for ( QStringList::ConstIterator itr = docStr.begin(); itr != docStr.end(); ++itr )
961 \brief Get document tag name
962 \return XML document tag name
964 QString QtxResourceMgr::XmlFormat::docTag() const
966 QString tag = option( "doc_tag" );
968 tag = QString( "document" );
973 \brief Get section tag name
974 \return XML section tag name
976 QString QtxResourceMgr::XmlFormat::sectionTag() const
978 QString tag = option( "section_tag" );
980 tag = QString( "section" );
985 \brief Get parameter tag name
986 \return XML parameter tag name
988 QString QtxResourceMgr::XmlFormat::parameterTag() const
990 QString tag = option( "parameter_tag" );
992 tag = QString( "parameter" );
997 \brief Get import tag name
998 \return XML import tag name
1000 QString QtxResourceMgr::XmlFormat::importTag() const
1002 QString tag = option( "import_tag" );
1003 if ( tag.isEmpty() )
1004 tag = QString( "import" );
1009 \brief Get parameter tag's "name" attribute name
1010 \return XML parameter tag's "name" attribute name
1012 QString QtxResourceMgr::XmlFormat::nameAttribute() const
1014 QString str = option( "name_attribute" );
1015 if ( str.isEmpty() )
1016 str = QString( "name" );
1021 \brief Get parameter tag's "value" attribute name
1022 \return XML parameter tag's "value" attribute name
1024 QString QtxResourceMgr::XmlFormat::valueAttribute() const
1026 QString str = option( "value_attribute" );
1027 if ( str.isEmpty() )
1028 str = QString( "value" );
1033 \class QtxResourceMgr::Format
1034 \brief Generic resources files reader/writer class.
1039 \param fmt format name (for example, "xml" or "ini")
1041 QtxResourceMgr::Format::Format( const QString& fmt )
1049 QtxResourceMgr::Format::~Format()
1054 \brief Get the format name.
1057 QString QtxResourceMgr::Format::format() const
1063 \brief Get options names.
1064 \return list of the format options
1066 QStringList QtxResourceMgr::Format::options() const
1068 return myOpt.keys();
1072 \brief Get the value of the option with specified name.
1074 If option doesn't exist then null QString is returned.
1076 \param opt option name
1077 \return option value
1079 QString QtxResourceMgr::Format::option( const QString& opt ) const
1082 if ( myOpt.contains( opt ) )
1088 \brief Set the value of the option with specified name.
1089 \param opt option name
1090 \param val option value
1092 void QtxResourceMgr::Format::setOption( const QString& opt, const QString& val )
1094 myOpt.insert( opt, val );
1098 \brief Load resources from the resource file.
1099 \param res resources object
1100 \return \c true on success and \c false on error
1102 bool QtxResourceMgr::Format::load( Resources* res )
1107 QMap<QString, Section> sections;
1108 bool status = load( res->myFileName, sections );
1110 res->mySections = sections;
1112 qDebug() << "QtxResourceMgr: Can't load resource file:" << res->myFileName;
1118 \brief Save resources to the resource file.
1119 \param res resources object
1120 \return \c true on success and \c false on error
1122 bool QtxResourceMgr::Format::save( Resources* res )
1127 Qtx::mkDir( Qtx::dir( res->myFileName ) );
1129 QtxResourceMgr* mgr = res->resMgr();
1130 QString name = mgr ? mgr->userFileName( mgr->appName(), false ) : res->myFileName;
1131 return save( name, res->mySections );
1135 \fn virtual bool QtxResourceMgr::Format::load( const QString& fname,
1136 QMap<QString, Section>& secMap )
1137 \brief Load resources from the specified resources file.
1139 Should be implemented in the successors.
1141 \param fname resources file name
1142 \param secMap resources map to be filled in
1143 \return \c true on success and \c false on error
1147 \fn virtual bool QtxResourceMgr::Format::save( const QString& fname,
1148 const QMap<QString, Section>& secMap )
1150 \brief Save resources to the specified resources file.
1152 Should be implemented in the successors.
1154 \param fname resources file name
1155 \param secMap resources map
1156 \return \c true on success and \c false on error
1160 \class QtxResourceMgr
1161 \brief Application resources manager.
1163 This class can be used to define settings, save/load settings and
1164 application preferences to the resource file(s), load translation files
1165 (internationalization mechanism), load pixmaps and other resources from
1166 external files, etc.
1168 Currently it supports .ini and .xml resources file formats. To implement
1169 own resources file format, inherit from the Format class and implement virtual
1170 Format::load() and Format::save() methods.
1172 Resources manager is initialized by the (symbolic) name of the application.
1173 The parameter \a resVarTemplate specifies the template for the environment
1174 variable which should point to the resource directory or list of directories.
1175 Environment variable name is calculated by substitution of "%1" substring in
1176 the \a resVarTemplate parameter (if it contains such substring) by the
1177 application name (\a appName).
1178 By default, \a resVarTemplate is set to "%1Resources". For example, if the application name
1179 is "MyApp", the environment variable "MyAppResources" will be inspected in this case.
1181 Resource manager can handle several global application configuration files and
1182 one user configuration file. Location of global configuration files is defined
1183 by the environment variable (see above) and these files are always read-only.
1184 The name of the global configuration files is retrieved by calling virtual method
1185 globalFileName() which can be redefined in the QtxResourceMgr class successors.
1186 User configuration file always situated in the user's home directory. It's name
1187 is defined by calling virtual method userFileName() which can be also redefined
1188 in the QtxResourceMgr class successors. This is the only file which the preferences
1189 changed by the user during the application session are written to (usually
1190 when the application closes).
1192 Resources environment variable should contain one or several resource directories
1193 (separated by ";" symbol on Windows and ":" or ";" on Linux). Each resource directory
1194 can contain application global configuration file. The user configuration file has
1195 the highest priority, for the global configuration files the priority is decreasing from
1196 left to right, i.e. the first directory in the directoris list, defined by the
1197 resources environment variable has higher priority. Priority has the meaning when
1198 searching requested resources (application preference, pixmap file name, translation
1201 When retrieving preferences, it is sometimes helpful to ignore values coming from the
1202 user preference file and take into account only global preferences.
1203 To do this, use setWorkingMode() method passing QtxResourceMgr::IgnoreUserValues enumerator
1206 Resources manager operates with such terms like options, sections and parameters.
1207 Parametets are named application resources, for example, application preferences like
1208 integer, double, boolean or string values, pictures, font and color definitions, etc.
1209 Parameters are organized inside the resources files into the named groups - sections.
1210 Options are special kind of resoures which allow customizing resource files interpreting.
1211 For example, by default language settings are defined in the resource file in the
1212 section "language". It is possible to change this section name by setting "language"
1213 option to another value (see setOption()).
1215 Retrieving preferences values can be done by using one of value() methods, each returns
1216 \c true if the corresponding preference is found. Another way is to use integerValue(),
1217 doubleValue(), etc methods, which allow specifying default value which is used if the
1218 specified preference is not found. Removing of preferences or sections can be done using
1219 remove(const QString& sect) or remove(const QString& sect, const QString& name) methods.
1220 To add the preference or to change exiting preference value use setValue() methods family.
1221 Methods hasSection() and hasValue() can be used to check existence of section or
1222 preference (in the specified section). List of all sections can be retrieved with the
1223 sections() method, and list of all settings names in some specified section can be
1224 obtained with parameters() method.
1226 Pixmaps can be loaded with the loadPixmap() methods. If the specified pixmap is not found,
1227 the default one is returned. Default pixmap can be set by setDefaultPixmap().
1229 One of the key feature of the resources manager is support of application
1230 internationalization mechanism. Translation files for the specified language can be loaded
1231 with loadLanguage() method.
1235 \brief Constructs the resource manager.
1236 \param appName application name
1237 \param resVarTemplate resource environment variable pattern
1239 QtxResourceMgr::QtxResourceMgr( const QString& appName, const QString& resVarTemplate )
1240 : myAppName( appName ),
1241 myCheckExist( true ),
1242 myIsPixmapCached( true ),
1243 myHasUserValues( true ),
1244 myWorkingMode( AllowUserValues )
1246 QString envVar = !resVarTemplate.isEmpty() ? resVarTemplate : QString( "%1Resources" );
1247 if ( envVar.contains( "%1" ) )
1248 envVar = envVar.arg( appName );
1251 if ( ::getenv( envVar.toLatin1() ) )
1252 dirs = ::getenv( envVar.toLatin1() );
1254 QString dirsep = ";"; // for Windows: ";" is used as directories separator
1256 QString dirsep = "[:|;]"; // for Linux: both ":" and ";" can be used
1258 setDirList( dirs.split( QRegExp( dirsep ), QString::SkipEmptyParts ) );
1260 installFormat( new XmlFormat() );
1261 installFormat( new IniFormat() );
1263 setOption( "translators", QString( "%P_msg_%L.qm|%P_images.qm" ) );
1269 Destroy the resource manager and free allocated memory.
1271 QtxResourceMgr::~QtxResourceMgr()
1273 QStringList prefList = myTranslator.keys();
1274 for ( QStringList::ConstIterator it = prefList.begin(); it != prefList.end(); ++it )
1275 removeTranslators( *it );
1277 qDeleteAll( myResources );
1278 qDeleteAll( myFormats );
1282 \brief Get the application name.
1283 \return application name
1285 QString QtxResourceMgr::appName() const
1291 \brief Get the "check existance" flag
1293 If this flag is \c true then preference can be set (with setValue() method)
1294 only if it doesn't exist or if the value is changed.
1296 \return \c true if "check existance" flag is set
1298 bool QtxResourceMgr::checkExisting() const
1300 return myCheckExist;
1304 \brief Set the "check existance" flag.
1305 \param on new flag value
1307 void QtxResourceMgr::setCheckExisting( const bool on )
1313 \brief Get the resource directories list.
1315 Home user directory (where the user application configuration file is situated)
1316 is not included. This is that directories list defined by the application
1317 resources environment variable.
1319 \return list of directories names
1321 QStringList QtxResourceMgr::dirList() const
1327 \brief Initialise resources manager.
1329 Prepare the resources containers and load resources (if \a autoLoad is \c true).
1331 \param autoLoad if \c true (default) then all resources are loaded
1333 void QtxResourceMgr::initialize( const bool autoLoad ) const
1335 if ( !myResources.isEmpty() )
1338 QtxResourceMgr* that = (QtxResourceMgr*)this;
1340 if ( !userFileName( appName() ).isEmpty() )
1341 that->myResources.append( new Resources( that, userFileName( appName() ) ) );
1343 that->myHasUserValues = myResources.count() > 0;
1345 for ( QStringList::ConstIterator it = myDirList.begin(); it != myDirList.end(); ++it )
1347 QString path = Qtx::addSlash( *it ) + globalFileName( appName() );
1348 that->myResources.append( new Resources( that, path ) );
1356 \brief Get "cached pixmaps" option value.
1358 Resources manager allows possibility to cache loaded pixmaps that allow to
1359 improve application performance. This feature is turned on by default - all
1360 loaded pixmaps are stored in the internal map. Switching of this feature on/off
1361 can be done by setIsPixmapCached() method.
1363 \return \c true if pixmap cache is turned on
1364 \sa setIsPixmapCached()
1366 bool QtxResourceMgr::isPixmapCached() const
1368 return myIsPixmapCached;
1372 \brief Switch "cached pixmaps" option on/off.
1373 \param on enable pixmap cache if \c true and disable it if \c false
1374 \sa isPixmapCached()
1376 void QtxResourceMgr::setIsPixmapCached( const bool on )
1378 myIsPixmapCached = on;
1382 \brief Remove all resources from the resources manager.
1384 void QtxResourceMgr::clear()
1386 for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
1391 \brief Get current working mode.
1393 \return current working mode
1394 \sa setWorkingMode(), value(), hasValue(), hasSection(), setValue()
1396 QtxResourceMgr::WorkingMode QtxResourceMgr::workingMode() const
1398 return myWorkingMode;
1402 \brief Set resource manager's working mode.
1404 The resource manager can operate in the following working modes:
1405 * AllowUserValues : methods values(), hasValue(), hasSection() take into account user values (default)
1406 * IgnoreUserValues : methods values(), hasValue(), hasSection() do not take into account user values
1408 Note, that setValue() method always put the value to the user settings file.
1410 \param mode new working mode
1411 \sa workingMode(), value(), hasValue(), hasSection(), setValue()
1413 void QtxResourceMgr::setWorkingMode( WorkingMode mode )
1415 myWorkingMode = mode;
1419 \brief Get interger parameter value.
1420 \param sect section name
1421 \param name parameter name
1422 \param iVal parameter to return resulting integer value
1423 \return \c true if parameter is found and \c false if parameter is not found
1424 (in this case \a iVal value is undefined)
1426 bool QtxResourceMgr::value( const QString& sect, const QString& name, int& iVal ) const
1429 if ( !value( sect, name, val, true ) )
1433 iVal = val.toInt( &ok );
1439 \brief Get double parameter value.
1440 \param sect section name
1441 \param name parameter name
1442 \param dVal parameter to return resulting double value
1443 \return \c true if parameter is found and \c false if parameter is not found
1444 (in this case \a dVal value is undefined)
1446 bool QtxResourceMgr::value( const QString& sect, const QString& name, double& dVal ) const
1449 if ( !value( sect, name, val, true ) )
1453 dVal = val.toDouble( &ok );
1459 \brief Get boolean parameter value.
1460 \param sect section name
1461 \param name parameter name
1462 \param bVal parameter to return resulting boolean value
1463 \return \c true if parameter is found and \c false if parameter is not found
1464 (in this case \a bVal value is undefined)
1466 bool QtxResourceMgr::value( const QString& sect, const QString& name, bool& bVal ) const
1469 if ( !value( sect, name, val, true ) )
1472 static QMap<QString, bool> boolMap;
1473 if ( boolMap.isEmpty() )
1475 boolMap["true"] = boolMap["yes"] = boolMap["on"] = true;
1476 boolMap["false"] = boolMap["no"] = boolMap["off"] = false;
1479 val = val.toLower();
1480 bool res = boolMap.contains( val );
1482 bVal = boolMap[val];
1485 double num = val.toDouble( &res );
1494 \brief Get color parameter value.
1495 \param sect section name
1496 \param name parameter name
1497 \param cVal parameter to return resulting color value
1498 \return \c true if parameter is found and \c false if parameter is not found
1499 (in this case \a cVal value is undefined)
1501 bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cVal ) const
1504 if ( !value( sect, name, val, true ) )
1507 return Qtx::stringToColor( val, cVal );
1511 \brief Get font parameter value.
1512 \param sect section name
1513 \param name parameter name
1514 \param fVal parameter to return resulting font value
1515 \return \c true if parameter is found and \c false if parameter is not found
1516 (in this case \a fVal value is undefined)
1518 bool QtxResourceMgr::value( const QString& sect, const QString& name, QFont& fVal ) const
1521 if ( !value( sect, name, val, true ) )
1524 QStringList fontDescr = val.split( ",", QString::SkipEmptyParts );
1526 if ( fontDescr.count() < 2 )
1529 QString family = fontDescr[0];
1530 if ( family.isEmpty() )
1533 fVal = QFont( family );
1535 for ( int i = 1; i < (int)fontDescr.count(); i++ )
1537 QString curval = fontDescr[i].trimmed().toLower();
1538 if ( curval == QString( "bold" ) )
1539 fVal.setBold( true );
1540 else if ( curval == QString( "italic" ) )
1541 fVal.setItalic( true );
1542 else if ( curval == QString( "underline" ) )
1543 fVal.setUnderline( true );
1544 else if ( curval == QString( "shadow" ) || curval == QString( "overline" ) )
1545 fVal.setOverline( true );
1549 int ps = curval.toInt( &isOk );
1551 fVal.setPointSize( ps );
1559 \brief Get byte array parameter value.
1560 \param sect section name
1561 \param name parameter name
1562 \param baVal parameter to return resulting byte array value
1563 \return \c true if parameter is found and \c false if parameter is not found
1564 (in this case \a baVal value is undefined)
1566 bool QtxResourceMgr::value( const QString& sect, const QString& name, QByteArray& baVal ) const
1569 if ( !value( sect, name, val, true ) )
1573 QStringList lst = val.split( QRegExp( "[\\s|,]" ), QString::SkipEmptyParts );
1574 for ( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it )
1578 if ( str.startsWith( "#" ) )
1584 int num = str.toInt( &ok, base );
1585 if ( !ok || num < 0 || num > 255 )
1588 baVal.append( (char)num );
1590 return !baVal.isEmpty();
1594 \brief Get linear gradient parameter value.
1595 \param sect section name
1596 \param name parameter name
1597 \param gVal parameter to return resulting linear gradient value
1598 \return \c true if parameter is found and \c false if parameter is not found
1599 (in this case \a gVal value is undefined)
1601 bool QtxResourceMgr::value( const QString& sect, const QString& name, QLinearGradient& gVal ) const
1604 if ( !value( sect, name, val, true ) )
1607 return Qtx::stringToLinearGradient( val, gVal );
1611 \brief Get radial gradient parameter value.
1612 \param sect section name
1613 \param name parameter name
1614 \param gVal parameter to return resulting radial gradient value
1615 \return \c true if parameter is found and \c false if parameter is not found
1616 (in this case \a gVal value is undefined)
1618 bool QtxResourceMgr::value( const QString& sect, const QString& name, QRadialGradient& gVal ) const
1621 if ( !value( sect, name, val, true ) )
1624 return Qtx::stringToRadialGradient( val, gVal );
1628 \brief Get conical gradient parameter value.
1629 \param sect section name
1630 \param name parameter name
1631 \param gVal parameter to return resulting conical gradient value
1632 \return \c true if parameter is found and \c false if parameter is not found
1633 (in this case \a gVal value is undefined)
1635 bool QtxResourceMgr::value( const QString& sect, const QString& name, QConicalGradient& gVal ) const
1638 if ( !value( sect, name, val, true ) )
1641 return Qtx::stringToConicalGradient( val, gVal );
1645 \brief Get background parameter value.
1646 \param sect section name
1647 \param name parameter name
1648 \param bgVal parameter to return resulting background value
1649 \return \c true if parameter is found and \c false if parameter is not found
1650 (in this case \a bgVal value is undefined)
1652 bool QtxResourceMgr::value( const QString& sect, const QString& name, Qtx::BackgroundData& bgVal ) const
1655 if ( !value( sect, name, val, true ) )
1658 bgVal = Qtx::stringToBackground( val );
1659 return bgVal.isValid();
1663 \brief Get string parameter value (native format).
1664 \param sect section name
1665 \param name parameter name
1666 \param val parameter to return resulting byte array value
1667 \param subst if \c true perform environment variables substitution
1668 \return \c true if parameter is found and \c false if parameter is not found
1669 (in this case \a val value is undefined)
1671 bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& val, const bool subst ) const
1677 ResList::ConstIterator it = myResources.begin();
1678 if ( myHasUserValues && workingMode() == IgnoreUserValues )
1681 for ( ; it != myResources.end() && !ok; ++it )
1683 ok = (*it)->hasValue( sect, name );
1685 val = (*it)->value( sect, name, subst );
1692 \brief Get interger parameter value.
1694 If the specified parameter is not found or can not be converted to the integer value,
1695 the specified default value is returned instead.
1697 \param sect section name
1698 \param name parameter name
1699 \param def default value
1700 \return parameter value (or default value if parameter is not found)
1702 int QtxResourceMgr::integerValue( const QString& sect, const QString& name, const int def ) const
1705 if ( !value( sect, name, val ) )
1711 \brief Get double parameter value.
1713 If the specified parameter is not found or can not be converted to the double value,
1714 the specified default value is returned instead.
1716 \param sect section name
1717 \param name parameter name
1718 \param def default value
1719 \return parameter value (or default value if parameter is not found)
1721 double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, const double def ) const
1724 if ( !value( sect, name, val ) )
1730 \brief Get boolean parameter value.
1732 If the specified parameter is not found or can not be converted to the boolean value,
1733 the specified default value is returned instead.
1735 \param sect section name
1736 \param name parameter name
1737 \param def default value
1738 \return parameter value (or default value if parameter is not found)
1740 bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, const bool def ) const
1743 if ( !value( sect, name, val ) )
1749 \brief Get font parameter value.
1751 If the specified parameter is not found or can not be converted to the font value,
1752 the specified default value is returned instead.
1754 \param sect section name
1755 \param name parameter name
1756 \param def default value
1757 \return parameter value (or default value if parameter is not found)
1759 QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const QFont& def ) const
1762 if( !value( sect, name, font ) )
1768 \brief Get color parameter value.
1770 If the specified parameter is not found or can not be converted to the color value,
1771 the specified default value is returned instead.
1773 \param sect section name
1774 \param name parameter name
1775 \param def default value
1776 \return parameter value (or default value if parameter is not found)
1778 QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, const QColor& def ) const
1781 if ( !value( sect, name, val ) )
1787 \brief Get string parameter value.
1789 If the specified parameter is not found, the specified default value is returned instead.
1791 \param sect section name
1792 \param name parameter name
1793 \param def default value
1794 \return parameter value (or default value if parameter is not found)
1796 QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, const QString& def ) const
1799 if ( !value( sect, name, val ) )
1805 \brief Get byte array parameter value.
1807 If the specified parameter is not found, the specified default value is returned instead.
1809 \param sect section name
1810 \param name parameter name
1811 \param def default value
1812 \return parameter value (or default value if parameter is not found)
1814 QByteArray QtxResourceMgr::byteArrayValue( const QString& sect, const QString& name, const QByteArray& def ) const
1817 if ( !value( sect, name, val ) )
1823 \brief Get linear gradient parameter value.
1825 If the specified parameter is not found, the specified default value is returned instead.
1827 \param sect section name
1828 \param name parameter name
1829 \param def default value
1830 \return parameter value (or default value if parameter is not found)
1832 QLinearGradient QtxResourceMgr::linearGradientValue( const QString& sect, const QString& name, const QLinearGradient& def ) const
1834 QLinearGradient val;
1835 if ( !value( sect, name, val ) )
1841 \brief Get radial gradient parameter value.
1843 If the specified parameter is not found, the specified default value is returned instead.
1845 \param sect section name
1846 \param name parameter name
1847 \param def default value
1848 \return parameter value (or default value if parameter is not found)
1850 QRadialGradient QtxResourceMgr::radialGradientValue( const QString& sect, const QString& name, const QRadialGradient& def ) const
1852 QRadialGradient val;
1853 if ( !value( sect, name, val ) )
1859 \brief Get conical gradient parameter value.
1861 If the specified parameter is not found, the specified default value is returned instead.
1863 \param sect section name
1864 \param name parameter name
1865 \param def default value
1866 \return parameter value (or default value if parameter is not found)
1868 QConicalGradient QtxResourceMgr::conicalGradientValue( const QString& sect, const QString& name, const QConicalGradient& def ) const
1870 QConicalGradient val;
1871 if ( !value( sect, name, val ) )
1877 \brief Get background parameter value.
1879 If the specified parameter is not found, the specified default value is returned instead.
1881 \param sect section name
1882 \param name parameter name
1883 \param def default value
1884 \return parameter value (or default value if parameter is not found)
1886 Qtx::BackgroundData QtxResourceMgr::backgroundValue( const QString& sect, const QString& name, const Qtx::BackgroundData& def ) const
1888 Qtx::BackgroundData val;
1889 if ( !value( sect, name, val ) )
1895 \brief Check parameter existence.
1896 \param sect section name
1897 \param name parameter name
1898 \return \c true if parameter exists in specified section
1900 bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
1906 ResList::ConstIterator it = myResources.begin();
1907 if ( myHasUserValues && workingMode() == IgnoreUserValues )
1910 for ( ; it != myResources.end() && !ok; ++it )
1911 ok = (*it)->hasValue( sect, name );
1917 \brief Check section existence.
1918 \param sect section name
1919 \return \c true if section exists
1921 bool QtxResourceMgr::hasSection( const QString& sect ) const
1927 ResList::ConstIterator it = myResources.begin();
1928 if ( myHasUserValues && workingMode() == IgnoreUserValues )
1931 for ( ; it != myResources.end() && !ok; ++it )
1932 ok = (*it)->hasSection( sect );
1938 \brief Set integer parameter value.
1939 \param sect section name
1940 \param name parameter name
1941 \param val parameter value
1943 void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val )
1946 if ( checkExisting() && value( sect, name, res ) && res == val )
1949 setResource( sect, name, QString::number( val ) );
1953 \brief Set double parameter value.
1954 \param sect section name
1955 \param name parameter name
1956 \param val parameter value
1958 void QtxResourceMgr::setValue( const QString& sect, const QString& name, double val )
1961 if ( checkExisting() && value( sect, name, res ) && res == val )
1964 setResource( sect, name, QString::number( val, 'g', 12 ) );
1968 \brief Set boolean parameter value.
1969 \param sect section name
1970 \param name parameter name
1971 \param val parameter value
1973 void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool val )
1976 if ( checkExisting() && value( sect, name, res ) && res == val )
1979 setResource( sect, name, QString( val ? "true" : "false" ) );
1983 \brief Set color parameter value.
1984 \param sect section name
1985 \param name parameter name
1986 \param val parameter value
1988 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QColor& val )
1991 if ( checkExisting() && value( sect, name, res ) && res == val )
1994 setResource( sect, name, Qtx::colorToString( val ) );
1998 \brief Set font parameter value.
1999 \param sect section name
2000 \param name parameter name
2001 \param val parameter value
2003 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QFont& val )
2006 if ( checkExisting() && value( sect, name, res ) && res == val )
2009 QStringList fontDescr;
2010 fontDescr.append( val.family() );
2012 fontDescr.append( "Bold" );
2014 fontDescr.append( "Italic" );
2015 if ( val.underline() )
2016 fontDescr.append( "Underline" );
2017 if ( val.overline() )
2018 fontDescr.append( "Overline" );
2019 fontDescr.append( QString( "%1" ).arg( val.pointSize() ) );
2021 setResource( sect, name, fontDescr.join( "," ) );
2025 \brief Set string parameter value.
2026 \param sect section name
2027 \param name parameter name
2028 \param val parameter value
2030 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QString& val )
2033 if ( checkExisting() && value( sect, name, res ) && res == val )
2036 setResource( sect, name, val );
2040 \brief Set byte array 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 QByteArray& val )
2048 if ( checkExisting() && value( sect, name, res ) && res == val )
2053 for ( int i = 0; i < val.size(); i++ )
2055 ::sprintf( buf, "#%02X", (unsigned char)val.at( i ) );
2056 lst.append( QString( buf ) );
2058 setResource( sect, name, lst.join( " " ) );
2062 \brief Set linear gradient parameter value.
2063 \param sect section name
2064 \param name parameter name
2065 \param val parameter value
2067 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QLinearGradient& val )
2069 QLinearGradient res;
2070 if ( checkExisting() && value( sect, name, res ) && res == val )
2073 setResource( sect, name, Qtx::gradientToString( val ) );
2077 \brief Set radial gradient parameter value.
2078 \param sect section name
2079 \param name parameter name
2080 \param val parameter value
2082 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QRadialGradient& val )
2084 QRadialGradient res;
2085 if ( checkExisting() && value( sect, name, res ) && res == val )
2088 setResource( sect, name, Qtx::gradientToString( val ) );
2092 \brief Set conical gradient parameter value.
2093 \param sect section name
2094 \param name parameter name
2095 \param val parameter value
2097 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QConicalGradient& val )
2099 QConicalGradient res;
2100 if ( checkExisting() && value( sect, name, res ) && res == val )
2103 setResource( sect, name, Qtx::gradientToString( val ) );
2107 \brief Set background parameter value.
2108 \param sect section name
2109 \param name parameter name
2110 \param val parameter value
2112 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const Qtx::BackgroundData& val )
2114 Qtx::BackgroundData res;
2115 if ( checkExisting() && value( sect, name, res ) && res == val )
2118 setResource( sect, name, Qtx::backgroundToString( val ) );
2122 \brief Remove resources section.
2123 \param sect section name
2125 void QtxResourceMgr::remove( const QString& sect )
2129 for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2130 (*it)->removeSection( sect );
2134 \brief Remove the specified parameter.
2135 \param sect section name
2136 \param name parameter name
2138 void QtxResourceMgr::remove( const QString& sect, const QString& name )
2142 for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2143 (*it)->removeValue( sect, name );
2147 \brief Get current configuration files format.
2148 \return configuration files format name
2150 QString QtxResourceMgr::currentFormat() const
2153 if ( !myFormats.isEmpty() )
2154 fmt = myFormats[0]->format();
2159 \brief Set current configuration files format.
2160 \param fmt configuration files format name
2162 void QtxResourceMgr::setCurrentFormat( const QString& fmt )
2164 Format* form = format( fmt );
2168 myFormats.removeAll( form );
2169 myFormats.prepend( form );
2171 if ( myResources.isEmpty() )
2174 ResList::Iterator resIt = myResources.begin();
2175 if ( myResources.count() > myDirList.count() && resIt != myResources.end() )
2177 (*resIt)->setFile( userFileName( appName() ) );
2181 for ( QStringList::ConstIterator it = myDirList.begin(); it != myDirList.end() && resIt != myResources.end(); ++it, ++resIt )
2182 (*resIt)->setFile( Qtx::addSlash( *it ) + globalFileName( appName() ) );
2186 \brief Get configuration files format by specified format name.
2187 \param fmt configuration files format name
2188 \return format object or 0 if format is not defined
2190 QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
2193 for ( FormatList::ConstIterator it = myFormats.begin(); it != myFormats.end() && !form; ++it )
2195 if ( (*it)->format() == fmt )
2203 \brief Install configuration files format.
2205 Added format becomes current.
2207 \param form format object to be installed
2209 void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
2211 if ( !myFormats.contains( form ) )
2212 myFormats.prepend( form );
2216 \brief Remove configuration files format.
2217 \param form format object to be uninstalled
2219 void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
2221 myFormats.removeAll( form );
2225 \brief Get resource format options names.
2226 \return list of options names
2228 QStringList QtxResourceMgr::options() const
2230 return myOptions.keys();
2234 \brief Get the string value of the specified resources format option.
2236 If option does not exist, null QString is returned.
2238 \param opt option name
2239 \return option value
2240 \sa setOption(), options()
2242 QString QtxResourceMgr::option( const QString& opt ) const
2245 if ( myOptions.contains( opt ) )
2246 val = myOptions[opt];
2251 \brief Set the string value of the specified resources format option.
2252 \param opt option name
2253 \param val option value
2254 \sa option(), options()
2256 void QtxResourceMgr::setOption( const QString& opt, const QString& val )
2258 myOptions.insert( opt, val );
2262 \brief Load all resources from all resource files (global and user).
2263 \return \c true on success and \c false on error
2266 bool QtxResourceMgr::load()
2268 initialize( false );
2270 Format* fmt = format( currentFormat() );
2275 for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2276 res = fmt->load( *it ) && res;
2282 \brief Import resources from specified resource file.
2283 \param fname resources file name
2284 \return \c true on success and \c false on error
2286 bool QtxResourceMgr::import( const QString& fname )
2288 Format* fmt = format( currentFormat() );
2292 if ( myResources.isEmpty() || !myHasUserValues )
2295 Resources* r = myResources[0];
2299 QString old = r->file();
2300 r->setFile( fname );
2301 bool res = fmt->load( r );
2307 \brief Save all resources to the user resource files.
2308 \return \c true on success and \c false on error
2310 bool QtxResourceMgr::save()
2312 initialize( false );
2314 Format* fmt = format( currentFormat() );
2318 if ( myResources.isEmpty() || !myHasUserValues )
2321 bool result = fmt->save( myResources[0] );
2329 \brief Get all sections names.
2330 \return list of section names
2332 QStringList QtxResourceMgr::sections() const
2336 QMap<QString, int> map;
2338 ResList::ConstIterator it = myResources.begin();
2339 if ( myHasUserValues && workingMode() == IgnoreUserValues )
2342 for ( ; it != myResources.end(); ++it )
2344 QStringList lst = (*it)->sections();
2345 for ( QStringList::ConstIterator itr = lst.begin(); itr != lst.end(); ++itr )
2346 map.insert( *itr, 0 );
2353 \brief Get all sections names matching specified regular expression.
2354 \param re searched regular expression
2355 \return list of sections names
2357 QStringList QtxResourceMgr::sections(const QRegExp& re) const
2359 return sections().filter( re );
2363 \brief Get all sections names with the prefix specified by passed
2364 list of parent sections names.
2366 Sub-sections are separated inside the section name by the sections
2367 separator token, for example "splash:color:label".
2369 \param names parent sub-sections names
2370 \return list of sections names
2372 QStringList QtxResourceMgr::sections(const QStringList& names) const
2374 QStringList nm = names;
2376 QRegExp re( QString( "^%1$" ).arg( nm.join( sectionsToken() ) ) );
2377 return sections( re );
2381 \brief Get list of sub-sections names for the specified parent section name.
2383 Sub-sections are separated inside the section name by the sections
2384 separator token, for example "splash:color:label".
2386 \param section parent sub-section name
2387 \param full if \c true return full names of child sub-sections, if \c false,
2388 return only top-level sub-sections names
2389 \return list of sub-sections names
2391 QStringList QtxResourceMgr::subSections(const QString& section, const bool full) const
2393 QStringList names = sections( QStringList() << section );
2394 QMutableListIterator<QString> it( names );
2395 while ( it.hasNext() ) {
2396 QString name = it.next().mid( section.size() + 1 ).trimmed();
2397 if ( name.isEmpty() ) {
2401 if ( !full ) name = name.split( sectionsToken() ).first();
2402 it.setValue( name );
2404 names.removeDuplicates();
2410 \brief Get all parameters name in specified section.
2411 \param sec section name
2412 \return list of settings names
2414 QStringList QtxResourceMgr::parameters( const QString& sec ) const
2418 #if defined(QTX_NO_INDEXED_MAP)
2419 typedef QMap<QString, int> PMap;
2421 typedef IMap<QString, int> PMap;
2425 Resources* ur = !myResources.isEmpty() && workingMode() == IgnoreUserValues ? myResources[0] : 0;
2427 QListIterator<Resources*> it( myResources );
2429 while ( it.hasPrevious() )
2431 Resources* r = it.previous();
2432 if ( r == ur ) break;
2433 QStringList lst = r->parameters( sec );
2434 for ( QStringList::ConstIterator itr = lst.begin(); itr != lst.end(); ++itr )
2435 #if defined(QTX_NO_INDEXED_MAP)
2436 if ( !pmap.contains( *itr ) ) pmap.insert( *itr, 0 );
2438 pmap.insert( *itr, 0, false );
2446 \brief Get all parameters name in specified
2447 list of sub-sections names.
2449 Sub-sections are separated inside the section name by the sections
2450 separator token, for example "splash:color:label".
2452 \param names parent sub-sections names
2453 \return list of settings names
2455 QStringList QtxResourceMgr::parameters( const QStringList& names ) const
2457 return parameters( names.join( sectionsToken() ) );
2461 \brief Get absolute path to the file which name is defined by the parameter.
2463 The file name is defined by \a name argument, while directory name is retrieved
2464 from resources parameter \a prefix of section \a sec. Both directory and file name
2465 can be relative. If the directory is relative, it is calculated from the initial
2466 resources file name. Directory parameter can contain environment
2467 variables, which are substituted automatically.
2469 \param sec section name
2470 \param prefix parameter containing directory name
2471 \param name file name
2472 \return absolute file path or null QString if file does not exist
2474 QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const QString& name ) const
2478 ResList::ConstIterator it = myResources.begin();
2479 if ( myHasUserValues && workingMode() == IgnoreUserValues )
2482 for ( ; it != myResources.end() && res.isEmpty(); ++it )
2483 res = (*it)->path( sect, prefix, name );
2488 \brief Get application resources section name.
2490 By default, application resources section name is "resources" but
2491 it can be changed by setting the "res_section_name" resources manager option.
2493 \return section corresponding to the resources directories
2494 \sa option(), setOption()
2496 QString QtxResourceMgr::resSection() const
2498 QString res = option( "res_section_name" );
2499 if ( res.isEmpty() )
2500 res = QString( "resources" );
2505 \brief Get application language section name.
2507 By default, application language section name is "language" but
2508 it can be changed by setting the "lang_section_name" resources manager option.
2510 \return section corresponding to the application language settings
2511 \sa option(), setOption()
2513 QString QtxResourceMgr::langSection() const
2515 QString res = option( "lang_section_name" );
2516 if ( res.isEmpty() )
2517 res = QString( "language" );
2522 \brief Get sections separator token.
2524 By default, sections separator token is colon symbol ":" but
2525 it can be changed by setting the "section_token" resources manager option.
2527 \return string corresponding to the current section separator token
2528 \sa option(), setOption()
2530 QString QtxResourceMgr::sectionsToken() const
2532 QString res = option( "section_token" );
2533 if ( res.isEmpty() )
2534 res = QString( ":" );
2539 \brief Get default pixmap.
2541 Default pixmap is used when requested pixmap resource is not found.
2543 \return default pixmap
2544 \sa setDefaultPixmap(), loadPixmap()
2546 QPixmap QtxResourceMgr::defaultPixmap()
2550 myDefaultPix = new QPixmap( pixmap_not_found_xpm );
2552 if ( myDefaultPix && !myDefaultPix->isNull() )
2553 res = *myDefaultPix;
2558 \brief Set default pixmap.
2560 Default pixmap is used when requested pixmap resource is not found.
2562 \param pix default pixmap
2563 \sa defaultPixmap(), loadPixmap()
2565 void QtxResourceMgr::setDefaultPixmap( const QPixmap& pix )
2567 delete myDefaultPix;
2571 myDefaultPix = new QPixmap( pix );
2575 \brief Load pixmap resource.
2576 \param prefix parameter which refers to the resources directory (directories)
2577 \param name pixmap file name
2578 \return pixmap loaded from the file
2579 \sa defaultPixmap(), setDefaultPixmap()
2581 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name ) const
2583 return loadPixmap( prefix, name, true );
2587 \brief Load pixmap resource.
2589 \param prefix parameter which refers to the resources directory (directories)
2590 \param name pixmap file name
2591 \param useDef if \c false, default pixmap is not returned if resource is not found,
2592 in this case null pixmap is returned instead
2593 \return pixmap loaded from the file
2594 \sa defaultPixmap(), setDefaultPixmap()
2596 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const bool useDef ) const
2598 return loadPixmap( prefix, name, useDef ? defaultPixmap() : QPixmap() );
2602 \brief Load pixmap resource.
2604 \param prefix parameter which refers to the resources directory (directories)
2605 \param name pixmap file name
2606 \param defPix default which should be used if the resource file doesn't exist
2607 \return pixmap loaded from the file
2608 \sa defaultPixmap(), setDefaultPixmap()
2610 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const QPixmap& defPix ) const
2616 ResList::ConstIterator it = myResources.begin();
2617 if ( myHasUserValues && workingMode() == IgnoreUserValues )
2620 for ( ; it != myResources.end() && pix.isNull(); ++it )
2621 pix = (*it)->loadPixmap( resSection(), prefix, name );
2628 \brief Load translation files according to the specified language.
2630 Names of the translation files are calculated according to the pattern specified
2631 by the "translators" option (this option is read from the section "language" of resources files).
2632 By default, "%P_msg_%L.qm" pattern is used.
2633 Keywords \%A, \%P, \%L in the pattern are substituted by the application name, prefix and language name
2635 For example, for prefix "SUIT" and language "en", all translation files "SUIT_msg_en.qm" are searched and
2638 If prefix is empty or null string, all translation files specified in the "resources" section of resources
2639 files are loaded (actually, the section is retrieved from resSection() method).
2640 If language is not specified, it is retrieved from the langSection() method, and if the latest is also empty,
2641 by default "en" (English) language is used.
2642 By default, settings from the user preferences file are also loaded (if user resource file is valid,
2643 see userFileName()). To avoid loading user settings, pass \c false as first parameter.
2645 \param pref parameter which defines translation context (for example, package name)
2646 \param l language name
2648 \sa resSection(), langSection(), loadTranslators()
2650 void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
2654 QMap<QChar, QString> substMap;
2655 substMap.insert( 'A', appName() );
2658 if ( lang.isEmpty() )
2659 value( langSection(), "language", lang );
2661 if ( lang.isEmpty() )
2663 lang = QString( "en" );
2664 qWarning() << "QtxResourceMgr: Language not specified. Assumed:" << lang;
2667 substMap.insert( 'L', lang );
2670 if ( value( langSection(), "translators", trs, false ) && !trs.isEmpty() )
2672 QStringList translators = option( "translators" ).split( "|", QString::SkipEmptyParts );
2673 QStringList newTranslators = trs.split( "|", QString::SkipEmptyParts );
2674 for ( int i = 0; i < (int)newTranslators.count(); i++ )
2676 if ( translators.indexOf( newTranslators[i] ) < 0 )
2677 translators += newTranslators[i];
2679 setOption( "translators", translators.join( "|" ) );
2682 QStringList trList = option( "translators" ).split( "|", QString::SkipEmptyParts );
2683 if ( trList.isEmpty() )
2685 trList.append( "%P_msg_%L.qm" );
2686 qWarning() << "QtxResourceMgr: Translators not defined. Assumed:" << trList[0];
2689 QStringList prefixList;
2690 if ( !pref.isEmpty() )
2691 prefixList.append( pref );
2693 prefixList = parameters( resSection() );
2695 if ( pref.isEmpty() && lang != "en" ) {
2696 // load Qt resources
2697 QString qt_translations = QLibraryInfo::location( QLibraryInfo::TranslationsPath );
2698 QString qt_dir_trpath;
2699 if ( ::getenv( "QTDIR" ) )
2700 qt_dir_trpath = QString( ::getenv( "QTDIR" ) );
2701 if ( !qt_dir_trpath.isEmpty() )
2702 qt_dir_trpath = QDir( qt_dir_trpath ).absoluteFilePath( "translations" );
2704 QTranslator* trans = new QtxTranslator( 0 );
2705 if ( trans->load( QString("qt_%1").arg( lang ), qt_translations ) || trans->load( QString("qt_%1").arg( lang ), qt_dir_trpath ) )
2706 QApplication::instance()->installTranslator( trans );
2709 for ( QStringList::ConstIterator iter = prefixList.begin(); iter != prefixList.end(); ++iter )
2711 QString prefix = *iter;
2712 substMap.insert( 'P', prefix );
2715 for ( QStringList::ConstIterator it = trList.begin(); it != trList.end(); ++it )
2716 trs.append( substMacro( *it, substMap ).trimmed() );
2718 loadTranslators( prefix, trs );
2723 \brief Load translation files for the specified translation context.
2724 \param prefix parameter which defines translation context (for example, package name)
2725 \param translators list of translation files
2728 void QtxResourceMgr::loadTranslators( const QString& prefix, const QStringList& translators )
2734 ResList::ConstIterator iter = myResources.begin();
2735 if ( myHasUserValues && workingMode() == IgnoreUserValues )
2738 for ( ; iter != myResources.end(); ++iter )
2739 lst.prepend( *iter );
2741 QTranslator* trans = 0;
2743 for ( ResList::Iterator it = lst.begin(); it != lst.end(); ++it )
2745 for ( QStringList::ConstIterator itr = translators.begin(); itr != translators.end(); ++itr )
2747 trans = (*it)->loadTranslator( resSection(), prefix, *itr );
2750 if ( !myTranslator[prefix].contains( trans ) )
2751 myTranslator[prefix].append( trans );
2752 QApplication::instance()->installTranslator( trans );
2759 \brief Load translation file.
2760 \param prefix parameter which defines translation context (for example, package name)
2761 \param name translator file name
2762 \sa loadLanguage(), loadTranslators()
2764 void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name )
2768 QTranslator* trans = 0;
2770 Resources* ur = !myResources.isEmpty() && workingMode() == IgnoreUserValues ? myResources[0] : 0;
2772 QListIterator<Resources*> it( myResources );
2774 while ( it.hasPrevious() )
2776 Resources* r = it.previous();
2777 if ( r == ur ) break;
2779 trans = r->loadTranslator( resSection(), prefix, name );
2782 if ( !myTranslator[prefix].contains( trans ) )
2783 myTranslator[prefix].append( trans );
2784 QApplication::instance()->installTranslator( trans );
2790 \brief Remove all translators corresponding to the specified translation context.
2791 \param prefix parameter which defines translation context (for example, package name)
2793 void QtxResourceMgr::removeTranslators( const QString& prefix )
2795 if ( !myTranslator.contains( prefix ) )
2798 for ( TransList::Iterator it = myTranslator[prefix].begin(); it != myTranslator[prefix].end(); ++it )
2800 QApplication::instance()->removeTranslator( *it );
2804 myTranslator.remove( prefix );
2808 \brief Move all translators corresponding to the specified translation context
2809 to the top of translators stack (increase their priority).
2810 \param prefix parameter which defines translation context (for example, package name)
2812 void QtxResourceMgr::raiseTranslators( const QString& prefix )
2814 if ( !myTranslator.contains( prefix ) )
2817 for ( TransList::Iterator it = myTranslator[prefix].begin(); it != myTranslator[prefix].end(); ++it )
2819 QApplication::instance()->removeTranslator( *it );
2820 QApplication::instance()->installTranslator( *it );
2825 \brief Copy all parameters to the user resources in order to
2826 saved them lately in the user home folder.
2828 void QtxResourceMgr::refresh()
2830 QStringList sl = sections();
2831 for ( QStringList::ConstIterator it = sl.begin(); it != sl.end(); ++it )
2833 QStringList pl = parameters( *it );
2834 for ( QStringList::ConstIterator itr = pl.begin(); itr != pl.end(); ++itr )
2835 setResource( *it, *itr, stringValue( *it, *itr ) );
2840 \brief Set the resource directories (where global confguration files are searched).
2842 This function also clears all currently set resources.
2844 \param dl directories list
2846 void QtxResourceMgr::setDirList( const QStringList& dl )
2849 for ( ResList::Iterator it = myResources.begin(); it != myResources.end(); ++it )
2852 myResources.clear();
2856 \brief Set parameter value.
2857 \param sect section name
2858 \param name parameter name
2859 \param val parameter value
2861 void QtxResourceMgr::setResource( const QString& sect, const QString& name, const QString& val )
2865 if ( !myResources.isEmpty() && myHasUserValues )
2866 myResources.first()->setValue( sect, name, val );
2870 \brief Get user configuration file name.
2872 This method can be redefined in the successor class to customize the user configuration file name.
2873 User configuration file is always situated in the user's home directory. By default .<appName>rc
2874 file is used on Linux (e.g. .MyApprc) and <appName>.<format> under Windows (e.g. MyApp.xml).
2876 Parameter \a for_load (not used in default implementation) specifies the usage mode, i.e. if
2877 user configuration file is opened for reading or writing. This allows customizing a way of application
2878 resources initializing (for example, if the user configuraion file includes version number and there is
2879 no file corresponding to this version in the user's home directory, it could be good idea to try
2880 the configuration file from the previous versions of the application).
2882 \param appName application name
2883 \param for_load boolean flag indicating that file is opened for loading or saving (not used in default implementation)
2884 \return user configuration file name
2885 \sa globalFileName()
2887 QString QtxResourceMgr::userFileName( const QString& appName, const bool /*for_load*/ ) const
2890 QString pathName = QDir::homePath();
2891 QString cfgAppName = QApplication::applicationName();
2892 if ( !cfgAppName.isEmpty() )
2893 pathName = Qtx::addSlash( Qtx::addSlash( pathName ) + QString( ".config" ) ) + cfgAppName;
2896 fileName = QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
2898 fileName = QString( "%1rc" ).arg( appName );
2899 // VSR 24/09/2012: issue 0021781: do not prepend filename with "."
2900 // when user file is stored in ~/.config/<appname> directory
2901 if ( cfgAppName.isEmpty() )
2902 fileName.prepend( "." );
2905 if ( !fileName.isEmpty() )
2906 pathName = Qtx::addSlash( pathName ) + fileName;
2912 \brief Get global configuration file name.
2914 This method can be redefined in the successor class to customize the global configuration file name.
2915 Global configuration files are searched in the directories specified by the application resources
2916 environment variable (e.g. MyAppResources). By default <appName>.<format> file name is used
2919 \param appName application name
2920 \return global configuration file name
2923 QString QtxResourceMgr::globalFileName( const QString& appName ) const
2925 return QString( "%1.%2" ).arg( appName ).arg( currentFormat() );
2929 \brief This function is called after user configuration file is saved.
2930 Can be redefined in the successor classes, default implementation does nothing.
2932 void QtxResourceMgr::saved()
2937 \brief Perform substitution of the patterns like \%A, \%B, etc by values from the map.
2939 Used by loadLanguage().
2941 \param src sring to be processed
2942 \param substMap map of values for replacing
2943 \return processed string
2945 QString QtxResourceMgr::substMacro( const QString& src, const QMap<QChar, QString>& substMap ) const
2949 QRegExp rx( "%[A-Za-z%]" );
2952 while ( ( idx = rx.indexIn( trg, idx ) ) >= 0 )
2954 QChar spec = trg.at( idx + 1 );
2958 else if ( substMap.contains( spec ) )
2959 subst = substMap[spec];
2961 if ( !subst.isEmpty() )
2963 trg.replace( idx, rx.matchedLength(), subst );
2964 idx += subst.length();
2967 idx += rx.matchedLength();