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

qsettings.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** 
00003 **
00004 ** Implementation of QSettings class
00005 **
00006 ** Created : 000626
00007 **
00008 ** Copyright (C) 2000-2003 Trolltech AS.  All rights reserved.
00009 **
00010 ** This file is part of the tools module of the Qt GUI Toolkit.
00011 **
00012 ** This file may be distributed under the terms of the Q Public License
00013 ** as defined by Trolltech AS of Norway and appearing in the file
00014 ** LICENSE.QPL included in the packaging of this file.
00015 **
00016 ** This file may be distributed and/or modified under the terms of the
00017 ** GNU General Public License version 2 as published by the Free Software
00018 ** Foundation and appearing in the file LICENSE.GPL included in the
00019 ** packaging of this file.
00020 **
00021 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
00022 ** licenses may use this file in accordance with the Qt Commercial License
00023 ** Agreement provided with the Software.
00024 **
00025 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00026 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00027 **
00028 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00029 **   information about Qt Commercial License Agreements.
00030 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00031 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00032 **
00033 ** Contact info@trolltech.com if any conditions of this licensing are
00034 ** not clear to you.
00035 **
00036 **********************************************************************/
00037 
00038 #include "qplatformdefs.h"
00039 
00040 // POSIX Large File Support redefines open -> open64
00041 static inline int qt_open( const char *pathname, int flags, mode_t mode )
00042 { return ::open( pathname, flags, mode ); }
00043 #if defined(open)
00044 # undef open
00045 #endif
00046 
00047 // POSIX Large File Support redefines truncate -> truncate64
00048 #if defined(truncate)
00049 # undef truncate
00050 #endif
00051 
00052 #include "qsettings.h"
00053 
00054 #ifndef QT_NO_SETTINGS
00055 
00056 #include "qdir.h"
00057 #include "qfile.h"
00058 #include "qfileinfo.h"
00059 #include "qmap.h"
00060 #include "qtextstream.h"
00061 #include "qregexp.h"
00062 #include <private/qsettings_p.h>
00063 #ifndef NO_ERRNO_H
00064 #include <errno.h>
00065 #endif
00066 
00252 #if defined(Q_OS_UNIX)
00253 typedef int HANDLE;
00254 #define Q_LOCKREAD F_RDLCK
00255 #define Q_LOCKWRITE F_WRLCK
00256 /*
00257   Locks the file specified by name.  The lockfile is created as a
00258   hidden file in the same directory as the target file, with .lock
00259   appended to the name. For example, "/etc/settings/onerc" uses a
00260   lockfile named "/etc/settings/.onerc.lock".  The type argument
00261   controls the type of the lock, it can be either F_RDLCK for a read
00262   lock, or F_WRLCK for a write lock.
00263 
00264   A file descriptor for the lock file is returned, and should be
00265   closed with closelock() when the lock is no longer needed.
00266  */
00267 static HANDLE openlock( const QString &name, int type )
00268 {
00269     QFileInfo info( name );
00270     // lockfile should be hidden, and never removed
00271     QString lockfile = info.dirPath() + "/." + info.fileName() + ".lock";
00272 
00273     // open the lockfile
00274     HANDLE fd = qt_open( QFile::encodeName( lockfile ),
00275                          O_RDWR | O_CREAT, S_IRUSR | S_IWUSR );
00276 
00277     if ( fd < 0 ) {
00278         // failed to open the lock file, most likely because of permissions
00279         return fd;
00280     }
00281 
00282     struct flock fl;
00283     fl.l_type = type;
00284     fl.l_whence = SEEK_SET;
00285     fl.l_start = 0;
00286     fl.l_len = 0;
00287     if ( fcntl( fd, F_SETLKW, &fl ) == -1 ) {
00288         // the lock failed, so we should fail silently, so that people
00289         // using filesystems that do not support locking don't see
00290         // numerous warnings about a failed lock
00291         close( fd );
00292         fd = -1;
00293     }
00294 
00295     return fd;
00296 }
00297 
00298 /*
00299   Closes the lock file specified by fd.  fd is the file descriptor
00300   returned by the openlock() function.
00301 */
00302 static void closelock( HANDLE fd )
00303 {
00304     if ( fd < 0 ) {
00305         // the lock file is not open
00306         return;
00307     }
00308 
00309     struct flock fl;
00310     fl.l_type = F_UNLCK;
00311     fl.l_whence = SEEK_SET;
00312     fl.l_start = 0;
00313     fl.l_len = 0;
00314     // ignore the return value, so that the unlock fails silently
00315     (void) fcntl( fd, F_SETLKW, &fl );
00316 
00317     close( fd );
00318 }
00319 #endif
00320 
00321 
00322 QSettingsGroup::QSettingsGroup()
00323     : modified(FALSE)
00324 {
00325 }
00326 
00327 
00328 
00329 
00330 void QSettingsHeading::read(const QString &filename)
00331 {
00332     if (! QFileInfo(filename).exists())
00333         return;
00334 
00335 #ifndef Q_WS_WIN
00336     HANDLE lockfd = openlock( filename, Q_LOCKREAD );
00337 #endif
00338 
00339     QFile file(filename);
00340     if (! file.open(IO_ReadOnly)) {
00341 #if defined(QT_CHECK_STATE)
00342         qWarning("QSettings: failed to open file '%s'", filename.latin1());
00343 #endif
00344         return;
00345     }
00346 
00347     git = end();
00348 
00349     QTextStream stream(&file);
00350     stream.setEncoding(QTextStream::UnicodeUTF8);
00351     while (! stream.atEnd())
00352         parseLine(stream);
00353 
00354     git = end();
00355 
00356     file.close();
00357 
00358 #ifndef Q_WS_WIN
00359     closelock( lockfd );
00360 #endif
00361 }
00362 
00363 
00364 void QSettingsHeading::parseLine(QTextStream &stream)
00365 {
00366     QString line = stream.readLine();
00367     if (line.isEmpty())
00368         // empty line... we'll allow it
00369         return;
00370 
00371     if (line[0] == QChar('#'))
00372         // commented line
00373         return;
00374 
00375     if (line[0] == QChar('[')) {
00376         QString gname = line;
00377 
00378         gname = gname.remove((uint)0, 1);
00379         if (gname[(int)gname.length() - 1] == QChar(']'))
00380             gname = gname.remove(gname.length() - 1, 1);
00381 
00382         git = find(gname);
00383         if (git == end())
00384             git = replace(gname, QSettingsGroup());
00385     } else {
00386         if (git == end()) {
00387 #if defined(QT_CHECK_STATE)
00388             qWarning("QSettings: line '%s' out of group", line.latin1());
00389 #endif
00390             return;
00391         }
00392 
00393         int i = line.find('=');
00394         if (i == -1) {
00395 #if defined(QT_CHECK_STATE)
00396             qWarning("QSettings: malformed line '%s' in group '%s'",
00397                      line.latin1(), git.key().latin1());
00398 #endif
00399             return;
00400         } else {
00401             QString key, value;
00402             key = line.left(i);
00403             value = "";
00404             bool esc=TRUE;
00405             i++;
00406             while (esc) {
00407                 esc = FALSE;
00408                 for ( ; i < (int)line.length(); i++ ) {
00409                     if ( esc ) {
00410                         if ( line[i] == 'n' )
00411                             value.append('\n'); // escaped newline
00412                         else if ( line[i] == '0' )
00413                             value = QString::null; // escaped empty string
00414                         else
00415                             value.append(line[i]);
00416                         esc = FALSE;
00417                     } else if ( line[i] == '\\' )
00418                         esc = TRUE;
00419                     else
00420                         value.append(line[i]);
00421                 }
00422                 if ( esc ) {
00423                     // Backwards-compatiblity...
00424                     // still escaped at EOL - manually escaped "newline"
00425                     if (stream.atEnd()) {
00426 #if defined(QT_CHECK_STATE)
00427                         qWarning("QSettings: reached end of file, expected continued line");
00428 #endif
00429                         break;
00430                     }
00431                     value.append('\n');
00432                     line = stream.readLine();
00433                     i = 0;
00434                 }
00435             }
00436 
00437             (*git).insert(key, value);
00438         }
00439     }
00440 }
00441 
00442 #ifdef Q_WS_WIN // for homedirpath reading from registry
00443 #include "qt_windows.h"
00444 #include "qlibrary.h"
00445 
00446 #ifndef CSIDL_APPDATA
00447 #define CSIDL_APPDATA                   0x001a        // <user name>\Application Data
00448 #endif
00449 #ifndef CSIDL_COMMON_APPDATA
00450 #define CSIDL_COMMON_APPDATA            0x0023        // All Users\Application Data
00451 #endif
00452 
00453 #endif
00454 
00455 QSettingsPrivate::QSettingsPrivate( QSettings::Format format )
00456     : groupDirty( TRUE ), modified(FALSE), globalScope(TRUE)
00457 {
00458 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
00459     if ( format != QSettings::Ini )
00460         return;
00461 #else
00462     Q_UNUSED( format );
00463 #endif
00464 
00465     QString appSettings(QDir::homeDirPath() + "/.qt/");
00466     QString defPath;
00467 #ifdef Q_WS_WIN
00468 #ifdef Q_OS_TEMP
00469         TCHAR path[MAX_PATH];
00470         SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE );
00471         appSettings  = QString::fromUcs2( path );
00472         SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE );
00473         defPath = QString::fromUcs2( path );
00474 #else
00475     QLibrary library( "shell32" );
00476     library.setAutoUnload( FALSE );
00477     QT_WA( {
00478         typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL);
00479         GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathW" );
00480         if ( SHGetSpecialFolderPath ) {
00481             TCHAR path[MAX_PATH];
00482             SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE );
00483             appSettings  = QString::fromUcs2( (ushort*)path );
00484             SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE );
00485             defPath = QString::fromUcs2( (ushort*)path );
00486         }
00487     } , {
00488         typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL);
00489         GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathA" );
00490         if ( SHGetSpecialFolderPath ) {
00491             char path[MAX_PATH];
00492             SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE );
00493             appSettings = QString::fromLocal8Bit( path );
00494             SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE );
00495             defPath = QString::fromLocal8Bit( path );
00496         }
00497     } );
00498 #endif // Q_OS_TEMP
00499 #else
00500     defPath = qInstallPathSysconf();
00501 #endif
00502     QDir dir(appSettings);
00503     if (! dir.exists()) {
00504         if (! dir.mkdir(dir.path()))
00505 #if defined(QT_CHECK_STATE)
00506             qWarning("QSettings: error creating %s", dir.path().latin1());
00507 #else
00508             ;
00509 #endif
00510     }
00511 
00512     if ( !!defPath )
00513         searchPaths.append(defPath);
00514     searchPaths.append(dir.path());
00515 }
00516 
00517 QSettingsPrivate::~QSettingsPrivate()
00518 {
00519 }
00520 
00521 QSettingsGroup QSettingsPrivate::readGroup()
00522 {
00523     QSettingsHeading hd;
00524     QSettingsGroup grp;
00525 
00526     QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading);
00527     if (headingsit != headings.end())
00528         hd = *headingsit;
00529 
00530     QSettingsHeading::Iterator grpit = hd.find(group);
00531     if (grpit == hd.end()) {
00532         QStringList::Iterator it = searchPaths.begin();
00533         if ( !globalScope )
00534             ++it;
00535         while (it != searchPaths.end()) {
00536             QString filebase = heading.lower().replace(QRegExp("\\s+"), "_");
00537             QString fn((*it++) + "/" + filebase + "rc");
00538             if (! hd.contains(fn + "cached")) {
00539                 hd.read(fn);
00540                 hd.insert(fn + "cached", QSettingsGroup());
00541             }
00542         }
00543 
00544         headings.replace(heading, hd);
00545 
00546         grpit = hd.find(group);
00547         if (grpit != hd.end())
00548             grp = *grpit;
00549     } else if (hd.count() != 0)
00550         grp = *grpit;
00551 
00552     return grp;
00553 }
00554 
00555 
00556 void QSettingsPrivate::removeGroup(const QString &key)
00557 {
00558     QSettingsHeading hd;
00559     QSettingsGroup grp;
00560     bool found = FALSE;
00561 
00562     QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading);
00563     if (headingsit != headings.end())
00564         hd = *headingsit;
00565 
00566     QSettingsHeading::Iterator grpit = hd.find(group);
00567     if (grpit == hd.end()) {
00568         QStringList::Iterator it = searchPaths.begin();
00569         if ( !globalScope )
00570             ++it;
00571         while (it != searchPaths.end()) {
00572             QString filebase = heading.lower().replace(QRegExp("\\s+"), "_");
00573             QString fn((*it++) + "/" + filebase + "rc");
00574             if (! hd.contains(fn + "cached")) {
00575                 hd.read(fn);
00576                 hd.insert(fn + "cached", QSettingsGroup());
00577             }
00578         }
00579 
00580         headings.replace(heading, hd);
00581 
00582         grpit = hd.find(group);
00583         if (grpit != hd.end()) {
00584             found = TRUE;
00585             grp = *grpit;
00586         }
00587     } else if (hd.count() != 0) {
00588         found = TRUE;
00589         grp = *grpit;
00590     }
00591 
00592     if (found) {
00593         grp.remove(key);
00594 
00595         if (grp.count() > 0)
00596             hd.replace(group, grp);
00597         else
00598             hd.remove(group);
00599 
00600         if (hd.count() > 0)
00601             headings.replace(heading, hd);
00602         else
00603             headings.remove(heading);
00604 
00605         modified = TRUE;
00606     }
00607 }
00608 
00609 
00610 void QSettingsPrivate::writeGroup(const QString &key, const QString &value)
00611 {
00612     QSettingsHeading hd;
00613     QSettingsGroup grp;
00614 
00615     QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading);
00616     if (headingsit != headings.end())
00617         hd = *headingsit;
00618 
00619     QSettingsHeading::Iterator grpit = hd.find(group);
00620     if (grpit == hd.end()) {
00621         QStringList::Iterator it = searchPaths.begin();
00622         if ( !globalScope )
00623             ++it;
00624         while (it != searchPaths.end()) {
00625             QString filebase = heading.lower().replace(QRegExp("\\s+"), "_");
00626             QString fn((*it++) + "/" + filebase + "rc");
00627             if (! hd.contains(fn + "cached")) {
00628                 hd.read(fn);
00629                 hd.insert(fn + "cached", QSettingsGroup());
00630             }
00631         }
00632 
00633         headings.replace(heading, hd);
00634 
00635         grpit = hd.find(group);
00636         if (grpit != hd.end())
00637             grp = *grpit;
00638     } else if (hd.count() != 0)
00639         grp = *grpit;
00640 
00641     grp.modified = TRUE;
00642     grp.replace(key, value);
00643     hd.replace(group, grp);
00644     headings.replace(heading, hd);
00645 
00646     modified = TRUE;
00647 }
00648 
00649 
00650 QDateTime QSettingsPrivate::modificationTime()
00651 {
00652     QSettingsHeading hd = headings[heading];
00653     QSettingsGroup grp = hd[group];
00654 
00655     QDateTime datetime;
00656 
00657     QStringList::Iterator it = searchPaths.begin();
00658     if ( !globalScope )
00659         ++it;
00660     while (it != searchPaths.end()) {
00661         QFileInfo fi((*it++) + "/" + heading + "rc");
00662         if (fi.exists() && fi.lastModified() > datetime)
00663             datetime = fi.lastModified();
00664     }
00665 
00666     return datetime;
00667 }
00668 
00669 bool qt_verify_key( const QString &key )
00670 {
00671     if ( key.isEmpty() || key[0] != '/' || key.contains( QRegExp("[=\\r\\n]" ) ) )
00672         return FALSE;
00673     return TRUE;
00674 }
00675 
00676 static QString groupKey( const QString &group, const QString &key )
00677 {
00678     QString grp_key;
00679     if ( group.isEmpty() || ( group.length() == 1 && group[0] == '/' ) ) {
00680         // group is empty, or it contains a single '/', so we just return the key
00681         if ( key.startsWith( "/" ) )
00682             grp_key = key;
00683         else
00684             grp_key = "/" + key;
00685     } else if ( group.endsWith( "/" ) || key.startsWith( "/" ) ) {
00686         grp_key = group + key;
00687     } else {
00688         grp_key = group + "/" + key;
00689     }
00690     return grp_key;
00691 }
00692 
00781 void QSettings::insertSearchPath( System s, const QString &path)
00782 {
00783 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
00784     if ( d->sysd ) {
00785         d->sysInsertSearchPath( s, path );
00786         return;
00787     }
00788 #endif
00789 
00790 #if !defined(Q_WS_WIN)
00791     if ( s == Windows )
00792         return;
00793 #endif
00794 #if !defined(Q_OS_MAC)
00795     if ( s == Mac )
00796         return;
00797 #endif
00798 
00799     if ( !qt_verify_key( path ) ) {
00800 #if defined(QT_CHECK_STATE)
00801         qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() );
00802 #endif
00803         return;
00804     }
00805 
00806 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
00807     if ( d->sysd && s != Unix ) {
00808 #else
00809     if ( s != Unix ) {
00810 #endif
00811 #if !defined(QWS) && defined(Q_OS_MAC)
00812         if(s != Mac) //mac is respected on the mac as well
00813 #endif
00814             return;
00815     }
00816 
00817     QString realPath = path;
00818 #if defined(Q_WS_WIN)
00819     QString defPath = d->globalScope ? d->searchPaths.first() : d->searchPaths.last();
00820     realPath = defPath + path;
00821 #endif
00822 
00823     QStringList::Iterator it = d->searchPaths.find(d->searchPaths.last());
00824     if (it != d->searchPaths.end()) {
00825         d->searchPaths.insert(it, realPath);
00826     }
00827 }
00828 
00829 
00837 void QSettings::removeSearchPath( System s, const QString &path)
00838 {
00839     if ( !qt_verify_key( path ) ) {
00840 #if defined(QT_CHECK_STATE)
00841         qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() );
00842 #endif
00843         return;
00844     }
00845 
00846 #ifdef Q_WS_WIN
00847     if ( d->sysd ) {
00848         d->sysRemoveSearchPath( s, path );
00849         return;
00850     }
00851 #endif
00852 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
00853     if ( d->sysd && s != Unix ) {
00854 #else
00855     if ( s != Unix ) {
00856 #endif
00857 #if !defined(QWS) && defined(Q_OS_MAC)
00858         if(s != Mac) //mac is respected on the mac as well
00859 #endif
00860             return;
00861     }
00862 
00863     if (path == d->searchPaths.first() || path == d->searchPaths.last())
00864         return;
00865 
00866     d->searchPaths.remove(path);
00867 }
00868 
00869 
00873 QSettings::QSettings()
00874 {
00875     d = new QSettingsPrivate( Native );
00876     Q_CHECK_PTR(d);
00877 
00878 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
00879     d->sysd = 0;
00880     d->sysInit();
00881 #endif
00882 }
00883 
00890 QSettings::QSettings( Format format )
00891 {
00892     d = new QSettingsPrivate( format );
00893     Q_CHECK_PTR(d);
00894 
00895 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
00896     d->sysd = 0;
00897     if ( format == Native )
00898         d->sysInit();
00899 #else
00900     Q_UNUSED(format);
00901 #endif
00902 }
00903 
00909 QSettings::~QSettings()
00910 {
00911     sync();
00912 
00913 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
00914     if ( d->sysd )
00915         d->sysClear();
00916 #endif
00917 
00918     delete d;
00919 }
00920 
00921 
00926 bool QSettings::sync()
00927 {
00928 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
00929     if ( d->sysd )
00930         return d->sysSync();
00931 #endif
00932     if (! d->modified)
00933         // fake success
00934         return TRUE;
00935 
00936     bool success = TRUE;
00937     QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin();
00938 
00939     while (it != d->headings.end()) {
00940         // determine filename
00941         QSettingsHeading hd(*it);
00942         QSettingsHeading::Iterator hdit = hd.begin();
00943         QString filename;
00944 
00945         QStringList::Iterator pit = d->searchPaths.begin();
00946         if ( !d->globalScope )
00947             ++pit;
00948         while (pit != d->searchPaths.end()) {
00949             QString filebase = it.key().lower().replace(QRegExp("\\s+"), "_");
00950             QFileInfo di(*pit);
00951             if ( !di.exists() ) {
00952                 QDir dir;
00953                 dir.mkdir( *pit );
00954             }
00955 
00956             QFileInfo fi((*pit++) + "/" + filebase + "rc");
00957 
00958             if ((fi.exists() && fi.isFile() && fi.isWritable()) ||
00959                 (! fi.exists() && di.isDir() 
00960 #ifndef Q_WS_WIN
00961                 && di.isWritable()
00962 #else
00963                 && ((qWinVersion()&Qt::WV_NT_based) > Qt::WV_2000 || di.isWritable())
00964 #endif
00965                 )) {
00966                 filename = fi.filePath();
00967                 break;
00968             }
00969         }
00970 
00971         ++it;
00972 
00973         if ( filename.isEmpty() ) {
00974 
00975 #ifdef QT_CHECK_STATE
00976             qWarning("QSettings::sync: filename is null/empty");
00977 #endif // QT_CHECK_STATE
00978 
00979             success = FALSE;
00980             continue;
00981         }
00982 
00983 #ifndef Q_WS_WIN
00984         HANDLE lockfd = openlock( filename, Q_LOCKWRITE );
00985 #endif
00986 
00987         QFile file( filename + ".tmp" );
00988         if (! file.open(IO_WriteOnly)) {
00989 
00990 #ifdef QT_CHECK_STATE
00991             qWarning("QSettings::sync: failed to open '%s' for writing",
00992                      file.name().latin1());
00993 #endif // QT_CHECK_STATE
00994 
00995             success = FALSE;
00996             continue;
00997         }
00998 
00999         // spew to file
01000         QTextStream stream(&file);
01001         stream.setEncoding(QTextStream::UnicodeUTF8);
01002 
01003         while (hdit != hd.end()) {
01004             if ((*hdit).count() > 0) {
01005                 stream << "[" << hdit.key() << "]" << endl;
01006 
01007                 QSettingsGroup grp(*hdit);
01008                 QSettingsGroup::Iterator grpit = grp.begin();
01009 
01010                 while (grpit != grp.end()) {
01011                     QString v = grpit.data();
01012                     if ( v.isNull() ) {
01013                         v = "\\0"; // escape null string
01014                     } else {
01015                         v.replace("\\", "\\\\"); // escape backslash
01016                         v.replace("\n", "\\n"); // escape newlines
01017                     }
01018 
01019                     stream << grpit.key() << "=" << v << endl;
01020                     ++grpit;
01021                 }
01022 
01023                 stream << endl;
01024             }
01025 
01026             ++hdit;
01027         }
01028 
01029         if (file.status() != IO_Ok) {
01030 
01031 #ifdef QT_CHECK_STATE
01032             qWarning("QSettings::sync: error at end of write");
01033 #endif // QT_CHECK_STATE
01034 
01035             success = FALSE;
01036         }
01037 
01038         file.close();
01039 
01040         if ( success ) {
01041             QDir dir( QFileInfo( file ).dir( TRUE ) );
01042             if ( dir.exists( filename ) && !dir.remove( filename ) ||
01043                  !dir.rename( file.name(), filename, TRUE ) ) {
01044 
01045 #ifdef QT_CHECK_STATE
01046                 qWarning( "QSettings::sync: error writing file '%s'",
01047                           QFile::encodeName( filename ).data() );
01048 #endif // QT_CHECK_STATE
01049 
01050                 success = FALSE;
01051             }
01052         }
01053 
01054         // remove temporary file
01055         file.remove();
01056 
01057 #ifndef Q_WS_WIN
01058         closelock( lockfd );
01059 #endif
01060     }
01061 
01062     d->modified = FALSE;
01063 
01064     return success;
01065 }
01066 
01067 
01082 bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok )
01083 {
01084     QString grp_key( groupKey( group(), key ) );
01085     if ( !qt_verify_key( grp_key ) ) {
01086 #if defined(QT_CHECK_STATE)
01087         qWarning( "QSettings::readBoolEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01088 #endif
01089         if ( ok )
01090             *ok = FALSE;
01091 
01092         return def;
01093     }
01094 
01095 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01096     if ( d->sysd )
01097         return d->sysReadBoolEntry( grp_key, def, ok );
01098 #endif
01099 
01100     QString value = readEntry( key, ( def ? "true" : "false" ), ok );
01101 
01102     if (value.lower() == "true")
01103         return TRUE;
01104     else if (value.lower() == "false")
01105         return FALSE;
01106     else if (value == "1")
01107         return TRUE;
01108     else if (value == "0")
01109         return FALSE;
01110 
01111     if (! value.isEmpty())
01112         qWarning("QSettings::readBoolEntry: '%s' is not 'true' or 'false'",
01113                  value.latin1());
01114     if ( ok )
01115         *ok = FALSE;
01116     return def;
01117 }
01118 
01119 
01134 double QSettings::readDoubleEntry(const QString &key, double def, bool *ok )
01135 {
01136     QString grp_key( groupKey( group(), key ) );
01137     if ( !qt_verify_key( grp_key ) ) {
01138 #if defined(QT_CHECK_STATE)
01139         qWarning( "QSettings::readDoubleEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01140 #endif
01141         if ( ok )
01142             *ok = FALSE;
01143 
01144         return def;
01145     }
01146 
01147 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01148     if ( d->sysd )
01149         return d->sysReadDoubleEntry( grp_key, def, ok );
01150 #endif
01151 
01152     QString value = readEntry( key, QString::number(def), ok );
01153     bool conv_ok;
01154     double retval = value.toDouble( &conv_ok );
01155     if ( conv_ok )
01156         return retval;
01157     if ( ! value.isEmpty() )
01158         qWarning( "QSettings::readDoubleEntry: '%s' is not a number",
01159                   value.latin1() );
01160     if ( ok )
01161         *ok = FALSE;
01162     return def;
01163 }
01164 
01165 
01180 int QSettings::readNumEntry(const QString &key, int def, bool *ok )
01181 {
01182     QString grp_key( groupKey( group(), key ) );
01183     if ( !qt_verify_key( grp_key ) ) {
01184 #if defined(QT_CHECK_STATE)
01185         qWarning( "QSettings::readNumEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01186 #endif
01187         if ( ok )
01188             *ok = FALSE;
01189         return def;
01190     }
01191 
01192 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01193     if ( d->sysd )
01194         return d->sysReadNumEntry( grp_key, def, ok );
01195 #endif
01196 
01197     QString value = readEntry( key, QString::number( def ), ok );
01198     bool conv_ok;
01199     int retval = value.toInt( &conv_ok );
01200     if ( conv_ok )
01201         return retval;
01202     if ( ! value.isEmpty() )
01203         qWarning( "QSettings::readNumEntry: '%s' is not a number",
01204                   value.latin1() );
01205     if ( ok )
01206         *ok = FALSE;
01207     return def;
01208 }
01209 
01210 
01225 QString QSettings::readEntry(const QString &key, const QString &def, bool *ok )
01226 {
01227     QString grp_key( groupKey( group(), key ) );
01228     if ( !qt_verify_key( grp_key ) ) {
01229 #if defined(QT_CHECK_STATE)
01230         qWarning( "QSettings::readEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01231 #endif
01232         if ( ok )
01233             *ok = FALSE;
01234 
01235         return def;
01236     }
01237 
01238 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01239     if ( d->sysd )
01240         return d->sysReadEntry( grp_key, def, ok );
01241 #endif
01242 
01243     if ( ok ) // no, everything is not ok
01244         *ok = FALSE;
01245 
01246     QString realkey;
01247 
01248     if (grp_key[0] == '/') {
01249         // parse our key
01250         QStringList list(QStringList::split('/', grp_key));
01251 
01252         if (list.count() < 2) {
01253 #ifdef QT_CHECK_STATE
01254             qWarning("QSettings::readEntry: invalid key '%s'", grp_key.latin1());
01255 #endif // QT_CHECK_STATE
01256             if ( ok )
01257                 *ok = FALSE;
01258             return def;
01259         }
01260 
01261         if (list.count() == 2) {
01262             d->heading = list[0];
01263             d->group = "General";
01264             realkey = list[1];
01265         } else {
01266             d->heading = list[0];
01267             d->group = list[1];
01268 
01269             // remove the group from the list
01270             list.remove(list.at(1));
01271             // remove the heading from the list
01272             list.remove(list.at(0));
01273 
01274             realkey = list.join("/");
01275         }
01276     } else {
01277         realkey = grp_key;
01278     }
01279 
01280     QSettingsGroup grp = d->readGroup();
01281     QSettingsGroup::const_iterator it = grp.find( realkey ), end = grp.end();
01282     QString retval = def;
01283     if ( it != end ) {
01284         // found the value we needed
01285         retval = *it;
01286         if ( ok ) *ok = TRUE;
01287     }
01288     return retval;
01289 }
01290 
01291 
01292 #if !defined(Q_NO_BOOL_TYPE)
01293 
01303 bool QSettings::writeEntry(const QString &key, bool value)
01304 {
01305     QString grp_key( groupKey( group(), key ) );
01306     if ( !qt_verify_key( grp_key ) ) {
01307 #if defined(QT_CHECK_STATE)
01308         qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01309 #endif
01310         return FALSE;
01311     }
01312 
01313 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01314     if ( d->sysd )
01315         return d->sysWriteEntry( grp_key, value );
01316 #endif
01317     QString s(value ? "true" : "false");
01318     return writeEntry(key, s);
01319 }
01320 #endif
01321 
01322 
01334 bool QSettings::writeEntry(const QString &key, double value)
01335 {
01336     QString grp_key( groupKey( group(), key ) );
01337     if ( !qt_verify_key( grp_key ) ) {
01338 #if defined(QT_CHECK_STATE)
01339         qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01340 #endif
01341         return FALSE;
01342     }
01343 
01344 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01345     if ( d->sysd )
01346         return d->sysWriteEntry( grp_key, value );
01347 #endif
01348     QString s(QString::number(value));
01349     return writeEntry(key, s);
01350 }
01351 
01352 
01364 bool QSettings::writeEntry(const QString &key, int value)
01365 {
01366     QString grp_key( groupKey( group(), key ) );
01367     if ( !qt_verify_key( grp_key ) ) {
01368 #if defined(QT_CHECK_STATE)
01369         qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01370 #endif
01371         return FALSE;
01372     }
01373 
01374 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01375     if ( d->sysd )
01376         return d->sysWriteEntry( grp_key, value );
01377 #endif
01378     QString s(QString::number(value));
01379     return writeEntry(key, s);
01380 }
01381 
01382 
01399 bool QSettings::writeEntry(const QString &key, const char *value)
01400 {
01401     return writeEntry(key, QString(value));
01402 }
01403 
01404 
01417 bool QSettings::writeEntry(const QString &key, const QString &value)
01418 {
01419     QString grp_key( groupKey( group(), key ) );
01420     if ( !qt_verify_key( grp_key ) ) {
01421 #if defined(QT_CHECK_STATE)
01422         qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01423 #endif
01424         return FALSE;
01425     }
01426 
01427 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01428     if ( d->sysd )
01429         return d->sysWriteEntry( grp_key, value );
01430 #endif
01431     // NOTE: we *do* allow value to be a null/empty string
01432 
01433     QString realkey;
01434 
01435     if (grp_key[0] == '/') {
01436         // parse our key
01437         QStringList list(QStringList::split('/', grp_key));
01438 
01439         if (list.count() < 2) {
01440 #ifdef QT_CHECK_STATE
01441             qWarning("QSettings::writeEntry: invalid key '%s'", grp_key.latin1());
01442 #endif // QT_CHECK_STATE
01443 
01444             return FALSE;
01445         }
01446 
01447         if (list.count() == 2) {
01448             d->heading = list[0];
01449             d->group = "General";
01450             realkey = list[1];
01451         } else {
01452             d->heading = list[0];
01453             d->group = list[1];
01454 
01455             // remove the group from the list
01456             list.remove(list.at(1));
01457             // remove the heading from the list
01458             list.remove(list.at(0));
01459 
01460             realkey = list.join("/");
01461         }
01462     } else {
01463         realkey = grp_key;
01464     }
01465 
01466     d->writeGroup(realkey, value);
01467     return TRUE;
01468 }
01469 
01470 
01478 bool QSettings::removeEntry(const QString &key)
01479 {
01480     QString grp_key( groupKey( group(), key ) );
01481     if ( !qt_verify_key( grp_key ) ) {
01482 #if defined(QT_CHECK_STATE)
01483         qWarning( "QSettings::removeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01484 #endif
01485         return FALSE;
01486     }
01487 
01488 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01489     if ( d->sysd )
01490         return d->sysRemoveEntry( grp_key );
01491 #endif
01492 
01493     QString realkey;
01494     if (grp_key[0] == '/') {
01495         // parse our key
01496         QStringList list(QStringList::split('/', grp_key));
01497 
01498         if (list.count() < 2) {
01499 #ifdef QT_CHECK_STATE
01500             qWarning("QSettings::removeEntry: invalid key '%s'", grp_key.latin1());
01501 #endif // QT_CHECK_STATE
01502 
01503             return FALSE;
01504         }
01505 
01506         if (list.count() == 2) {
01507             d->heading = list[0];
01508             d->group = "General";
01509             realkey = list[1];
01510         } else {
01511             d->heading = list[0];
01512             d->group = list[1];
01513 
01514             // remove the group from the list
01515             list.remove(list.at(1));
01516             // remove the heading from the list
01517             list.remove(list.at(0));
01518 
01519             realkey = list.join("/");
01520         }
01521     } else {
01522         realkey = grp_key;
01523     }
01524 
01525     d->removeGroup(realkey);
01526     return TRUE;
01527 }
01528 
01529 
01556 QStringList QSettings::entryList(const QString &key) const
01557 {
01558     QString grp_key( groupKey( group(), key ) );
01559     if ( !qt_verify_key( grp_key ) ) {
01560 #if defined(QT_CHECK_STATE)
01561         qWarning( "QSettings::entryList: Invalid key: %s", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01562 #endif
01563         return QStringList();
01564     }
01565 
01566 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01567     if ( d->sysd )
01568         return d->sysEntryList( grp_key );
01569 #endif
01570 
01571     QString realkey;
01572     if (grp_key[0] == '/') {
01573         // parse our key
01574         QStringList list(QStringList::split('/', grp_key));
01575 
01576         if (list.count() < 1) {
01577 #ifdef QT_CHECK_STATE
01578             qWarning("QSettings::listEntries: invalid key '%s'", grp_key.latin1());
01579 #endif // QT_CHECK_STATE
01580 
01581             return QStringList();
01582         }
01583 
01584         if (list.count() == 1) {
01585             d->heading = list[0];
01586             d->group = "General";
01587         } else {
01588             d->heading = list[0];
01589             d->group = list[1];
01590 
01591             // remove the group from the list
01592             list.remove(list.at(1));
01593             // remove the heading from the list
01594             list.remove(list.at(0));
01595 
01596             realkey = list.join("/");
01597         }
01598     } else
01599         realkey = grp_key;
01600 
01601     QSettingsGroup grp = d->readGroup();
01602     QSettingsGroup::Iterator it = grp.begin();
01603     QStringList ret;
01604     QString itkey;
01605     while (it != grp.end()) {
01606         itkey = it.key();
01607         ++it;
01608 
01609         if ( realkey.length() > 0 ) {
01610             if ( itkey.left( realkey.length() ) != realkey )
01611                 continue;
01612             else
01613                 itkey.remove( 0, realkey.length() + 1 );
01614         }
01615 
01616         if ( itkey.find( '/' ) != -1 )
01617             continue;
01618 
01619         ret << itkey;
01620     }
01621 
01622     return ret;
01623 }
01624 
01625 
01652 QStringList QSettings::subkeyList(const QString &key) const
01653 {
01654     QString grp_key( groupKey( group(), key ) );
01655     if ( !qt_verify_key( grp_key ) ) {
01656 #if defined(QT_CHECK_STATE)
01657         qWarning( "QSettings::subkeyList: Invalid key: %s", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01658 #endif
01659         return QStringList();
01660     }
01661 
01662 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01663     if ( d->sysd )
01664         return d->sysSubkeyList( grp_key );
01665 #endif
01666 
01667     QString realkey;
01668     int subkeycount = 2;
01669     if (grp_key[0] == '/') {
01670         // parse our key
01671         QStringList list(QStringList::split('/', grp_key));
01672 
01673         if (list.count() < 1) {
01674 #ifdef QT_CHECK_STATE
01675             qWarning("QSettings::subkeyList: invalid key '%s'", grp_key.latin1());
01676 #endif // QT_CHECK_STATE
01677 
01678             return QStringList();
01679         }
01680 
01681         subkeycount = list.count();
01682 
01683         if (list.count() == 1) {
01684             d->heading = list[0];
01685             d->group = "General";
01686         } else {
01687             d->heading = list[0];
01688             d->group = list[1];
01689 
01690             // remove the group from the list
01691             list.remove(list.at(1));
01692             // remove the heading from the list
01693             list.remove(list.at(0));
01694 
01695             realkey = list.join("/");
01696         }
01697 
01698     } else
01699         realkey = grp_key;
01700 
01701     QStringList ret;
01702     if ( subkeycount == 1 ) {
01703         QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin();
01704         while ( it != d->headings.end() ) {
01705             if ( it.key() != "General" && ! ret.contains( it.key() ) )
01706                 ret << it.key();
01707             ++it;
01708         }
01709 
01710         return ret;
01711     }
01712 
01713     QSettingsGroup grp = d->readGroup();
01714     QSettingsGroup::Iterator it = grp.begin();
01715     QString itkey;
01716     while (it != grp.end()) {
01717         itkey = it.key();
01718         ++it;
01719 
01720         if ( realkey.length() > 0 ) {
01721             if ( itkey.left( realkey.length() ) != realkey )
01722                 continue;
01723             else
01724                 itkey.remove( 0, realkey.length() + 1 );
01725         }
01726 
01727         int slash = itkey.find( '/' );
01728         if ( slash == -1 )
01729             continue;
01730         itkey.truncate( slash );
01731 
01732         if ( ! ret.contains( itkey ) )
01733             ret << itkey;
01734     }
01735 
01736     return ret;
01737 }
01738 
01739 
01745 QDateTime QSettings::lastModificationTime( const QString &key )
01746 {
01747     QString grp_key( groupKey( group(), key ) );
01748     if ( !qt_verify_key( grp_key ) ) {
01749 #if defined(QT_CHECK_STATE)
01750         qWarning( "QSettings::lastModificationTime: Invalid key '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
01751 #endif
01752         return QDateTime();
01753     }
01754 
01755 #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
01756     if ( d->sysd )
01757         return QDateTime();
01758 #endif
01759 
01760     if (grp_key[0] == '/') {
01761         // parse our key
01762         QStringList list(QStringList::split('/', grp_key));
01763 
01764         if (list.count() < 2) {
01765 #ifdef QT_CHECK_STATE
01766             qWarning("QSettings::lastModificationTime: Invalid key '%s'", grp_key.latin1());
01767 #endif // QT_CHECK_STATE
01768 
01769             return QDateTime();
01770         }
01771 
01772         if (list.count() == 2) {
01773             d->heading = list[0];
01774             d->group = "General";
01775         } else {
01776             d->heading = list[0];
01777             d->group = list[1];
01778         }
01779     }
01780 
01781     return d->modificationTime();
01782 }
01783 
01784 
01810 bool QSettings::writeEntry(const QString &key, const QStringList &value,
01811                            const QChar &separator)
01812 {
01813     QString s(value.join(separator));
01814     return writeEntry(key, s);
01815 }
01816 
01829 bool QSettings::writeEntry(const QString &key, const QStringList &value)
01830 {
01831     QString s;
01832     for (QStringList::ConstIterator it=value.begin(); it!=value.end(); ++it) {
01833         QString el = *it;
01834         if ( el.isNull() ) {
01835             el = "^0";
01836         } else {
01837             el.replace("^", "^^");
01838         }
01839         s+=el;
01840         s+="^e"; // end of element
01841     }
01842     return writeEntry(key, s);
01843 }
01844 
01845 
01878 QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok )
01879 {
01880     QString value = readEntry( key, QString::null, ok );
01881     if ( ok && !*ok )
01882         return QStringList();
01883 
01884     return QStringList::split(separator, value);
01885 }
01886 
01910 QStringList QSettings::readListEntry(const QString &key, bool *ok )
01911 {
01912     QString value = readEntry( key, QString::null, ok );
01913     if ( ok && !*ok )
01914         return QStringList();
01915     QStringList l;
01916     QString s;
01917     bool esc=FALSE;
01918     for (int i=0; i<(int)value.length(); i++) {
01919         if ( esc ) {
01920             if ( value[i] == 'e' ) { // end-of-string
01921                 l.append(s);
01922                 s="";
01923             } else if ( value[i] == '0' ) { // null string
01924                 s=QString::null;
01925             } else {
01926                 s.append(value[i]);
01927             }
01928             esc=FALSE;
01929         } else if ( value[i] == '^' ) {
01930             esc = TRUE;
01931         } else {
01932             s.append(value[i]);
01933             if ( i == (int)value.length()-1 )
01934                 l.append(s);
01935         }
01936     }
01937     return l;
01938 }
01939 
01940 #ifdef Q_OS_MAC
01941 void qt_setSettingsBasePath(const QString &); //qsettings_mac.cpp
01942 #endif
01943 
01961 void QSettings::setPath( const QString &domain, const QString &product, Scope scope )
01962 {
01963 //    On Windows, any trailing ".com(\..*)" is stripped from the domain. The
01964 //    Global scope corresponds to HKEY_LOCAL_MACHINE, and User corresponds to
01965 //    HKEY_CURRENT_USER. Note that on some installations, not all users can
01966 //    write to the Global scope. On UNIX, any trailing ".com(\..*)" is stripped
01967 //    from the domain. The Global scope corresponds to "/opt" (this would be
01968 //    configurable at library build time - eg. to "/usr/local" or "/usr"),
01969 //    while the User scope corresponds to $HOME/.*rc.
01970 //    Note that on most installations, not all users can write to the System
01971 //    scope.
01972 //
01973 //    On MacOS X, if there is no "." in domain, append ".com", then reverse the
01974 //    order of the elements (Mac OS uses "com.apple.finder" as domain+product).
01975 //    The Global scope corresponds to /Library/Preferences/*.plist, while the
01976 //    User scope corresponds to ~/Library/Preferences/*.plist.
01977 //    Note that on most installations, not all users can write to the System
01978 //    scope.
01979     d->globalScope = scope == Global;
01980 
01981     QString actualSearchPath;
01982     int lastDot = domain.findRev( '.' );
01983 
01984 #if defined(Q_WS_WIN)
01985     actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product;
01986     insertSearchPath( Windows, actualSearchPath );
01987 #elif !defined(QWS) && defined(Q_OS_MAC)
01988     if(lastDot != -1) {
01989         QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + ".";
01990         if ( !topLevelDomain.isEmpty() )
01991             qt_setSettingsBasePath( topLevelDomain );
01992     }
01993     actualSearchPath = "/" + domain.left( lastDot ) + "." + product;
01994     insertSearchPath( Mac, actualSearchPath );
01995 #else
01996     if (scope == User)
01997         actualSearchPath = QDir::homeDirPath() + "/.";
01998     else
01999         actualSearchPath = QString(qInstallPathSysconf()) + "/";
02000     actualSearchPath += domain.mid( 0, lastDot ) + "/" + product;
02001     insertSearchPath( Unix, actualSearchPath );
02002 #endif
02003 }
02004 
02015 void QSettings::beginGroup( const QString &group )
02016 {
02017     d->groupStack.push( group );
02018     d->groupDirty = TRUE;
02019 }
02020 
02032 void QSettings::endGroup()
02033 {
02034     d->groupStack.pop();
02035     d->groupDirty = TRUE;
02036 }
02037 
02041 void QSettings::resetGroup()
02042 {
02043     d->groupStack.clear();
02044     d->groupDirty = FALSE;
02045     d->groupPrefix = QString::null;
02046 }
02047 
02053 QString QSettings::group() const
02054 {
02055     if ( d->groupDirty ) {
02056         d->groupDirty = FALSE;
02057         d->groupPrefix = QString::null;
02058 
02059         QValueStack<QString>::Iterator it = d->groupStack.begin();
02060         while ( it != d->groupStack.end() ) {
02061             QString group = *it;
02062             ++it;
02063             if ( group[0] != '/' )
02064                 group.prepend( "/" );
02065             d->groupPrefix += group;
02066         }
02067     }
02068     return d->groupPrefix;
02069 }
02070 
02071 #endif

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