Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

config.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000,2004 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 #include <qdir.h>
00022 #include <qmessagebox.h>
00023 #if QT_VERSION <= 230 && defined(QT_NO_CODECS)
00024 #include <qtextcodec.h>
00025 #endif
00026 #include <qtextstream.h>
00027 
00028 #include <sys/stat.h>
00029 #include <sys/types.h>
00030 #include <sys/time.h>
00031 #include <fcntl.h>
00032 #include <stdlib.h>
00033 #include <time.h>
00034 #include <unistd.h>
00035 
00036 #define QTOPIA_INTERNAL_LANGLIST
00037 #include "config.h"
00038 #include "global.h"
00039 #include <qtopia/qpeapplication.h>
00040 
00041 
00042 /*
00043  * Internal Class
00044  */
00045 class ConfigPrivate {
00046 public:
00047     ConfigPrivate() : multilang(FALSE) {}
00048     ConfigPrivate(const ConfigPrivate& o) :
00049         trfile(o.trfile),
00050         trcontext(o.trcontext),
00051         multilang(o.multilang)
00052     {}
00053     ConfigPrivate& operator=(const ConfigPrivate& o)
00054     {
00055         trfile = o.trfile;
00056         trcontext = o.trcontext;
00057         multilang = o.multilang;
00058         return *this;
00059     }
00060 
00061     QString trfile;
00062     QCString trcontext;
00063     bool multilang;
00064 };
00065 
00068 
00069 #ifndef Q_OS_WIN32
00070 
00071 //#define DEBUG_CONFIG_CACHE
00072 class ConfigData
00073 {
00074 public:
00075     ConfigData() {}
00076     ConfigData( const ConfigGroupMap& cf, const ConfigPrivate& pri,
00077                 struct stat sbuf )
00078         : cfg( cf ), priv( pri ), mtime( sbuf.st_mtime ),
00079           size( sbuf.st_size )
00080         {
00081             gettimeofday(&used, 0 );
00082         }
00083 
00084     ConfigGroupMap cfg;
00085     ConfigPrivate priv; // Owned by this object
00086     time_t mtime;
00087     unsigned int size;
00088     struct timeval used;
00089 };
00090 
00091 
00092 class ConfigCache : public QObject {
00093 public:
00094     static ConfigCache* instance();
00095 
00096     void insert( const QString& fileName, const ConfigGroupMap& cfg,
00097                  const ConfigPrivate *priv );
00098     bool find(const QString& fileName, ConfigGroupMap& cfg,
00099               ConfigPrivate** priv );
00100 protected:
00101     void timerEvent( QTimerEvent* );
00102 
00103 private:
00104     ConfigCache();
00105     void remove( const QString& fileName );
00106     void removeLru();
00107 
00108 private:
00109     QMap<QString, ConfigData> m_cached;
00110     unsigned int m_totalSize;
00111     int m_tid;
00112 private:
00113     static ConfigCache* m_inst;
00114     static const unsigned int CONFIG_CACHE_SIZE = 8192;
00115     static const unsigned int CONFIG_CACHE_TIMEOUT = 1000;
00116 };
00117 
00118 ConfigCache* ConfigCache::m_inst = 0;
00119 /*
00120  * get destroyed when qApp gets destroyed
00121  */
00122 ConfigCache::ConfigCache() : QObject( qApp ), m_totalSize( 0 ), m_tid( 0 ) {}
00123 ConfigCache* ConfigCache::instance() {
00124     if ( !m_inst )
00125         m_inst = new ConfigCache();
00126 
00127     return m_inst;
00128 }
00129 
00130 void ConfigCache::remove( const QString& fileName ) {
00131     QMap<QString, ConfigData>::Iterator it = m_cached.find( fileName );
00132 
00133     if ( it == m_cached.end() )
00134         return;
00135 
00136     m_totalSize -= (*it).size;
00137     m_cached.remove( it );
00138 }
00139 
00140 void ConfigCache::removeLru() {
00141     QMap<QString, ConfigData>::Iterator it  = m_cached.begin();
00142     QMap<QString, ConfigData>::Iterator lru = it;
00143     ++it;
00144     for (; it != m_cached.end(); ++it)
00145         if ((*it).used.tv_sec < (*lru).used.tv_sec ||
00146             ((*it).used.tv_sec == (*lru).used.tv_sec &&
00147              (*it).used.tv_usec < (*lru).used.tv_usec))
00148             lru = it;
00149 
00150     m_totalSize -= (*lru).size;
00151     m_cached.remove(lru);
00152 }
00153 
00154 void ConfigCache::timerEvent( QTimerEvent* ) {
00155     while ( m_totalSize > CONFIG_CACHE_SIZE )
00156         removeLru();
00157 
00158     killTimer(m_tid);
00159     m_tid = 0;
00160 }
00161 
00162 void ConfigCache::insert( const QString& fileName, const ConfigGroupMap& cfg,
00163                           const ConfigPrivate* _priv ) {
00164 
00165 
00166     struct stat sbuf;
00167     ::stat( QFile::encodeName(fileName), &sbuf );
00168     if ( static_cast<unsigned int>(sbuf.st_size) >= CONFIG_CACHE_SIZE>>1)
00169         return;
00170 
00171     /*
00172      * remove the old version and use the new one
00173      */
00174     ConfigPrivate priv = _priv ? *_priv : ConfigPrivate();
00175     ConfigData data( cfg, priv, sbuf );
00176     m_totalSize += data.size;
00177 
00178     remove( fileName );
00179     m_cached.insert( fileName, data );
00180 
00181     /*
00182      * we've overcommited allocation, let us clean up
00183      * soon
00184      */
00185     if ( m_totalSize >= CONFIG_CACHE_SIZE )
00186         if ( !m_tid )
00187             m_tid = startTimer(CONFIG_CACHE_TIMEOUT);
00188 }
00189 
00190 bool ConfigCache::find( const QString& fileName, ConfigGroupMap& cfg,
00191                         ConfigPrivate **ppriv ) {
00192     QMap<QString, ConfigData>::Iterator it = m_cached.find(fileName);
00193     if (it != m_cached.end()) {
00194         ConfigData &data = *it;
00195         struct stat sbuf;
00196         ::stat(QFile::encodeName( fileName ), &sbuf);
00197 
00198         if (data.mtime == sbuf.st_mtime && (int)data.size == sbuf.st_size) {
00199             cfg = data.cfg;
00200 
00201             /*
00202              * null pointer
00203              */
00204             if ( *ppriv == 0 )
00205                 *ppriv = new ConfigPrivate( data.priv );
00206             **ppriv = data.priv;
00207             gettimeofday(&data.used, 0);
00208 
00209             return true;
00210         }
00211     }
00212 
00213     return false;
00214 }
00215 
00216 #endif
00217 
00218 
00222 QString Config::configFilename(const QString& name, Domain d)
00223 {
00224     switch (d) {
00225     case File:
00226         return name;
00227     case User: {
00228         QDir dir = (QString(getenv("HOME")) + "/Settings");
00229         if ( !dir.exists() )
00230             mkdir(dir.path().local8Bit(),0700);
00231         return dir.path() + "/" + name + ".conf";
00232     }
00233     }
00234     return name;
00235 }
00236 
00237 /* This cannot be made public because of binary compat issues */
00238 void Config::read( QTextStream &s )
00239 {
00240 #if QT_VERSION <= 230 && defined(QT_NO_CODECS)
00241     // The below should work, but doesn't in Qt 2.3.0
00242     s.setCodec( QTextCodec::codecForMib( 106 ) );
00243 #else
00244     s.setEncoding( QTextStream::UnicodeUTF8 );
00245 #endif
00246 
00247     QStringList list = QStringList::split('\n', s.read() );
00248 
00249     for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
00250         if ( !parse( *it ) ) {
00251             git = groups.end();
00252             return;
00253         }
00254     }
00255 }
00256 
00293 Config::Config( const QString &name, Domain domain )
00294     : filename( configFilename(name,domain) )
00295 {
00296     git = groups.end();
00297     d = 0;
00298     read();
00299 }
00300 
00301 
00302 // Sharp ROM compatibility
00303 Config::Config ( const QString &name, bool what )
00304         : filename( configFilename(name,what ? User : File) )
00305 {
00306     git = groups.end();
00307     d = 0;
00308     read();
00309 }
00310 
00314 Config::~Config()
00315 {
00316     if ( changed )
00317         write();
00318 
00319     delete d;
00320 }
00321 
00325 bool Config::hasKey( const QString &key ) const
00326 {
00327     if ( groups.end() == git )
00328         return FALSE;
00329     ConfigGroup::ConstIterator it = ( *git ).find( key );
00330     if ( it == ( *git ).end() ) {
00331         if ( d && !d->trcontext.isNull() ) {
00332             it = ( *git ).find( key + "[]" );
00333         } else if ( d && d->multilang ) {
00334             it = ( *git ).find( key + "["+lang+"]" );
00335             if ( it == ( *git ).end() && !glang.isEmpty() )
00336                 it = ( *git ).find( key + "["+glang+"]" );
00337         }
00338     }
00339     return it != ( *git ).end();
00340 }
00341 
00351 void Config::setGroup( const QString &gname )
00352 {
00353     QMap< QString, ConfigGroup>::Iterator it = groups.find( gname );
00354     if ( it == groups.end() ) {
00355         git = groups.insert( gname, ConfigGroup() );
00356         changed = TRUE;
00357         return;
00358     }
00359     git = it;
00360 }
00361 
00367 void Config::writeEntry( const QString &key, const char* value )
00368 {
00369     writeEntry(key,QString(value));
00370 }
00371 
00377 void Config::writeEntry( const QString &key, const QString &value )
00378 {
00379     if ( git == groups.end() ) {
00380         qWarning( "no group set" );
00381         return;
00382     }
00383     if ( (*git)[key] != value ) {
00384         ( *git ).insert( key, value );
00385         changed = TRUE;
00386     }
00387 }
00388 
00389 /*
00390   Note that the degree of protection offered by the encryption here is
00391   only sufficient to avoid the most casual observation of the configuration
00392   files. People with access to the files can write down the contents and
00393   decrypt it using this source code.
00394 
00395   Conceivably, and at some burden to the user, this encryption could
00396   be improved.
00397 */
00398 static QString encipher(const QString& plain)
00399 {
00400     // mainly, we make it long
00401     QString cipher;
00402     int mix=28730492;
00403     for (int i=0; i<(int)plain.length(); i++) {
00404         int u = plain[i].unicode();
00405         int c = u ^ mix;
00406         QString x = QString::number(c,36);
00407         cipher.append(QChar('a'+x.length()));
00408         cipher.append(x);
00409         mix *= u;
00410     }
00411     return cipher;
00412 }
00413 
00414 static QString decipher(const QString& cipher)
00415 {
00416     QString plain;
00417     int mix=28730492;
00418     for (int i=0; i<(int)cipher.length();) {
00419         int l = cipher[i].unicode()-'a';
00420         QString x = cipher.mid(i+1,l); i+=l+1;
00421         int u = x.toInt(0,36) ^ mix;
00422         plain.append(QChar(u));
00423         mix *= u;
00424     }
00425     return plain;
00426 }
00427 
00437 void Config::writeEntryCrypt( const QString &key, const QString &value )
00438 {
00439     if ( git == groups.end() ) {
00440         qWarning( "no group set" );
00441         return;
00442     }
00443     QString evalue = encipher(value);
00444     if ( (*git)[key] != evalue ) {
00445         ( *git ).insert( key, evalue );
00446         changed = TRUE;
00447     }
00448 }
00449 
00455 void Config::writeEntry( const QString &key, int num )
00456 {
00457     QString s;
00458     s.setNum( num );
00459     writeEntry( key, s );
00460 }
00461 
00462 #ifdef Q_HAS_BOOL_TYPE
00463 
00469 void Config::writeEntry( const QString &key, bool b )
00470 {
00471     QString s;
00472     s.setNum( ( int )b );
00473     writeEntry( key, s );
00474 }
00475 #endif
00476 
00483 void Config::writeEntry( const QString &key, const QStringList &lst, const QChar &sep )
00484 {
00485     QString s;
00486     QStringList::ConstIterator it = lst.begin();
00487     for ( ; it != lst.end(); ++it )
00488         s += *it + sep;
00489     writeEntry( key, s );
00490 }
00491 
00497 void Config::removeEntry( const QString &key )
00498 {
00499     if ( git == groups.end() ) {
00500         qWarning( "no group set" );
00501         return;
00502     }
00503     ( *git ).remove( key );
00504     changed = TRUE;
00505 }
00506 
00526 /*
00527  * ### !LocalTranslator::translate was kept out!
00528  *
00529  */
00530 
00535 QString Config::readEntry( const QString &key, const QString &deflt )
00536 {
00537     QString r;
00538     if ( d && !d->trcontext.isNull() ) {
00539         // Still try untranslated first, becuase:
00540         //  1. It's the common case
00541         //  2. That way the value can be WRITTEN (becoming untranslated)
00542         r = readEntryDirect( key );
00543         if ( !r.isNull() )
00544             return r;
00545         r = readEntryDirect( key + "[]" );
00546         if ( !r.isNull() )
00547             return qApp->translate(d->trfile,d->trcontext,r);
00548     } else if ( d && d->multilang ) {
00549         // For compatibilitity
00550         r = readEntryDirect( key + "["+lang+"]" );
00551         if ( !r.isNull() )
00552             return r;
00553         if ( !glang.isEmpty() ) {
00554             r = readEntryDirect( key + "["+glang+"]" );
00555             if ( !r.isNull() )
00556                 return r;
00557         }
00558     }
00559     r = readEntryDirect( key, deflt );
00560     return r;
00561 }
00562 
00573 QString Config::readEntryCrypt( const QString &key, const QString &deflt )
00574 {
00575     QString res = readEntry( key );
00576     if ( res.isNull() )
00577         return deflt;
00578     return decipher(res);
00579 }
00580 
00590 QString Config::readEntryDirect( const QString &key, const QString &deflt )
00591 {
00592     if ( git == groups.end() ) {
00593         //qWarning( "no group set" );
00594         return deflt;
00595     }
00596     ConfigGroup::ConstIterator it = ( *git ).find( key );
00597     if ( it != ( *git ).end() )
00598         return *it;
00599     else
00600         return deflt;
00601 }
00602 
00612 int Config::readNumEntry( const QString &key, int deflt )
00613 {
00614     QString s = readEntry( key );
00615     if ( s.isEmpty() )
00616         return deflt;
00617     else
00618         return s.toInt();
00619 }
00620 
00630 bool Config::readBoolEntry( const QString &key, bool deflt )
00631 {
00632     QString s = readEntry( key );
00633     if ( s.isEmpty() )
00634         return deflt;
00635     else
00636         return (bool)s.toInt();
00637 }
00638 
00648 QStringList Config::readListEntry( const QString &key, const QChar &sep )
00649 {
00650     QString s = readEntry( key );
00651     if ( s.isEmpty() )
00652         return QStringList();
00653     else
00654         return QStringList::split( sep, s );
00655 }
00656 
00660 void Config::clearGroup()
00661 {
00662     if ( git == groups.end() ) {
00663         qWarning( "no group set" );
00664         return;
00665     }
00666     if ( !(*git).isEmpty() ) {
00667         ( *git ).clear();
00668         changed = TRUE;
00669     }
00670 }
00671 
00675 void Config::write( const QString &fn )
00676 {
00677     QString oldGroup = git.key();
00678 
00679     QString strNewFile;
00680     if ( !fn.isEmpty() )
00681         filename = fn;
00682     strNewFile = filename + ".new";
00683 
00684     QFile f( strNewFile );
00685     if ( !f.open( IO_WriteOnly|IO_Raw ) ) {
00686         qWarning( "could not open for writing `%s'", strNewFile.latin1() );
00687         git = groups.end();
00688         return;
00689     }
00690 
00691     QString str;
00692     QCString cstr;
00693     QMap< QString, ConfigGroup >::Iterator g_it = groups.begin();
00694 
00695     for ( ; g_it != groups.end(); ++g_it ) {
00696         str += "[" + g_it.key() + "]\n";
00697         ConfigGroup::Iterator e_it = ( *g_it ).begin();
00698         for ( ; e_it != ( *g_it ).end(); ++e_it )
00699             str += e_it.key() + " = " + *e_it + "\n";
00700     }
00701     cstr = str.utf8();
00702 
00703     int total_length;
00704     total_length = f.writeBlock( cstr.data(), cstr.length() );
00705     if ( total_length != int(cstr.length()) ) {
00706         QMessageBox::critical( 0, QObject::tr("Out of Space"),
00707                                QObject::tr("There was a problem creating\nConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") );
00708         f.close();
00709         QFile::remove( strNewFile );
00710         return;
00711     }
00712 
00713     f.close();
00714     // now rename the file...
00715     if ( rename( strNewFile, filename ) < 0 ) {
00716         qWarning( "problem renaming the file %s to %s", strNewFile.latin1(),
00717                   filename.latin1() );
00718         QFile::remove( strNewFile );
00719         return;
00720     }
00721 
00722 #ifndef Q_OS_WIN32
00723     ConfigCache::instance()->insert( filename, groups, d );
00724     setGroup( oldGroup );
00725 #endif
00726     changed = FALSE;
00727 }
00728 
00732 bool Config::isValid() const
00733 {
00734     return groups.end() != git;
00735 }
00736 
00740 void Config::read()
00741 {
00742     changed = FALSE;
00743 
00744     QString readFilename(filename);
00745 
00746     if ( !QFile::exists(filename) ) {
00747         bool failed = TRUE;
00748         QFileInfo fi(filename);
00749         QString settingsDir = QDir::homeDirPath() + "/Settings";
00750         if (fi.dirPath(TRUE) == settingsDir) {
00751         // User setting - see if there is a default in $OPIEDIR/etc/default/
00752             QString dftlFile = QPEApplication::qpeDir() + "etc/default/" + fi.fileName();
00753             if (QFile::exists(dftlFile)) {
00754                 readFilename = dftlFile;
00755                 failed = FALSE;
00756             }
00757         }
00758         if (failed) {
00759             git = groups.end();
00760             return;
00761         }
00762     }
00763 
00764 #ifndef Q_OS_WIN32
00765 
00766     if (ConfigCache::instance()->find(readFilename, groups, &d)) {
00767         if ( d && d->multilang ) {
00768             QStringList l = Global::languageList();
00769             lang = l[0];
00770             glang = l[1];
00771         }
00772         git = groups.begin();
00773         return;
00774     }
00775 #endif
00776 
00777     QFile f( readFilename );
00778     if ( !f.open( IO_ReadOnly ) ) {
00779         git = groups.end();
00780         return;
00781     }
00782 
00783     if (f.getch()!='[') {
00784         git = groups.end();
00785         return;
00786     }
00787     f.ungetch('[');
00788 
00789     QTextStream s( &f );
00790     read( s );
00791     f.close();
00792 
00793 #ifndef Q_OS_WIN32
00794     ConfigCache::instance()->insert(readFilename, groups, d);
00795 #endif
00796 }
00797 
00801 bool Config::parse( const QString &l )
00802 {
00803     QString line = l.stripWhiteSpace();
00804     if ( line[ 0 ] == QChar( '[' ) ) {
00805         QString gname = line;
00806         gname = gname.remove( 0, 1 );
00807         if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) )
00808             gname = gname.remove( gname.length() - 1, 1 );
00809         git = groups.insert( gname, ConfigGroup() );
00810     } else if ( !line.isEmpty() ) {
00811         if ( git == groups.end() )
00812             return FALSE;
00813         int eq = line.find( '=' );
00814         if ( eq == -1 )
00815             return FALSE;
00816         QString key = line.left(eq).stripWhiteSpace();
00817         QString value = line.mid(eq+1).stripWhiteSpace();
00818 
00819         if ( git.key() == "Translation" ) {
00820             if ( key == "File" ) {
00821                 if ( !d )
00822                     d = new ConfigPrivate;
00823                 d->trfile = value;
00824             } else if ( key == "Context" ) {
00825                 if ( !d )
00826                     d = new ConfigPrivate;
00827                 d->trcontext = value.latin1();
00828             } else if ( key.startsWith("Comment") ) {
00829                 return TRUE; // ignore comment for ts file
00830             } else {
00831                 return FALSE; // Unrecognized
00832             }
00833         }
00834 
00835         int kl = key.length();
00836         if ( kl > 1 && key[kl-1] == ']' && key[kl-2] != '[' ) {
00837             // Old-style translation (inefficient)
00838             if ( !d )
00839                 d = new ConfigPrivate;
00840             if ( !d->multilang ) {
00841                 QStringList l = Global::languageList();
00842                 lang = l[0];
00843                 glang = l[1];
00844                 d->multilang = TRUE;
00845             }
00846         }
00847 
00848         ( *git ).insert( key, value );
00849     }
00850     return TRUE;
00851 }
00852 
00853 
00854 
00855 bool Config::hasGroup( const QString& name )const {
00856     return ( groups. find ( name ) != groups. end ( ));
00857 };
00858 
00859 QStringList Config::groupList()const {
00860     QStringList sl;
00861     for ( ConfigGroupMap::ConstIterator it = groups. begin ( ); it != groups. end ( ); ++it )
00862         sl << it.key();
00863 
00864     return sl;
00865 };
00866 
00868 // Qtopia 2.1 Functions
00869 //
00871 
00872 QStringList Config::allGroups()const {
00873     return groupList();
00874 }
00875 
00886 long Config::timeStamp(const QString& name, Domain domain)
00887 {
00888 #ifdef Q_WS_WIN
00889     // Too slow (many conversions too and from time_t and QDataTime)
00890     QDateTime epoch;
00891     epoch.setTime_t(0);
00892     return epoch.secsTo(QFileInfo(Config::configFilename(name,domain)).lastModified());
00893 #else
00894     QString fn = Config::configFilename(name,domain);
00895     struct stat b;
00896     if (lstat( QFile::encodeName(fn).data(), &b ) == 0)
00897         return b.st_mtime;
00898     else
00899         return 0;
00900 #endif
00901 }
00902 
00903 
00911 void Config::removeGroup()
00912 {
00913     if ( git == groups.end() ) {
00914         qWarning( "no group set" );
00915         return;
00916     }
00917 
00918     groups.remove(git.key());
00919     git = groups.end();
00920     changed = TRUE;
00921 }
00922 
00930 void Config::removeGroup(const QString& g)
00931 {
00932     groups.remove(g);
00933     git = groups.end();
00934 }
00935 
00936 
00937 
00952 void Config::writeEntry( const QString &key, const QStringList &lst )
00953 {
00954     QString s;
00955     for (QStringList::ConstIterator it=lst.begin(); it!=lst.end(); ++it) {
00956         QString el = *it;
00957         if ( el.isNull() ) {
00958             el = "^0";
00959         } else {
00960             el.replace(QRegExp("\\^"), "^^");
00961         }
00962         s+=el;
00963         s+="^e"; // end of element
00964     }
00965     writeEntry(key, s);
00966 }
00967 
00974 QStringList Config::readListEntry( const QString &key ) const
00975 {
00976     QString value = readEntry( key, QString::null );
00977     QStringList l;
00978     QString s;
00979     bool esc=FALSE;
00980     for (int i=0; i<(int)value.length(); i++) {
00981         if ( esc ) {
00982             if ( value[i] == 'e' ) { // end-of-string
00983                 l.append(s);
00984                 s="";
00985             } else if ( value[i] == '0' ) { // null string
00986                 s=QString::null;
00987             } else {
00988                 s.append(value[i]);
00989             }
00990             esc = FALSE;
00991         } else if ( value[i] == '^' ) {
00992             esc = TRUE;
00993         } else {
00994             s.append(value[i]);
00995             if ( i == (int)value.length()-1 )
00996                 l.append(s);
00997         }
00998     }
00999     return l;
01000 }
01001 
01002 QString Config::readEntry( const QString &key, const QString &deflt ) const
01003 { return ((Config*)this)->readEntry(key,deflt); }
01004 QString Config::readEntryCrypt( const QString &key, const QString &deflt ) const
01005 { return ((Config*)this)->readEntryCrypt(key,deflt); }
01006 QString Config::readEntryDirect( const QString &key, const QString &deflt ) const
01007 { return ((Config*)this)->readEntryDirect(key,deflt); }
01008 int Config::readNumEntry( const QString &key, int deflt ) const
01009 { return ((Config*)this)->readNumEntry(key,deflt); }
01010 bool Config::readBoolEntry( const QString &key, bool deflt ) const
01011 { return ((Config*)this)->readBoolEntry(key,deflt); }
01012 QStringList Config::readListEntry( const QString &key, const QChar &sep ) const
01013 { return ((Config*)this)->readListEntry(key,sep); }

Generated on Sat Nov 5 16:16:34 2005 for OPIE by  doxygen 1.4.2