src/corelib/io/qsettings.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <qdebug.h>
       
    43 #include "qplatformdefs.h"
       
    44 #include "qsettings.h"
       
    45 
       
    46 #ifndef QT_NO_SETTINGS
       
    47 
       
    48 #include "qsettings_p.h"
       
    49 #include "qcache.h"
       
    50 #include "qfile.h"
       
    51 #include "qdir.h"
       
    52 #include "qfileinfo.h"
       
    53 #include "qmutex.h"
       
    54 #include "qlibraryinfo.h"
       
    55 #include "qtemporaryfile.h"
       
    56 
       
    57 #ifndef QT_NO_TEXTCODEC
       
    58 #  include "qtextcodec.h"
       
    59 #endif
       
    60 
       
    61 #ifndef QT_NO_GEOM_VARIANT
       
    62 #include "qsize.h"
       
    63 #include "qpoint.h"
       
    64 #include "qrect.h"
       
    65 #endif // !QT_NO_GEOM_VARIANT
       
    66 
       
    67 #ifndef QT_NO_QOBJECT
       
    68 #include "qcoreapplication.h"
       
    69 
       
    70 #ifdef Q_OS_WIN // for homedirpath reading from registry
       
    71 #include "qt_windows.h"
       
    72 #include "qlibrary.h"
       
    73 
       
    74 #endif // Q_OS_WIN
       
    75 #endif // QT_NO_QOBJECT
       
    76 
       
    77 #ifdef Q_OS_VXWORKS
       
    78 #  include <ioLib.h>
       
    79 #endif
       
    80 
       
    81 #include <stdlib.h>
       
    82 
       
    83 #ifndef CSIDL_COMMON_APPDATA
       
    84 #define CSIDL_COMMON_APPDATA	0x0023  // All Users\Application Data
       
    85 #endif
       
    86 
       
    87 #ifndef CSIDL_APPDATA
       
    88 #define CSIDL_APPDATA		0x001a	// <username>\Application Data
       
    89 #endif
       
    90 
       
    91 // ************************************************************************
       
    92 // QConfFile
       
    93 
       
    94 /*
       
    95     QConfFile objects are explicitly shared within the application.
       
    96     This ensures that modification to the settings done through one
       
    97     QSettings object are immediately reflected in other setting
       
    98     objects of the same application.
       
    99 */
       
   100 
       
   101 QT_BEGIN_NAMESPACE
       
   102 
       
   103 struct QConfFileCustomFormat
       
   104 {
       
   105     QString extension;
       
   106     QSettings::ReadFunc readFunc;
       
   107     QSettings::WriteFunc writeFunc;
       
   108     Qt::CaseSensitivity caseSensitivity;
       
   109 };
       
   110 
       
   111 typedef QHash<QString, QConfFile *> ConfFileHash;
       
   112 typedef QCache<QString, QConfFile> ConfFileCache;
       
   113 typedef QHash<int, QString> PathHash;
       
   114 typedef QVector<QConfFileCustomFormat> CustomFormatVector;
       
   115 
       
   116 Q_GLOBAL_STATIC(ConfFileHash, usedHashFunc)
       
   117 Q_GLOBAL_STATIC(ConfFileCache, unusedCacheFunc)
       
   118 Q_GLOBAL_STATIC(PathHash, pathHashFunc)
       
   119 Q_GLOBAL_STATIC(CustomFormatVector, customFormatVectorFunc)
       
   120 Q_GLOBAL_STATIC(QMutex, globalMutex)
       
   121 static QSettings::Format globalDefaultFormat = QSettings::NativeFormat;
       
   122 
       
   123 #ifndef Q_OS_WIN
       
   124 inline bool qt_isEvilFsTypeName(const char *name)
       
   125 {
       
   126     return (qstrncmp(name, "nfs", 3) == 0
       
   127             || qstrncmp(name, "autofs", 6) == 0
       
   128             || qstrncmp(name, "cachefs", 7) == 0);
       
   129 }
       
   130 
       
   131 #if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)
       
   132 QT_BEGIN_INCLUDE_NAMESPACE
       
   133 # include <sys/param.h>
       
   134 # include <sys/mount.h>
       
   135 QT_END_INCLUDE_NAMESPACE
       
   136 
       
   137 static bool isLikelyToBeNfs(int handle)
       
   138 {
       
   139     struct statfs buf;
       
   140     if (fstatfs(handle, &buf) != 0)
       
   141         return false;
       
   142     return qt_isEvilFsTypeName(buf.f_fstypename);
       
   143 }
       
   144 
       
   145 #elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
       
   146 QT_BEGIN_INCLUDE_NAMESPACE
       
   147 # include <sys/vfs.h>
       
   148 # ifdef QT_LINUXBASE
       
   149    // LSB 3.2 has fstatfs in sys/statfs.h, sys/vfs.h is just an empty dummy header
       
   150 #  include <sys/statfs.h>
       
   151 # endif
       
   152 QT_END_INCLUDE_NAMESPACE
       
   153 # ifndef NFS_SUPER_MAGIC
       
   154 #  define NFS_SUPER_MAGIC       0x00006969
       
   155 # endif
       
   156 # ifndef AUTOFS_SUPER_MAGIC
       
   157 #  define AUTOFS_SUPER_MAGIC    0x00000187
       
   158 # endif
       
   159 # ifndef AUTOFSNG_SUPER_MAGIC
       
   160 #  define AUTOFSNG_SUPER_MAGIC  0x7d92b1a0
       
   161 # endif
       
   162 
       
   163 static bool isLikelyToBeNfs(int handle)
       
   164 {
       
   165     struct statfs buf;
       
   166     if (fstatfs(handle, &buf) != 0)
       
   167         return false;
       
   168     return buf.f_type == NFS_SUPER_MAGIC
       
   169            || buf.f_type == AUTOFS_SUPER_MAGIC
       
   170            || buf.f_type == AUTOFSNG_SUPER_MAGIC;
       
   171 }
       
   172 
       
   173 #elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \
       
   174       || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \
       
   175       || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD)
       
   176 QT_BEGIN_INCLUDE_NAMESPACE
       
   177 # include <sys/statvfs.h>
       
   178 QT_END_INCLUDE_NAMESPACE
       
   179 
       
   180 static bool isLikelyToBeNfs(int handle)
       
   181 {
       
   182     struct statvfs buf;
       
   183     if (fstatvfs(handle, &buf) != 0)
       
   184         return false;
       
   185 #if defined(Q_OS_NETBSD)
       
   186     return qt_isEvilFsTypeName(buf.f_fstypename);
       
   187 #else
       
   188     return qt_isEvilFsTypeName(buf.f_basetype);
       
   189 #endif
       
   190 }
       
   191 #else
       
   192 static inline bool isLikelyToBeNfs(int /* handle */)
       
   193 {
       
   194     return true;
       
   195 }
       
   196 #endif
       
   197 
       
   198 static bool unixLock(int handle, int lockType)
       
   199 {
       
   200     /*
       
   201         NFS hangs on the fcntl() call below when statd or lockd isn't
       
   202         running. There's no way to detect this. Our work-around for
       
   203         now is to disable locking when we detect NFS (or AutoFS or
       
   204         CacheFS, which are probably wrapping NFS).
       
   205     */
       
   206     if (isLikelyToBeNfs(handle))
       
   207         return false;
       
   208 
       
   209     struct flock fl;
       
   210     fl.l_whence = SEEK_SET;
       
   211     fl.l_start = 0;
       
   212     fl.l_len = 0;
       
   213     fl.l_type = lockType;
       
   214     return fcntl(handle, F_SETLKW, &fl) == 0;
       
   215 }
       
   216 #endif
       
   217 
       
   218 QConfFile::QConfFile(const QString &fileName, bool _userPerms)
       
   219     : name(fileName), size(0), ref(1), userPerms(_userPerms)
       
   220 {
       
   221     usedHashFunc()->insert(name, this);
       
   222 }
       
   223 
       
   224 QConfFile::~QConfFile()
       
   225 {
       
   226     if (usedHashFunc())
       
   227         usedHashFunc()->remove(name);
       
   228 }
       
   229 
       
   230 ParsedSettingsMap QConfFile::mergedKeyMap() const
       
   231 {
       
   232     ParsedSettingsMap result = originalKeys;
       
   233     ParsedSettingsMap::const_iterator i;
       
   234 
       
   235     for (i = removedKeys.begin(); i != removedKeys.end(); ++i)
       
   236         result.remove(i.key());
       
   237     for (i = addedKeys.begin(); i != addedKeys.end(); ++i)
       
   238         result.insert(i.key(), i.value());
       
   239     return result;
       
   240 }
       
   241 
       
   242 bool QConfFile::isWritable() const
       
   243 {
       
   244     QFileInfo fileInfo(name);
       
   245 
       
   246 #ifndef QT_NO_TEMPORARYFILE
       
   247     if (fileInfo.exists()) {
       
   248 #endif
       
   249         QFile file(name);
       
   250         return file.open(QFile::ReadWrite);
       
   251 #ifndef QT_NO_TEMPORARYFILE
       
   252     } else {
       
   253         // Create the directories to the file.
       
   254         QDir dir(fileInfo.absolutePath());
       
   255         if (dir.exists() && dir.isReadable()) {
       
   256             return true;
       
   257         } else {
       
   258             if (!dir.mkpath(dir.absolutePath()))
       
   259                 return false;
       
   260         }
       
   261 
       
   262         // we use a temporary file to avoid race conditions
       
   263         QTemporaryFile file(name);
       
   264         return file.open();
       
   265     }
       
   266 #endif
       
   267 }
       
   268 
       
   269 QConfFile *QConfFile::fromName(const QString &fileName, bool _userPerms)
       
   270 {
       
   271     QString absPath = QFileInfo(fileName).absoluteFilePath();
       
   272 
       
   273     ConfFileHash *usedHash = usedHashFunc();
       
   274     ConfFileCache *unusedCache = unusedCacheFunc();
       
   275 
       
   276     QConfFile *confFile = 0;
       
   277     QMutexLocker locker(globalMutex());
       
   278 
       
   279     if (!(confFile = usedHash->value(absPath))) {
       
   280         if ((confFile = unusedCache->take(absPath)))
       
   281             usedHash->insert(absPath, confFile);
       
   282     }
       
   283     if (confFile) {
       
   284         confFile->ref.ref();
       
   285         return confFile;
       
   286     }
       
   287     return new QConfFile(absPath, _userPerms);
       
   288 }
       
   289 
       
   290 void QConfFile::clearCache()
       
   291 {
       
   292     QMutexLocker locker(globalMutex());
       
   293     unusedCacheFunc()->clear();
       
   294 }
       
   295 
       
   296 // ************************************************************************
       
   297 // QSettingsPrivate
       
   298 
       
   299 QSettingsPrivate::QSettingsPrivate(QSettings::Format format)
       
   300     : format(format), scope(QSettings::UserScope /* nothing better to put */), iniCodec(0), spec(0), fallbacks(true),
       
   301       pendingChanges(false), status(QSettings::NoError)
       
   302 {
       
   303 }
       
   304 
       
   305 QSettingsPrivate::QSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
       
   306                                    const QString &organization, const QString &application)
       
   307     : format(format), scope(scope), organizationName(organization), applicationName(application),
       
   308       iniCodec(0), spec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError)
       
   309 {
       
   310 }
       
   311 
       
   312 QSettingsPrivate::~QSettingsPrivate()
       
   313 {
       
   314 }
       
   315 
       
   316 QString QSettingsPrivate::actualKey(const QString &key) const
       
   317 {
       
   318     QString n = normalizedKey(key);
       
   319     Q_ASSERT_X(!n.isEmpty(), "QSettings", "empty key");
       
   320     n.prepend(groupPrefix);
       
   321     return n;
       
   322 }
       
   323 
       
   324 /*
       
   325     Returns a string that never starts nor ends with a slash (or an
       
   326     empty string). Examples:
       
   327 
       
   328             "foo"            becomes   "foo"
       
   329             "/foo//bar///"   becomes   "foo/bar"
       
   330             "///"            becomes   ""
       
   331 
       
   332     This function is optimized to avoid a QString deep copy in the
       
   333     common case where the key is already normalized.
       
   334 */
       
   335 QString QSettingsPrivate::normalizedKey(const QString &key)
       
   336 {
       
   337     QString result = key;
       
   338 
       
   339     int i = 0;
       
   340     while (i < result.size()) {
       
   341         while (result.at(i) == QLatin1Char('/')) {
       
   342             result.remove(i, 1);
       
   343             if (i == result.size())
       
   344                 goto after_loop;
       
   345         }
       
   346         while (result.at(i) != QLatin1Char('/')) {
       
   347             ++i;
       
   348             if (i == result.size())
       
   349                 return result;
       
   350         }
       
   351         ++i; // leave the slash alone
       
   352     }
       
   353 
       
   354 after_loop:
       
   355     if (!result.isEmpty())
       
   356         result.truncate(i - 1); // remove the trailing slash
       
   357     return result;
       
   358 }
       
   359 
       
   360 // see also qsettings_win.cpp and qsettings_mac.cpp
       
   361 
       
   362 #if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
       
   363 QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
       
   364                                            const QString &organization, const QString &application)
       
   365 {
       
   366     return new QConfFileSettingsPrivate(format, scope, organization, application);
       
   367 }
       
   368 #endif
       
   369 
       
   370 #if !defined(Q_OS_WIN)
       
   371 QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
       
   372 {
       
   373     return new QConfFileSettingsPrivate(fileName, format);
       
   374 }
       
   375 #endif
       
   376 
       
   377 void QSettingsPrivate::processChild(QString key, ChildSpec spec, QMap<QString, QString> &result)
       
   378 {
       
   379     if (spec != AllKeys) {
       
   380         int slashPos = key.indexOf(QLatin1Char('/'));
       
   381         if (slashPos == -1) {
       
   382             if (spec != ChildKeys)
       
   383                 return;
       
   384         } else {
       
   385             if (spec != ChildGroups)
       
   386                 return;
       
   387             key.truncate(slashPos);
       
   388         }
       
   389     }
       
   390     result.insert(key, QString());
       
   391 }
       
   392 
       
   393 void QSettingsPrivate::beginGroupOrArray(const QSettingsGroup &group)
       
   394 {
       
   395     groupStack.push(group);
       
   396     if (!group.name().isEmpty()) {
       
   397         groupPrefix += group.name();
       
   398         groupPrefix += QLatin1Char('/');
       
   399     }
       
   400 }
       
   401 
       
   402 /*
       
   403     We only set an error if there isn't one set already. This way the user always gets the
       
   404     first error that occurred. We always allow clearing errors.
       
   405 */
       
   406 
       
   407 void QSettingsPrivate::setStatus(QSettings::Status status) const
       
   408 {
       
   409     if (status == QSettings::NoError || this->status == QSettings::NoError)
       
   410         this->status = status;
       
   411 }
       
   412 
       
   413 void QSettingsPrivate::update()
       
   414 {
       
   415     flush();
       
   416     pendingChanges = false;
       
   417 }
       
   418 
       
   419 void QSettingsPrivate::requestUpdate()
       
   420 {
       
   421     if (!pendingChanges) {
       
   422         pendingChanges = true;
       
   423 #ifndef QT_NO_QOBJECT
       
   424         Q_Q(QSettings);
       
   425         QCoreApplication::postEvent(q, new QEvent(QEvent::UpdateRequest));
       
   426 #else
       
   427         update();
       
   428 #endif
       
   429     }
       
   430 }
       
   431 
       
   432 QStringList QSettingsPrivate::variantListToStringList(const QVariantList &l)
       
   433 {
       
   434     QStringList result;
       
   435     QVariantList::const_iterator it = l.constBegin();
       
   436     for (; it != l.constEnd(); ++it)
       
   437         result.append(variantToString(*it));
       
   438     return result;
       
   439 }
       
   440 
       
   441 QVariant QSettingsPrivate::stringListToVariantList(const QStringList &l)
       
   442 {
       
   443     QStringList outStringList = l;
       
   444     for (int i = 0; i < outStringList.count(); ++i) {
       
   445         const QString &str = outStringList.at(i);
       
   446 
       
   447         if (str.startsWith(QLatin1Char('@'))) {
       
   448             if (str.length() >= 2 && str.at(1) == QLatin1Char('@')) {
       
   449                 outStringList[i].remove(0, 1);
       
   450             } else {
       
   451                 QVariantList variantList;
       
   452                 for (int j = 0; j < l.count(); ++j)
       
   453                     variantList.append(stringToVariant(l.at(j)));
       
   454                 return variantList;
       
   455             }
       
   456         }
       
   457     }
       
   458     return outStringList;
       
   459 }
       
   460 
       
   461 QString QSettingsPrivate::variantToString(const QVariant &v)
       
   462 {
       
   463     QString result;
       
   464 
       
   465     switch (v.type()) {
       
   466         case QVariant::Invalid:
       
   467             result = QLatin1String("@Invalid()");
       
   468             break;
       
   469 
       
   470         case QVariant::ByteArray: {
       
   471             QByteArray a = v.toByteArray();
       
   472             result = QLatin1String("@ByteArray(");
       
   473             result += QString::fromLatin1(a.constData(), a.size());
       
   474             result += QLatin1Char(')');
       
   475             break;
       
   476         }
       
   477 
       
   478         case QVariant::String:
       
   479         case QVariant::LongLong:
       
   480         case QVariant::ULongLong:
       
   481         case QVariant::Int:
       
   482         case QVariant::UInt:
       
   483         case QVariant::Bool:
       
   484         case QVariant::Double:
       
   485         case QVariant::KeySequence: {
       
   486             result = v.toString();
       
   487             if (result.startsWith(QLatin1Char('@')))
       
   488                 result.prepend(QLatin1Char('@'));
       
   489             break;
       
   490         }
       
   491 #ifndef QT_NO_GEOM_VARIANT
       
   492         case QVariant::Rect: {
       
   493             QRect r = qvariant_cast<QRect>(v);
       
   494             result += QLatin1String("@Rect(");
       
   495             result += QString::number(r.x());
       
   496             result += QLatin1Char(' ');
       
   497             result += QString::number(r.y());
       
   498             result += QLatin1Char(' ');
       
   499             result += QString::number(r.width());
       
   500             result += QLatin1Char(' ');
       
   501             result += QString::number(r.height());
       
   502             result += QLatin1Char(')');
       
   503             break;
       
   504         }
       
   505         case QVariant::Size: {
       
   506             QSize s = qvariant_cast<QSize>(v);
       
   507             result += QLatin1String("@Size(");
       
   508             result += QString::number(s.width());
       
   509             result += QLatin1Char(' ');
       
   510             result += QString::number(s.height());
       
   511             result += QLatin1Char(')');
       
   512             break;
       
   513         }
       
   514         case QVariant::Point: {
       
   515             QPoint p = qvariant_cast<QPoint>(v);
       
   516             result += QLatin1String("@Point(");
       
   517             result += QString::number(p.x());
       
   518             result += QLatin1Char(' ');
       
   519             result += QString::number(p.y());
       
   520             result += QLatin1Char(')');
       
   521             break;
       
   522         }
       
   523 #endif // !QT_NO_GEOM_VARIANT
       
   524 
       
   525         default: {
       
   526 #ifndef QT_NO_DATASTREAM
       
   527             QByteArray a;
       
   528             {
       
   529                 QDataStream s(&a, QIODevice::WriteOnly);
       
   530                 s.setVersion(QDataStream::Qt_4_0);
       
   531                 s << v;
       
   532             }
       
   533 
       
   534             result = QLatin1String("@Variant(");
       
   535             result += QString::fromLatin1(a.constData(), a.size());
       
   536             result += QLatin1Char(')');
       
   537 #else
       
   538             Q_ASSERT(!"QSettings: Cannot save custom types without QDataStream support");
       
   539 #endif
       
   540             break;
       
   541         }
       
   542     }
       
   543 
       
   544     return result;
       
   545 }
       
   546 
       
   547 
       
   548 QVariant QSettingsPrivate::stringToVariant(const QString &s)
       
   549 {
       
   550     if (s.startsWith(QLatin1Char('@'))) {
       
   551         if (s.endsWith(QLatin1Char(')'))) {
       
   552             if (s.startsWith(QLatin1String("@ByteArray("))) {
       
   553                 return QVariant(s.toLatin1().mid(11, s.size() - 12));
       
   554             } else if (s.startsWith(QLatin1String("@Variant("))) {
       
   555 #ifndef QT_NO_DATASTREAM
       
   556                 QByteArray a(s.toLatin1().mid(9));
       
   557                 QDataStream stream(&a, QIODevice::ReadOnly);
       
   558                 stream.setVersion(QDataStream::Qt_4_0);
       
   559                 QVariant result;
       
   560                 stream >> result;
       
   561                 return result;
       
   562 #else
       
   563                 Q_ASSERT(!"QSettings: Cannot load custom types without QDataStream support");
       
   564 #endif
       
   565 #ifndef QT_NO_GEOM_VARIANT
       
   566             } else if (s.startsWith(QLatin1String("@Rect("))) {
       
   567                 QStringList args = QSettingsPrivate::splitArgs(s, 5);
       
   568                 if (args.size() == 4)
       
   569                     return QVariant(QRect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()));
       
   570             } else if (s.startsWith(QLatin1String("@Size("))) {
       
   571                 QStringList args = QSettingsPrivate::splitArgs(s, 5);
       
   572                 if (args.size() == 2)
       
   573                     return QVariant(QSize(args[0].toInt(), args[1].toInt()));
       
   574             } else if (s.startsWith(QLatin1String("@Point("))) {
       
   575                 QStringList args = QSettingsPrivate::splitArgs(s, 6);
       
   576                 if (args.size() == 2)
       
   577                     return QVariant(QPoint(args[0].toInt(), args[1].toInt()));
       
   578 #endif
       
   579             } else if (s == QLatin1String("@Invalid()")) {
       
   580                 return QVariant();
       
   581             }
       
   582 
       
   583         }
       
   584         if (s.startsWith(QLatin1String("@@")))
       
   585             return QVariant(s.mid(1));
       
   586     }
       
   587 
       
   588     return QVariant(s);
       
   589 }
       
   590 
       
   591 static const char hexDigits[] = "0123456789ABCDEF";
       
   592 
       
   593 void QSettingsPrivate::iniEscapedKey(const QString &key, QByteArray &result)
       
   594 {
       
   595     result.reserve(result.length() + key.length() * 3 / 2);
       
   596     for (int i = 0; i < key.size(); ++i) {
       
   597         uint ch = key.at(i).unicode();
       
   598 
       
   599         if (ch == '/') {
       
   600             result += '\\';
       
   601         } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')
       
   602                 || ch == '_' || ch == '-' || ch == '.') {
       
   603             result += (char)ch;
       
   604         } else if (ch <= 0xFF) {
       
   605             result += '%';
       
   606             result += hexDigits[ch / 16];
       
   607             result += hexDigits[ch % 16];
       
   608         } else {
       
   609             result += "%U";
       
   610             QByteArray hexCode;
       
   611             for (int i = 0; i < 4; ++i) {
       
   612                 hexCode.prepend(hexDigits[ch % 16]);
       
   613                 ch >>= 4;
       
   614             }
       
   615             result += hexCode;
       
   616         }
       
   617     }
       
   618 }
       
   619 
       
   620 bool QSettingsPrivate::iniUnescapedKey(const QByteArray &key, int from, int to, QString &result)
       
   621 {
       
   622     bool lowercaseOnly = true;
       
   623     int i = from;
       
   624     result.reserve(result.length() + (to - from));
       
   625     while (i < to) {
       
   626         int ch = (uchar)key.at(i);
       
   627 
       
   628         if (ch == '\\') {
       
   629             result += QLatin1Char('/');
       
   630             ++i;
       
   631             continue;
       
   632         }
       
   633 
       
   634         if (ch != '%' || i == to - 1) {
       
   635             if (uint(ch - 'A') <= 'Z' - 'A') // only for ASCII
       
   636                 lowercaseOnly = false;
       
   637             result += QLatin1Char(ch);
       
   638             ++i;
       
   639             continue;
       
   640         }
       
   641 
       
   642         int numDigits = 2;
       
   643         int firstDigitPos = i + 1;
       
   644 
       
   645         ch = key.at(i + 1);
       
   646         if (ch == 'U') {
       
   647             ++firstDigitPos;
       
   648             numDigits = 4;
       
   649         }
       
   650 
       
   651         if (firstDigitPos + numDigits > to) {
       
   652             result += QLatin1Char('%');
       
   653             // ### missing U
       
   654             ++i;
       
   655             continue;
       
   656         }
       
   657 
       
   658         bool ok;
       
   659         ch = key.mid(firstDigitPos, numDigits).toInt(&ok, 16);
       
   660         if (!ok) {
       
   661             result += QLatin1Char('%');
       
   662             // ### missing U
       
   663             ++i;
       
   664             continue;
       
   665         }
       
   666 
       
   667         QChar qch(ch);
       
   668         if (qch.isUpper())
       
   669             lowercaseOnly = false;
       
   670         result += qch;
       
   671         i = firstDigitPos + numDigits;
       
   672     }
       
   673     return lowercaseOnly;
       
   674 }
       
   675 
       
   676 void QSettingsPrivate::iniEscapedString(const QString &str, QByteArray &result, QTextCodec *codec)
       
   677 {
       
   678     bool needsQuotes = false;
       
   679     bool escapeNextIfDigit = false;
       
   680     int i;
       
   681     int startPos = result.size();
       
   682 
       
   683     result.reserve(startPos + str.size() * 3 / 2);
       
   684     for (i = 0; i < str.size(); ++i) {
       
   685         uint ch = str.at(i).unicode();
       
   686         if (ch == ';' || ch == ',' || ch == '=')
       
   687             needsQuotes = true;
       
   688 
       
   689         if (escapeNextIfDigit
       
   690                 && ((ch >= '0' && ch <= '9')
       
   691                     || (ch >= 'a' && ch <= 'f')
       
   692                     || (ch >= 'A' && ch <= 'F'))) {
       
   693             result += "\\x";
       
   694             result += QByteArray::number(ch, 16);
       
   695             continue;
       
   696         }
       
   697 
       
   698         escapeNextIfDigit = false;
       
   699 
       
   700         switch (ch) {
       
   701         case '\0':
       
   702             result += "\\0";
       
   703             escapeNextIfDigit = true;
       
   704             break;
       
   705         case '\a':
       
   706             result += "\\a";
       
   707             break;
       
   708         case '\b':
       
   709             result += "\\b";
       
   710             break;
       
   711         case '\f':
       
   712             result += "\\f";
       
   713             break;
       
   714         case '\n':
       
   715             result += "\\n";
       
   716             break;
       
   717         case '\r':
       
   718             result += "\\r";
       
   719             break;
       
   720         case '\t':
       
   721             result += "\\t";
       
   722             break;
       
   723         case '\v':
       
   724             result += "\\v";
       
   725             break;
       
   726         case '"':
       
   727         case '\\':
       
   728             result += '\\';
       
   729             result += (char)ch;
       
   730             break;
       
   731         default:
       
   732             if (ch <= 0x1F || (ch >= 0x7F && !codec)) {
       
   733                 result += "\\x";
       
   734                 result += QByteArray::number(ch, 16);
       
   735                 escapeNextIfDigit = true;
       
   736 #ifndef QT_NO_TEXTCODEC
       
   737             } else if (codec) {
       
   738                 // slow
       
   739                 result += codec->fromUnicode(str.at(i));
       
   740 #endif
       
   741             } else {
       
   742                 result += (char)ch;
       
   743             }
       
   744         }
       
   745     }
       
   746 
       
   747     if (needsQuotes
       
   748             || (startPos < result.size() && (result.at(startPos) == ' '
       
   749                                                 || result.at(result.size() - 1) == ' '))) {
       
   750         result.insert(startPos, '"');
       
   751         result += '"';
       
   752     }
       
   753 }
       
   754 
       
   755 inline static void iniChopTrailingSpaces(QString &str)
       
   756 {
       
   757     int n = str.size() - 1;
       
   758     QChar ch;
       
   759     while (n >= 0 && ((ch = str.at(n)) == QLatin1Char(' ') || ch == QLatin1Char('\t')))
       
   760         str.truncate(n--);
       
   761 }
       
   762 
       
   763 void QSettingsPrivate::iniEscapedStringList(const QStringList &strs, QByteArray &result, QTextCodec *codec)
       
   764 {
       
   765     if (strs.isEmpty()) {
       
   766         /*
       
   767             We need to distinguish between empty lists and one-item
       
   768             lists that contain an empty string. Ideally, we'd have a
       
   769             @EmptyList() symbol but that would break compatibility
       
   770             with Qt 4.0. @Invalid() stands for QVariant(), and
       
   771             QVariant().toStringList() returns an empty QStringList,
       
   772             so we're in good shape.
       
   773 
       
   774             ### Qt 5: Use a nicer syntax, e.g. @List, for variant lists
       
   775         */
       
   776         result += "@Invalid()";
       
   777     } else {
       
   778         for (int i = 0; i < strs.size(); ++i) {
       
   779             if (i != 0)
       
   780                 result += ", ";
       
   781             iniEscapedString(strs.at(i), result, codec);
       
   782         }
       
   783     }
       
   784 }
       
   785 
       
   786 bool QSettingsPrivate::iniUnescapedStringList(const QByteArray &str, int from, int to,
       
   787                                               QString &stringResult, QStringList &stringListResult,
       
   788                                               QTextCodec *codec)
       
   789 {
       
   790     static const char escapeCodes[][2] =
       
   791     {
       
   792         { 'a', '\a' },
       
   793         { 'b', '\b' },
       
   794         { 'f', '\f' },
       
   795         { 'n', '\n' },
       
   796         { 'r', '\r' },
       
   797         { 't', '\t' },
       
   798         { 'v', '\v' },
       
   799         { '"', '"' },
       
   800         { '?', '?' },
       
   801         { '\'', '\'' },
       
   802         { '\\', '\\' }
       
   803     };
       
   804     static const int numEscapeCodes = sizeof(escapeCodes) / sizeof(escapeCodes[0]);
       
   805 
       
   806     bool isStringList = false;
       
   807     bool inQuotedString = false;
       
   808     bool currentValueIsQuoted = false;
       
   809     int escapeVal = 0;
       
   810     int i = from;
       
   811     char ch;
       
   812 
       
   813 StSkipSpaces:
       
   814     while (i < to && ((ch = str.at(i)) == ' ' || ch == '\t'))
       
   815         ++i;
       
   816     // fallthrough
       
   817 
       
   818 StNormal:
       
   819     while (i < to) {
       
   820         switch (str.at(i)) {
       
   821         case '\\':
       
   822             ++i;
       
   823             if (i >= to)
       
   824                 goto end;
       
   825 
       
   826             ch = str.at(i++);
       
   827             for (int j = 0; j < numEscapeCodes; ++j) {
       
   828                 if (ch == escapeCodes[j][0]) {
       
   829                     stringResult += QLatin1Char(escapeCodes[j][1]);
       
   830                     goto StNormal;
       
   831                 }
       
   832             }
       
   833 
       
   834             if (ch == 'x') {
       
   835                 escapeVal = 0;
       
   836 
       
   837                 if (i >= to)
       
   838                     goto end;
       
   839 
       
   840                 ch = str.at(i);
       
   841                 if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'))
       
   842                     goto StHexEscape;
       
   843             } else if (ch >= '0' && ch <= '7') {
       
   844                 escapeVal = ch - '0';
       
   845                 goto StOctEscape;
       
   846             } else if (ch == '\n' || ch == '\r') {
       
   847                 if (i < to) {
       
   848                     char ch2 = str.at(i);
       
   849                     // \n, \r, \r\n, and \n\r are legitimate line terminators in INI files
       
   850                     if ((ch2 == '\n' || ch2 == '\r') && ch2 != ch)
       
   851                         ++i;
       
   852                 }
       
   853             } else {
       
   854                 // the character is skipped
       
   855             }
       
   856             break;
       
   857         case '"':
       
   858             ++i;
       
   859             currentValueIsQuoted = true;
       
   860             inQuotedString = !inQuotedString;
       
   861             if (!inQuotedString)
       
   862                 goto StSkipSpaces;
       
   863             break;
       
   864         case ',':
       
   865             if (!inQuotedString) {
       
   866                 if (!currentValueIsQuoted)
       
   867                     iniChopTrailingSpaces(stringResult);
       
   868                 if (!isStringList) {
       
   869                     isStringList = true;
       
   870                     stringListResult.clear();
       
   871                     stringResult.squeeze();
       
   872                 }
       
   873                 stringListResult.append(stringResult);
       
   874                 stringResult.clear();
       
   875                 currentValueIsQuoted = false;
       
   876                 ++i;
       
   877                 goto StSkipSpaces;
       
   878             }
       
   879             // fallthrough
       
   880         default: {
       
   881             int j = i + 1;
       
   882             while (j < to) {
       
   883                 ch = str.at(j);
       
   884                 if (ch == '\\' || ch == '"' || ch == ',')
       
   885                     break;
       
   886                 ++j;
       
   887             }
       
   888 
       
   889 #ifndef QT_NO_TEXTCODEC
       
   890             if (codec) {
       
   891                 stringResult += codec->toUnicode(str.constData() + i, j - i);
       
   892             } else
       
   893 #endif
       
   894             {
       
   895                 int n = stringResult.size();
       
   896                 stringResult.resize(n + (j - i));
       
   897                 QChar *resultData = stringResult.data() + n;
       
   898                 for (int k = i; k < j; ++k)
       
   899                     *resultData++ = QLatin1Char(str.at(k));
       
   900             }
       
   901             i = j;
       
   902         }
       
   903         }
       
   904     }
       
   905     goto end;
       
   906 
       
   907 StHexEscape:
       
   908     if (i >= to) {
       
   909         stringResult += QChar(escapeVal);
       
   910         goto end;
       
   911     }
       
   912 
       
   913     ch = str.at(i);
       
   914     if (ch >= 'a')
       
   915         ch -= 'a' - 'A';
       
   916     if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')) {
       
   917         escapeVal <<= 4;
       
   918         escapeVal += strchr(hexDigits, ch) - hexDigits;
       
   919         ++i;
       
   920         goto StHexEscape;
       
   921     } else {
       
   922         stringResult += QChar(escapeVal);
       
   923         goto StNormal;
       
   924     }
       
   925 
       
   926 StOctEscape:
       
   927     if (i >= to) {
       
   928         stringResult += QChar(escapeVal);
       
   929         goto end;
       
   930     }
       
   931 
       
   932     ch = str.at(i);
       
   933     if (ch >= '0' && ch <= '7') {
       
   934         escapeVal <<= 3;
       
   935         escapeVal += ch - '0';
       
   936         ++i;
       
   937         goto StOctEscape;
       
   938     } else {
       
   939         stringResult += QChar(escapeVal);
       
   940         goto StNormal;
       
   941     }
       
   942 
       
   943 end:
       
   944     if (!currentValueIsQuoted)
       
   945         iniChopTrailingSpaces(stringResult);
       
   946     if (isStringList)
       
   947         stringListResult.append(stringResult);
       
   948     return isStringList;
       
   949 }
       
   950 
       
   951 QStringList QSettingsPrivate::splitArgs(const QString &s, int idx)
       
   952 {
       
   953     int l = s.length();
       
   954     Q_ASSERT(l > 0);
       
   955     Q_ASSERT(s.at(idx) == QLatin1Char('('));
       
   956     Q_ASSERT(s.at(l - 1) == QLatin1Char(')'));
       
   957 
       
   958     QStringList result;
       
   959     QString item;
       
   960 
       
   961     for (++idx; idx < l; ++idx) {
       
   962         QChar c = s.at(idx);
       
   963         if (c == QLatin1Char(')')) {
       
   964             Q_ASSERT(idx == l - 1);
       
   965             result.append(item);
       
   966         } else if (c == QLatin1Char(' ')) {
       
   967             result.append(item);
       
   968             item.clear();
       
   969         } else {
       
   970             item.append(c);
       
   971         }
       
   972     }
       
   973 
       
   974     return result;
       
   975 }
       
   976 
       
   977 // ************************************************************************
       
   978 // QConfFileSettingsPrivate
       
   979 
       
   980 /*
       
   981     If we don't have the permission to read the file, returns false.
       
   982     If the file doesn't exist, returns true.
       
   983 */
       
   984 static bool checkAccess(const QString &name)
       
   985 {
       
   986     QFileInfo fileInfo(name);
       
   987 
       
   988     if (fileInfo.exists()) {
       
   989         QFile file(name);
       
   990         // if the file exists but we can't open it, report an error
       
   991         return file.open(QFile::ReadOnly);
       
   992     } else {
       
   993         return true;
       
   994     }
       
   995 }
       
   996 
       
   997 void QConfFileSettingsPrivate::initFormat()
       
   998 {
       
   999     extension = (format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini");
       
  1000     readFunc = 0;
       
  1001     writeFunc = 0;
       
  1002 #if defined(Q_OS_MAC)
       
  1003     caseSensitivity = (format == QSettings::NativeFormat) ? Qt::CaseSensitive : Qt::CaseInsensitive;
       
  1004 #else
       
  1005     caseSensitivity = IniCaseSensitivity;
       
  1006 #endif
       
  1007 
       
  1008     if (format > QSettings::IniFormat) {
       
  1009         QMutexLocker locker(globalMutex());
       
  1010         const CustomFormatVector *customFormatVector = customFormatVectorFunc();
       
  1011 
       
  1012         int i = (int)format - (int)QSettings::CustomFormat1;
       
  1013         if (i >= 0 && i < customFormatVector->size()) {
       
  1014             QConfFileCustomFormat info = customFormatVector->at(i);
       
  1015             extension = info.extension;
       
  1016             readFunc = info.readFunc;
       
  1017             writeFunc = info.writeFunc;
       
  1018             caseSensitivity = info.caseSensitivity;
       
  1019         }
       
  1020     }
       
  1021 }
       
  1022 
       
  1023 void QConfFileSettingsPrivate::initAccess()
       
  1024 {
       
  1025     bool readAccess = false;
       
  1026     if (confFiles[spec]) {
       
  1027         readAccess = checkAccess(confFiles[spec]->name);
       
  1028         if (format > QSettings::IniFormat) {
       
  1029             if (!readFunc)
       
  1030                 readAccess = false;
       
  1031         }
       
  1032     }
       
  1033 
       
  1034     if (!readAccess)
       
  1035         setStatus(QSettings::AccessError);
       
  1036 
       
  1037     sync();       // loads the files the first time
       
  1038 }
       
  1039 
       
  1040 #ifdef Q_OS_WIN
       
  1041 static QString windowsConfigPath(int type)
       
  1042 {
       
  1043     QString result;
       
  1044 
       
  1045 #ifndef QT_NO_QOBJECT
       
  1046     // We can't use QLibrary if there is QT_NO_QOBJECT is defined
       
  1047     // This only happens when bootstrapping qmake.
       
  1048 #ifndef Q_OS_WINCE
       
  1049     QLibrary library(QLatin1String("shell32"));
       
  1050 #else
       
  1051     QLibrary library(QLatin1String("coredll"));
       
  1052 #endif // Q_OS_WINCE
       
  1053     typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL);
       
  1054     GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW");
       
  1055     if (SHGetSpecialFolderPath) {
       
  1056         wchar_t path[MAX_PATH];
       
  1057         SHGetSpecialFolderPath(0, path, type, FALSE);
       
  1058         result = QString::fromWCharArray(path);
       
  1059     }
       
  1060 
       
  1061 #endif // QT_NO_QOBJECT
       
  1062 
       
  1063     if (result.isEmpty()) {
       
  1064         switch (type) {
       
  1065 #ifndef Q_OS_WINCE
       
  1066         case CSIDL_COMMON_APPDATA:
       
  1067             result = QLatin1String("C:\\temp\\qt-common");
       
  1068             break;
       
  1069         case CSIDL_APPDATA:
       
  1070             result = QLatin1String("C:\\temp\\qt-user");
       
  1071             break;
       
  1072 #else
       
  1073         case CSIDL_COMMON_APPDATA:
       
  1074             result = QLatin1String("\\Temp\\qt-common");
       
  1075             break;
       
  1076         case CSIDL_APPDATA:
       
  1077             result = QLatin1String("\\Temp\\qt-user");
       
  1078             break;
       
  1079 #endif
       
  1080         default:
       
  1081             ;
       
  1082         }
       
  1083     }
       
  1084 
       
  1085     return result;
       
  1086 }
       
  1087 #endif // Q_OS_WIN
       
  1088 
       
  1089 static inline int pathHashKey(QSettings::Format format, QSettings::Scope scope)
       
  1090 {
       
  1091     return int((uint(format) << 1) | uint(scope == QSettings::SystemScope));
       
  1092 }
       
  1093 
       
  1094 static QString getPath(QSettings::Format format, QSettings::Scope scope)
       
  1095 {
       
  1096     Q_ASSERT((int)QSettings::NativeFormat == 0);
       
  1097     Q_ASSERT((int)QSettings::IniFormat == 1);
       
  1098 
       
  1099     QString homePath = QDir::homePath();
       
  1100     QString systemPath;
       
  1101 
       
  1102     QMutexLocker locker(globalMutex());
       
  1103     PathHash *pathHash = pathHashFunc();
       
  1104     bool loadSystemPath = pathHash->isEmpty();
       
  1105     locker.unlock();
       
  1106 
       
  1107     if (loadSystemPath) {
       
  1108         /*
       
  1109            QLibraryInfo::location() uses QSettings, so in order to
       
  1110            avoid a dead-lock, we can't hold the global mutex while
       
  1111            calling it.
       
  1112        */
       
  1113         systemPath = QLibraryInfo::location(QLibraryInfo::SettingsPath);
       
  1114         systemPath += QLatin1Char('/');
       
  1115     }
       
  1116 
       
  1117     locker.relock();
       
  1118     if (pathHash->isEmpty()) {
       
  1119         /*
       
  1120            Lazy initialization of pathHash. We initialize the
       
  1121            IniFormat paths and (on Unix) the NativeFormat paths.
       
  1122            (The NativeFormat paths are not configurable for the
       
  1123            Windows registry and the Mac CFPreferences.)
       
  1124        */
       
  1125 #ifdef Q_OS_WIN
       
  1126         pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope),
       
  1127                          windowsConfigPath(CSIDL_APPDATA) + QDir::separator());
       
  1128         pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope),
       
  1129                          windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator());
       
  1130 #else
       
  1131         QString userPath;
       
  1132         char *env = getenv("XDG_CONFIG_HOME");
       
  1133         if (env == 0) {
       
  1134             userPath = homePath;
       
  1135             userPath += QLatin1Char('/');
       
  1136 #ifdef Q_WS_QWS
       
  1137             userPath += QLatin1String("Settings");
       
  1138 #else
       
  1139             userPath += QLatin1String(".config");
       
  1140 #endif
       
  1141         } else if (*env == '/') {
       
  1142             userPath = QLatin1String(env);
       
  1143         } else {
       
  1144             userPath = homePath;
       
  1145             userPath += QLatin1Char('/');
       
  1146             userPath += QLatin1String(env);
       
  1147         }
       
  1148         userPath += QLatin1Char('/');
       
  1149 
       
  1150         pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath);
       
  1151         pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), systemPath);
       
  1152 #ifndef Q_OS_MAC
       
  1153         pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), userPath);
       
  1154         pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), systemPath);
       
  1155 #endif
       
  1156 #endif
       
  1157     }
       
  1158 
       
  1159     QString result = pathHash->value(pathHashKey(format, scope));
       
  1160     if (!result.isEmpty())
       
  1161         return result;
       
  1162 
       
  1163     // fall back on INI path
       
  1164     return pathHash->value(pathHashKey(QSettings::IniFormat, scope));
       
  1165 }
       
  1166 
       
  1167 QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
       
  1168                                                    QSettings::Scope scope,
       
  1169                                                    const QString &organization,
       
  1170                                                    const QString &application)
       
  1171     : QSettingsPrivate(format, scope, organization, application),
       
  1172       nextPosition(0x40000000) // big positive number
       
  1173 {
       
  1174     int i;
       
  1175     initFormat();
       
  1176 
       
  1177     QString org = organization;
       
  1178     if (org.isEmpty()) {
       
  1179         setStatus(QSettings::AccessError);
       
  1180         org = QLatin1String("Unknown Organization");
       
  1181     }
       
  1182 
       
  1183     QString appFile = org + QDir::separator() + application + extension;
       
  1184     QString orgFile = org + extension;
       
  1185 
       
  1186     if (scope == QSettings::UserScope) {
       
  1187         QString userPath = getPath(format, QSettings::UserScope);
       
  1188         if (!application.isEmpty())
       
  1189             confFiles[F_User | F_Application].reset(QConfFile::fromName(userPath + appFile, true));
       
  1190         confFiles[F_User | F_Organization].reset(QConfFile::fromName(userPath + orgFile, true));
       
  1191     }
       
  1192 
       
  1193     QString systemPath = getPath(format, QSettings::SystemScope);
       
  1194     if (!application.isEmpty())
       
  1195         confFiles[F_System | F_Application].reset(QConfFile::fromName(systemPath + appFile, false));
       
  1196     confFiles[F_System | F_Organization].reset(QConfFile::fromName(systemPath + orgFile, false));
       
  1197 
       
  1198     for (i = 0; i < NumConfFiles; ++i) {
       
  1199         if (confFiles[i]) {
       
  1200             spec = i;
       
  1201             break;
       
  1202         }
       
  1203     }
       
  1204 
       
  1205     initAccess();
       
  1206 }
       
  1207 
       
  1208 QConfFileSettingsPrivate::QConfFileSettingsPrivate(const QString &fileName,
       
  1209                                                    QSettings::Format format)
       
  1210     : QSettingsPrivate(format),
       
  1211       nextPosition(0x40000000) // big positive number
       
  1212 {
       
  1213     initFormat();
       
  1214 
       
  1215     confFiles[0].reset(QConfFile::fromName(fileName, true));
       
  1216 
       
  1217     initAccess();
       
  1218 }
       
  1219 
       
  1220 QConfFileSettingsPrivate::~QConfFileSettingsPrivate()
       
  1221 {
       
  1222     QMutexLocker locker(globalMutex());
       
  1223     ConfFileHash *usedHash = usedHashFunc();
       
  1224     ConfFileCache *unusedCache = unusedCacheFunc();
       
  1225 
       
  1226     for (int i = 0; i < NumConfFiles; ++i) {
       
  1227         if (confFiles[i] && !confFiles[i]->ref.deref()) {
       
  1228             if (confFiles[i]->size == 0) {
       
  1229                 delete confFiles[i].take();
       
  1230             } else if (unusedCache) {
       
  1231                 if (usedHash)
       
  1232                     usedHash->remove(confFiles[i]->name);
       
  1233                 QT_TRY {
       
  1234                     // compute a better size?
       
  1235                     unusedCache->insert(confFiles[i]->name, confFiles[i].data(),
       
  1236                                     10 + (confFiles[i]->originalKeys.size() / 4));
       
  1237                     confFiles[i].take();
       
  1238                 } QT_CATCH(...) {
       
  1239                     // out of memory. Do not cache the file.
       
  1240                     delete confFiles[i].take();
       
  1241                 }
       
  1242             }
       
  1243         }
       
  1244         // prevent the ScopedPointer to deref it again.
       
  1245         confFiles[i].take();
       
  1246     }
       
  1247 }
       
  1248 
       
  1249 void QConfFileSettingsPrivate::remove(const QString &key)
       
  1250 {
       
  1251     QConfFile *confFile = confFiles[spec].data();
       
  1252     if (!confFile)
       
  1253         return;
       
  1254 
       
  1255     QSettingsKey theKey(key, caseSensitivity);
       
  1256     QSettingsKey prefix(key + QLatin1Char('/'), caseSensitivity);
       
  1257     QMutexLocker locker(&confFile->mutex);
       
  1258 
       
  1259     ensureSectionParsed(confFile, theKey);
       
  1260     ensureSectionParsed(confFile, prefix);
       
  1261 
       
  1262     ParsedSettingsMap::iterator i = confFile->addedKeys.lowerBound(prefix);
       
  1263     while (i != confFile->addedKeys.end() && i.key().startsWith(prefix))
       
  1264         i = confFile->addedKeys.erase(i);
       
  1265     confFile->addedKeys.remove(theKey);
       
  1266 
       
  1267     ParsedSettingsMap::const_iterator j = const_cast<const ParsedSettingsMap *>(&confFile->originalKeys)->lowerBound(prefix);
       
  1268     while (j != confFile->originalKeys.constEnd() && j.key().startsWith(prefix)) {
       
  1269         confFile->removedKeys.insert(j.key(), QVariant());
       
  1270         ++j;
       
  1271     }
       
  1272     if (confFile->originalKeys.contains(theKey))
       
  1273         confFile->removedKeys.insert(theKey, QVariant());
       
  1274 }
       
  1275 
       
  1276 void QConfFileSettingsPrivate::set(const QString &key, const QVariant &value)
       
  1277 {
       
  1278     QConfFile *confFile = confFiles[spec].data();
       
  1279     if (!confFile)
       
  1280         return;
       
  1281 
       
  1282     QSettingsKey theKey(key, caseSensitivity, nextPosition++);
       
  1283     QMutexLocker locker(&confFile->mutex);
       
  1284     confFile->removedKeys.remove(theKey);
       
  1285     confFile->addedKeys.insert(theKey, value);
       
  1286 }
       
  1287 
       
  1288 bool QConfFileSettingsPrivate::get(const QString &key, QVariant *value) const
       
  1289 {
       
  1290     QSettingsKey theKey(key, caseSensitivity);
       
  1291     ParsedSettingsMap::const_iterator j;
       
  1292     bool found = false;
       
  1293 
       
  1294     for (int i = 0; i < NumConfFiles; ++i) {
       
  1295         if (QConfFile *confFile = confFiles[i].data()) {
       
  1296             QMutexLocker locker(&confFile->mutex);
       
  1297 
       
  1298             if (!confFile->addedKeys.isEmpty()) {
       
  1299                 j = confFile->addedKeys.constFind(theKey);
       
  1300                 found = (j != confFile->addedKeys.constEnd());
       
  1301             }
       
  1302             if (!found) {
       
  1303                 ensureSectionParsed(confFile, theKey);
       
  1304                 j = confFile->originalKeys.constFind(theKey);
       
  1305                 found = (j != confFile->originalKeys.constEnd()
       
  1306                          && !confFile->removedKeys.contains(theKey));
       
  1307             }
       
  1308 
       
  1309             if (found && value)
       
  1310                 *value = *j;
       
  1311 
       
  1312             if (found)
       
  1313                 return true;
       
  1314             if (!fallbacks)
       
  1315                 break;
       
  1316         }
       
  1317     }
       
  1318     return false;
       
  1319 }
       
  1320 
       
  1321 QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec spec) const
       
  1322 {
       
  1323     QMap<QString, QString> result;
       
  1324     ParsedSettingsMap::const_iterator j;
       
  1325 
       
  1326     QSettingsKey thePrefix(prefix, caseSensitivity);
       
  1327     int startPos = prefix.size();
       
  1328 
       
  1329     for (int i = 0; i < NumConfFiles; ++i) {
       
  1330         if (QConfFile *confFile = confFiles[i].data()) {
       
  1331             QMutexLocker locker(&confFile->mutex);
       
  1332 
       
  1333             if (thePrefix.isEmpty()) {
       
  1334                 ensureAllSectionsParsed(confFile);
       
  1335             } else {
       
  1336                 ensureSectionParsed(confFile, thePrefix);
       
  1337             }
       
  1338 
       
  1339             j = const_cast<const ParsedSettingsMap *>(
       
  1340                     &confFile->originalKeys)->lowerBound( thePrefix);
       
  1341             while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) {
       
  1342                 if (!confFile->removedKeys.contains(j.key()))
       
  1343                     processChild(j.key().originalCaseKey().mid(startPos), spec, result);
       
  1344                 ++j;
       
  1345             }
       
  1346 
       
  1347             j = const_cast<const ParsedSettingsMap *>(
       
  1348                     &confFile->addedKeys)->lowerBound(thePrefix);
       
  1349             while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) {
       
  1350                 processChild(j.key().originalCaseKey().mid(startPos), spec, result);
       
  1351                 ++j;
       
  1352             }
       
  1353 
       
  1354             if (!fallbacks)
       
  1355                 break;
       
  1356         }
       
  1357     }
       
  1358     return result.keys();
       
  1359 }
       
  1360 
       
  1361 void QConfFileSettingsPrivate::clear()
       
  1362 {
       
  1363     QConfFile *confFile = confFiles[spec].data();
       
  1364     if (!confFile)
       
  1365         return;
       
  1366 
       
  1367     QMutexLocker locker(&confFile->mutex);
       
  1368     ensureAllSectionsParsed(confFile);
       
  1369     confFile->addedKeys.clear();
       
  1370     confFile->removedKeys = confFile->originalKeys;
       
  1371 }
       
  1372 
       
  1373 void QConfFileSettingsPrivate::sync()
       
  1374 {
       
  1375     // people probably won't be checking the status a whole lot, so in case of
       
  1376     // error we just try to go on and make the best of it
       
  1377 
       
  1378     for (int i = 0; i < NumConfFiles; ++i) {
       
  1379         QConfFile *confFile = confFiles[i].data();
       
  1380         if (confFile) {
       
  1381             QMutexLocker locker(&confFile->mutex);
       
  1382             syncConfFile(i);
       
  1383         }
       
  1384     }
       
  1385 }
       
  1386 
       
  1387 void QConfFileSettingsPrivate::flush()
       
  1388 {
       
  1389     sync();
       
  1390 }
       
  1391 
       
  1392 QString QConfFileSettingsPrivate::fileName() const
       
  1393 {
       
  1394     QConfFile *confFile = confFiles[spec].data();
       
  1395     if (!confFile)
       
  1396         return QString();
       
  1397     return confFile->name;
       
  1398 }
       
  1399 
       
  1400 bool QConfFileSettingsPrivate::isWritable() const
       
  1401 {
       
  1402     if (format > QSettings::IniFormat && !writeFunc)
       
  1403         return false;
       
  1404 
       
  1405     QConfFile *confFile = confFiles[spec].data();
       
  1406     if (!confFile)
       
  1407         return false;
       
  1408 
       
  1409     return confFile->isWritable();
       
  1410 }
       
  1411 
       
  1412 void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
       
  1413 {
       
  1414     QConfFile *confFile = confFiles[confFileNo].data();
       
  1415     bool readOnly = confFile->addedKeys.isEmpty() && confFile->removedKeys.isEmpty();
       
  1416     bool ok;
       
  1417 
       
  1418     /*
       
  1419         We can often optimize the read-only case, if the file on disk
       
  1420         hasn't changed.
       
  1421     */
       
  1422     if (readOnly) {
       
  1423         QFileInfo fileInfo(confFile->name);
       
  1424         if (confFile->size == fileInfo.size() && confFile->timeStamp == fileInfo.lastModified())
       
  1425             return;
       
  1426     }
       
  1427 
       
  1428     /*
       
  1429         Open the configuration file and try to use it using a named
       
  1430         semaphore on Windows and an advisory lock on Unix-based
       
  1431         systems. This protect us against other QSettings instances
       
  1432         trying to access the same file from other threads or
       
  1433         processes.
       
  1434 
       
  1435         As it stands now, the locking mechanism doesn't work for
       
  1436         .plist files.
       
  1437     */
       
  1438     QFile file(confFile->name);
       
  1439     bool createFile = !file.exists();
       
  1440     if (!readOnly && confFile->isWritable())
       
  1441         file.open(QFile::ReadWrite);
       
  1442     if (!file.isOpen())
       
  1443         file.open(QFile::ReadOnly);
       
  1444 
       
  1445 #ifdef Q_OS_WIN
       
  1446     HANDLE readSemaphore = 0;
       
  1447     HANDLE writeSemaphore = 0;
       
  1448     static const int FileLockSemMax = 50;
       
  1449     int numReadLocks = readOnly ? 1 : FileLockSemMax;
       
  1450 
       
  1451     if (file.isOpen()) {
       
  1452         // Acquire the write lock if we will be writing
       
  1453         if (!readOnly) {
       
  1454             QString writeSemName = QLatin1String("QSettingsWriteSem ");
       
  1455             writeSemName.append(file.fileName());
       
  1456 
       
  1457             writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()));
       
  1458 
       
  1459             if (writeSemaphore) {
       
  1460                 WaitForSingleObject(writeSemaphore, INFINITE);
       
  1461             } else {
       
  1462                 setStatus(QSettings::AccessError);
       
  1463                 return;
       
  1464             }
       
  1465         }
       
  1466 
       
  1467         // Acquire all the read locks if we will be writing, to make sure nobody
       
  1468         // reads while we're writing. If we are only reading, acquire a single
       
  1469         // read lock.
       
  1470         QString readSemName(QLatin1String("QSettingsReadSem "));
       
  1471         readSemName.append(file.fileName());
       
  1472 
       
  1473         readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()));
       
  1474 
       
  1475         if (readSemaphore) {
       
  1476             for (int i = 0; i < numReadLocks; ++i)
       
  1477                 WaitForSingleObject(readSemaphore, INFINITE);
       
  1478         } else {
       
  1479             setStatus(QSettings::AccessError);
       
  1480             if (writeSemaphore != 0) {
       
  1481                 ReleaseSemaphore(writeSemaphore, 1, 0);
       
  1482                 CloseHandle(writeSemaphore);
       
  1483             }
       
  1484             return;
       
  1485         }
       
  1486     }
       
  1487 #else
       
  1488     if (file.isOpen())
       
  1489         unixLock(file.handle(), readOnly ? F_RDLCK : F_WRLCK);
       
  1490 #endif
       
  1491 
       
  1492     // If we have created the file, apply the file perms
       
  1493     if (file.isOpen()) {
       
  1494         if (createFile) {
       
  1495             QFile::Permissions perms = file.permissions() | QFile::ReadOwner | QFile::WriteOwner;
       
  1496             if (!confFile->userPerms)
       
  1497                 perms |= QFile::ReadGroup | QFile::ReadOther;
       
  1498             file.setPermissions(perms);
       
  1499         }
       
  1500     }
       
  1501 
       
  1502     /*
       
  1503         We hold the lock. Let's reread the file if it has changed
       
  1504         since last time we read it.
       
  1505     */
       
  1506     QFileInfo fileInfo(confFile->name);
       
  1507     bool mustReadFile = true;
       
  1508 
       
  1509     if (!readOnly)
       
  1510         mustReadFile = (confFile->size != fileInfo.size()
       
  1511                         || (confFile->size != 0 && confFile->timeStamp != fileInfo.lastModified()));
       
  1512 
       
  1513     if (mustReadFile) {
       
  1514         confFile->unparsedIniSections.clear();
       
  1515         confFile->originalKeys.clear();
       
  1516 
       
  1517         /*
       
  1518             Files that we can't read (because of permissions or
       
  1519             because they don't exist) are treated as empty files.
       
  1520         */
       
  1521         if (file.isReadable() && fileInfo.size() != 0) {
       
  1522 #ifdef Q_OS_MAC
       
  1523             if (format == QSettings::NativeFormat) {
       
  1524                 ok = readPlistFile(confFile->name, &confFile->originalKeys);
       
  1525             } else
       
  1526 #endif
       
  1527             {
       
  1528                 if (format <= QSettings::IniFormat) {
       
  1529                     QByteArray data = file.readAll();
       
  1530                     ok = readIniFile(data, &confFile->unparsedIniSections);
       
  1531                 } else {
       
  1532                     if (readFunc) {
       
  1533                         QSettings::SettingsMap tempNewKeys;
       
  1534                         ok = readFunc(file, tempNewKeys);
       
  1535 
       
  1536                         if (ok) {
       
  1537                             QSettings::SettingsMap::const_iterator i = tempNewKeys.constBegin();
       
  1538                             while (i != tempNewKeys.constEnd()) {
       
  1539                                 confFile->originalKeys.insert(QSettingsKey(i.key(),
       
  1540                                                                            caseSensitivity),
       
  1541                                                               i.value());
       
  1542                                 ++i;
       
  1543                             }
       
  1544                         }
       
  1545                     } else {
       
  1546                         ok = false;
       
  1547                     }
       
  1548                 }
       
  1549             }
       
  1550 
       
  1551             if (!ok)
       
  1552                 setStatus(QSettings::FormatError);
       
  1553         }
       
  1554 
       
  1555         confFile->size = fileInfo.size();
       
  1556         confFile->timeStamp = fileInfo.lastModified();
       
  1557     }
       
  1558 
       
  1559     /*
       
  1560         We also need to save the file. We still hold the file lock,
       
  1561         so everything is under control.
       
  1562     */
       
  1563     if (!readOnly) {
       
  1564         ensureAllSectionsParsed(confFile);
       
  1565         ParsedSettingsMap mergedKeys = confFile->mergedKeyMap();
       
  1566 
       
  1567         if (file.isWritable()) {
       
  1568 #ifdef Q_OS_MAC
       
  1569             if (format == QSettings::NativeFormat) {
       
  1570                 ok = writePlistFile(confFile->name, mergedKeys);
       
  1571             } else
       
  1572 #endif
       
  1573             {
       
  1574                 file.seek(0);
       
  1575                 file.resize(0);
       
  1576 
       
  1577                 if (format <= QSettings::IniFormat) {
       
  1578                     ok = writeIniFile(file, mergedKeys);
       
  1579                     if (!ok) {
       
  1580                         // try to restore old data; might work if the disk was full and the new data
       
  1581                         // was larger than the old data
       
  1582                         file.seek(0);
       
  1583                         file.resize(0);
       
  1584                         writeIniFile(file, confFile->originalKeys);
       
  1585                     }
       
  1586                 } else {
       
  1587                     if (writeFunc) {
       
  1588                         QSettings::SettingsMap tempOriginalKeys;
       
  1589 
       
  1590                         ParsedSettingsMap::const_iterator i = mergedKeys.constBegin();
       
  1591                         while (i != mergedKeys.constEnd()) {
       
  1592                             tempOriginalKeys.insert(i.key(), i.value());
       
  1593                             ++i;
       
  1594                         }
       
  1595                         ok = writeFunc(file, tempOriginalKeys);
       
  1596                     } else {
       
  1597                         ok = false;
       
  1598                     }
       
  1599                 }
       
  1600             }
       
  1601         } else {
       
  1602             ok = false;
       
  1603         }
       
  1604 
       
  1605         if (ok) {
       
  1606             confFile->unparsedIniSections.clear();
       
  1607             confFile->originalKeys = mergedKeys;
       
  1608             confFile->addedKeys.clear();
       
  1609             confFile->removedKeys.clear();
       
  1610 
       
  1611             QFileInfo fileInfo(confFile->name);
       
  1612             confFile->size = fileInfo.size();
       
  1613             confFile->timeStamp = fileInfo.lastModified();
       
  1614         } else {
       
  1615             setStatus(QSettings::AccessError);
       
  1616         }
       
  1617     }
       
  1618 
       
  1619     /*
       
  1620         Release the file lock.
       
  1621     */
       
  1622 #ifdef Q_OS_WIN
       
  1623     if (readSemaphore != 0) {
       
  1624         ReleaseSemaphore(readSemaphore, numReadLocks, 0);
       
  1625         CloseHandle(readSemaphore);
       
  1626     }
       
  1627     if (writeSemaphore != 0) {
       
  1628         ReleaseSemaphore(writeSemaphore, 1, 0);
       
  1629         CloseHandle(writeSemaphore);
       
  1630     }
       
  1631 #endif
       
  1632 }
       
  1633 
       
  1634 enum { Space = 0x1, Special = 0x2 };
       
  1635 
       
  1636 static const char charTraits[256] =
       
  1637 {
       
  1638     // Space: '\t', '\n', '\r', ' '
       
  1639     // Special: '\n', '\r', '"', ';', '=', '\\'
       
  1640 
       
  1641     0, 0, 0, 0, 0, 0, 0, 0, 0, Space, Space | Special, 0, 0, Space | Special, 0, 0,
       
  1642     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1643     Space, 0, Special, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1644     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Special, 0, Special, 0, 0,
       
  1645     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1646     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Special, 0, 0, 0,
       
  1647     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1648     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1649 
       
  1650     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1651     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1652     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1653     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1654     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1655     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1656     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
  1657     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  1658 };
       
  1659 
       
  1660 bool QConfFileSettingsPrivate::readIniLine(const QByteArray &data, int &dataPos,
       
  1661                                            int &lineStart, int &lineLen, int &equalsPos)
       
  1662 {
       
  1663     int dataLen = data.length();
       
  1664     bool inQuotes = false;
       
  1665 
       
  1666     equalsPos = -1;
       
  1667 
       
  1668     lineStart = dataPos;
       
  1669     while (lineStart < dataLen && (charTraits[uint(uchar(data.at(lineStart)))] & Space))
       
  1670         ++lineStart;
       
  1671 
       
  1672     int i = lineStart;
       
  1673     while (i < dataLen) {
       
  1674         while (!(charTraits[uint(uchar(data.at(i)))] & Special)) {
       
  1675             if (++i == dataLen)
       
  1676                 goto break_out_of_outer_loop;
       
  1677         }
       
  1678 
       
  1679         char ch = data.at(i++);
       
  1680         if (ch == '=') {
       
  1681             if (!inQuotes && equalsPos == -1)
       
  1682                 equalsPos = i - 1;
       
  1683         } else if (ch == '\n' || ch == '\r') {
       
  1684             if (i == lineStart + 1) {
       
  1685                 ++lineStart;
       
  1686             } else if (!inQuotes) {
       
  1687                 --i;
       
  1688                 goto break_out_of_outer_loop;
       
  1689             }
       
  1690         } else if (ch == '\\') {
       
  1691             if (i < dataLen) {
       
  1692                 char ch = data.at(i++);
       
  1693                 if (i < dataLen) {
       
  1694                     char ch2 = data.at(i);
       
  1695                     // \n, \r, \r\n, and \n\r are legitimate line terminators in INI files
       
  1696                     if ((ch == '\n' && ch2 == '\r') || (ch == '\r' && ch2 == '\n'))
       
  1697                         ++i;
       
  1698                 }
       
  1699             }
       
  1700         } else if (ch == '"') {
       
  1701             inQuotes = !inQuotes;
       
  1702         } else {
       
  1703             Q_ASSERT(ch == ';');
       
  1704 
       
  1705             if (i == lineStart + 1) {
       
  1706                 char ch;
       
  1707                 while (i < dataLen && ((ch = data.at(i) != '\n') && ch != '\r'))
       
  1708                     ++i;
       
  1709                 lineStart = i;
       
  1710             } else if (!inQuotes) {
       
  1711                 --i;
       
  1712                 goto break_out_of_outer_loop;
       
  1713             }
       
  1714         }
       
  1715     }
       
  1716 
       
  1717 break_out_of_outer_loop:
       
  1718     dataPos = i;
       
  1719     lineLen = i - lineStart;
       
  1720     return lineLen > 0;
       
  1721 }
       
  1722 
       
  1723 /*
       
  1724     Returns false on parse error. However, as many keys are read as
       
  1725     possible, so if the user doesn't check the status he will get the
       
  1726     most out of the file anyway.
       
  1727 */
       
  1728 bool QConfFileSettingsPrivate::readIniFile(const QByteArray &data,
       
  1729                                            UnparsedSettingsMap *unparsedIniSections)
       
  1730 {
       
  1731 #define FLUSH_CURRENT_SECTION() \
       
  1732     { \
       
  1733         QByteArray &sectionData = (*unparsedIniSections)[QSettingsKey(currentSection, \
       
  1734                                                                       IniCaseSensitivity, \
       
  1735                                                                       sectionPosition)]; \
       
  1736         if (!sectionData.isEmpty()) \
       
  1737             sectionData.append('\n'); \
       
  1738         sectionData += data.mid(currentSectionStart, lineStart - currentSectionStart); \
       
  1739         sectionPosition = ++position; \
       
  1740     }
       
  1741 
       
  1742     QString currentSection;
       
  1743     int currentSectionStart = 0;
       
  1744     int dataPos = 0;
       
  1745     int lineStart;
       
  1746     int lineLen;
       
  1747     int equalsPos;
       
  1748     int position = 0;
       
  1749     int sectionPosition = 0;
       
  1750     bool ok = true;
       
  1751 
       
  1752     while (readIniLine(data, dataPos, lineStart, lineLen, equalsPos)) {
       
  1753         char ch = data.at(lineStart);
       
  1754         if (ch == '[') {
       
  1755             FLUSH_CURRENT_SECTION();
       
  1756 
       
  1757             // this is a section
       
  1758             QByteArray iniSection;
       
  1759             int idx = data.indexOf(']', lineStart);
       
  1760             if (idx == -1 || idx >= lineStart + lineLen) {
       
  1761                 ok = false;
       
  1762                 iniSection = data.mid(lineStart + 1, lineLen - 1);
       
  1763             } else {
       
  1764                 iniSection = data.mid(lineStart + 1, idx - lineStart - 1);
       
  1765             }
       
  1766 
       
  1767             iniSection = iniSection.trimmed();
       
  1768 
       
  1769             if (qstricmp(iniSection, "general") == 0) {
       
  1770                 currentSection.clear();
       
  1771             } else {
       
  1772                 if (qstricmp(iniSection, "%general") == 0) {
       
  1773                     currentSection = QLatin1String(iniSection.constData() + 1);
       
  1774                 } else {
       
  1775                     currentSection.clear();
       
  1776                     iniUnescapedKey(iniSection, 0, iniSection.size(), currentSection);
       
  1777                 }
       
  1778                 currentSection += QLatin1Char('/');
       
  1779             }
       
  1780             currentSectionStart = dataPos;
       
  1781         }
       
  1782         ++position;
       
  1783     }
       
  1784 
       
  1785     Q_ASSERT(lineStart == data.length());
       
  1786     FLUSH_CURRENT_SECTION();
       
  1787 
       
  1788     return ok;
       
  1789 
       
  1790 #undef FLUSH_CURRENT_SECTION
       
  1791 }
       
  1792 
       
  1793 bool QConfFileSettingsPrivate::readIniSection(const QSettingsKey &section, const QByteArray &data,
       
  1794                                               ParsedSettingsMap *settingsMap, QTextCodec *codec)
       
  1795 {
       
  1796     QStringList strListValue;
       
  1797     bool sectionIsLowercase = (section == section.originalCaseKey());
       
  1798     int equalsPos;
       
  1799 
       
  1800     bool ok = true;
       
  1801     int dataPos = 0;
       
  1802     int lineStart;
       
  1803     int lineLen;
       
  1804     int position = section.originalKeyPosition();
       
  1805 
       
  1806     while (readIniLine(data, dataPos, lineStart, lineLen, equalsPos)) {
       
  1807         char ch = data.at(lineStart);
       
  1808         Q_ASSERT(ch != '[');
       
  1809 
       
  1810         if (equalsPos == -1) {
       
  1811             if (ch != ';')
       
  1812                 ok = false;
       
  1813             continue;
       
  1814         }
       
  1815 
       
  1816         int keyEnd = equalsPos;
       
  1817         while (keyEnd > lineStart && ((ch = data.at(keyEnd - 1)) == ' ' || ch == '\t'))
       
  1818             --keyEnd;
       
  1819         int valueStart = equalsPos + 1;
       
  1820 
       
  1821         QString key = section.originalCaseKey();
       
  1822         bool keyIsLowercase = (iniUnescapedKey(data, lineStart, keyEnd, key) && sectionIsLowercase);
       
  1823 
       
  1824         QString strValue;
       
  1825         strValue.reserve(lineLen - (valueStart - lineStart));
       
  1826         bool isStringList = iniUnescapedStringList(data, valueStart, lineStart + lineLen,
       
  1827                                                    strValue, strListValue, codec);
       
  1828         QVariant variant;
       
  1829         if (isStringList) {
       
  1830             variant = stringListToVariantList(strListValue);
       
  1831         } else {
       
  1832             variant = stringToVariant(strValue);
       
  1833         }
       
  1834 
       
  1835         /*
       
  1836             We try to avoid the expensive toLower() call in
       
  1837             QSettingsKey by passing Qt::CaseSensitive when the
       
  1838             key is already in lowercase.
       
  1839         */
       
  1840         settingsMap->insert(QSettingsKey(key, keyIsLowercase ? Qt::CaseSensitive
       
  1841                                                              : IniCaseSensitivity,
       
  1842                                          position),
       
  1843                             variant);
       
  1844         ++position;
       
  1845     }
       
  1846 
       
  1847     return ok;
       
  1848 }
       
  1849 
       
  1850 class QSettingsIniKey : public QString
       
  1851 {
       
  1852 public:
       
  1853     inline QSettingsIniKey() : position(-1) {}
       
  1854     inline QSettingsIniKey(const QString &str, int pos = -1) : QString(str), position(pos) {}
       
  1855 
       
  1856     int position;
       
  1857 };
       
  1858 
       
  1859 static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
       
  1860 {
       
  1861     if (k1.position != k2.position)
       
  1862         return k1.position < k2.position;
       
  1863     return static_cast<const QString &>(k1) < static_cast<const QString &>(k2);
       
  1864 }
       
  1865 
       
  1866 typedef QMap<QSettingsIniKey, QVariant> IniKeyMap;
       
  1867 
       
  1868 struct QSettingsIniSection
       
  1869 {
       
  1870     int position;
       
  1871     IniKeyMap keyMap;
       
  1872 
       
  1873     inline QSettingsIniSection() : position(-1) {}
       
  1874 };
       
  1875 
       
  1876 typedef QMap<QString, QSettingsIniSection> IniMap;
       
  1877 
       
  1878 /*
       
  1879     This would be more straightforward if we didn't try to remember the original
       
  1880     key order in the .ini file, but we do.
       
  1881 */
       
  1882 bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSettingsMap &map)
       
  1883 {
       
  1884     IniMap iniMap;
       
  1885     IniMap::const_iterator i;
       
  1886 
       
  1887 #ifdef Q_OS_WIN
       
  1888     const char * const eol = "\r\n";
       
  1889 #else
       
  1890     const char eol = '\n';
       
  1891 #endif
       
  1892 
       
  1893     for (ParsedSettingsMap::const_iterator j = map.constBegin(); j != map.constEnd(); ++j) {
       
  1894         QString section;
       
  1895         QSettingsIniKey key(j.key().originalCaseKey(), j.key().originalKeyPosition());
       
  1896         int slashPos;
       
  1897 
       
  1898         if ((slashPos = key.indexOf(QLatin1Char('/'))) != -1) {
       
  1899             section = key.left(slashPos);
       
  1900             key.remove(0, slashPos + 1);
       
  1901         }
       
  1902 
       
  1903         QSettingsIniSection &iniSection = iniMap[section];
       
  1904 
       
  1905         // -1 means infinity
       
  1906         if (uint(key.position) < uint(iniSection.position))
       
  1907             iniSection.position = key.position;
       
  1908         iniSection.keyMap[key] = j.value();
       
  1909     }
       
  1910 
       
  1911     const int sectionCount = iniMap.size();
       
  1912     QVector<QSettingsIniKey> sections;
       
  1913     sections.reserve(sectionCount);
       
  1914     for (i = iniMap.constBegin(); i != iniMap.constEnd(); ++i)
       
  1915         sections.append(QSettingsIniKey(i.key(), i.value().position));
       
  1916     qSort(sections);
       
  1917 
       
  1918     bool writeError = false;
       
  1919     for (int j = 0; !writeError && j < sectionCount; ++j) {
       
  1920         i = iniMap.constFind(sections.at(j));
       
  1921         Q_ASSERT(i != iniMap.constEnd());
       
  1922 
       
  1923         QByteArray realSection;
       
  1924 
       
  1925         iniEscapedKey(i.key(), realSection);
       
  1926 
       
  1927         if (realSection.isEmpty()) {
       
  1928             realSection = "[General]";
       
  1929         } else if (qstricmp(realSection, "general") == 0) {
       
  1930             realSection = "[%General]";
       
  1931         } else {
       
  1932             realSection.prepend('[');
       
  1933             realSection.append(']');
       
  1934         }
       
  1935 
       
  1936         if (j != 0)
       
  1937             realSection.prepend(eol);
       
  1938         realSection += eol;
       
  1939 
       
  1940         device.write(realSection);
       
  1941 
       
  1942         const IniKeyMap &ents = i.value().keyMap;
       
  1943         for (IniKeyMap::const_iterator j = ents.constBegin(); j != ents.constEnd(); ++j) {
       
  1944             QByteArray block;
       
  1945             iniEscapedKey(j.key(), block);
       
  1946             block += '=';
       
  1947 
       
  1948             const QVariant &value = j.value();
       
  1949 
       
  1950             /*
       
  1951                 The size() != 1 trick is necessary because
       
  1952                 QVariant(QString("foo")).toList() returns an empty
       
  1953                 list, not a list containing "foo".
       
  1954             */
       
  1955             if (value.type() == QVariant::StringList
       
  1956                     || (value.type() == QVariant::List && value.toList().size() != 1)) {
       
  1957                 iniEscapedStringList(variantListToStringList(value.toList()), block, iniCodec);
       
  1958             } else {
       
  1959                 iniEscapedString(variantToString(value), block, iniCodec);
       
  1960             }
       
  1961             block += eol;
       
  1962             if (device.write(block) == -1) {
       
  1963                 writeError = true;
       
  1964                 break;
       
  1965             }
       
  1966         }
       
  1967     }
       
  1968     return !writeError;
       
  1969 }
       
  1970 
       
  1971 void QConfFileSettingsPrivate::ensureAllSectionsParsed(QConfFile *confFile) const
       
  1972 {
       
  1973     UnparsedSettingsMap::const_iterator i = confFile->unparsedIniSections.constBegin();
       
  1974     const UnparsedSettingsMap::const_iterator end = confFile->unparsedIniSections.constEnd();
       
  1975 
       
  1976     for (; i != end; ++i) {
       
  1977         if (!QConfFileSettingsPrivate::readIniSection(i.key(), i.value(), &confFile->originalKeys, iniCodec))
       
  1978             setStatus(QSettings::FormatError);
       
  1979     }
       
  1980     confFile->unparsedIniSections.clear();
       
  1981 }
       
  1982 
       
  1983 void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
       
  1984                                                    const QSettingsKey &key) const
       
  1985 {
       
  1986     if (confFile->unparsedIniSections.isEmpty())
       
  1987         return;
       
  1988 
       
  1989     UnparsedSettingsMap::iterator i;
       
  1990 
       
  1991     int indexOfSlash = key.indexOf(QLatin1Char('/'));
       
  1992     if (indexOfSlash != -1) {
       
  1993         i = confFile->unparsedIniSections.upperBound(key);
       
  1994         if (i == confFile->unparsedIniSections.begin())
       
  1995             return;
       
  1996         --i;
       
  1997         if (i.key().isEmpty() || !key.startsWith(i.key()))
       
  1998             return;
       
  1999     } else {
       
  2000         i = confFile->unparsedIniSections.begin();
       
  2001         if (i == confFile->unparsedIniSections.end() || !i.key().isEmpty())
       
  2002             return;
       
  2003     }
       
  2004 
       
  2005     if (!QConfFileSettingsPrivate::readIniSection(i.key(), i.value(), &confFile->originalKeys, iniCodec))
       
  2006         setStatus(QSettings::FormatError);
       
  2007     confFile->unparsedIniSections.erase(i);
       
  2008 }
       
  2009 
       
  2010 /*!
       
  2011     \class QSettings
       
  2012     \brief The QSettings class provides persistent platform-independent application settings.
       
  2013 
       
  2014     \ingroup io
       
  2015 
       
  2016     \reentrant
       
  2017 
       
  2018     Users normally expect an application to remember its settings
       
  2019     (window sizes and positions, options, etc.) across sessions. This
       
  2020     information is often stored in the system registry on Windows,
       
  2021     and in XML preferences files on Mac OS X. On Unix systems, in the
       
  2022     absence of a standard, many applications (including the KDE
       
  2023     applications) use INI text files.
       
  2024 
       
  2025     QSettings is an abstraction around these technologies, enabling
       
  2026     you to save and restore application settings in a portable
       
  2027     manner. It also supports \l{registerFormat()}{custom storage
       
  2028     formats}.
       
  2029 
       
  2030     QSettings's API is based on QVariant, allowing you to save
       
  2031     most value-based types, such as QString, QRect, and QImage,
       
  2032     with the minimum of effort.
       
  2033 
       
  2034     If all you need is a non-persistent memory-based structure,
       
  2035     consider using QMap<QString, QVariant> instead.
       
  2036 
       
  2037     \tableofcontents section1
       
  2038 
       
  2039     \section1 Basic Usage
       
  2040 
       
  2041     When creating a QSettings object, you must pass the name of your
       
  2042     company or organization as well as the name of your application.
       
  2043     For example, if your product is called Star Runner and your
       
  2044     company is called MySoft, you would construct the QSettings
       
  2045     object as follows:
       
  2046 
       
  2047     \snippet doc/src/snippets/settings/settings.cpp 0
       
  2048 
       
  2049     QSettings objects can be created either on the stack or on
       
  2050     the heap (i.e. using \c new). Constructing and destroying a
       
  2051     QSettings object is very fast.
       
  2052 
       
  2053     If you use QSettings from many places in your application, you
       
  2054     might want to specify the organization name and the application
       
  2055     name using QCoreApplication::setOrganizationName() and
       
  2056     QCoreApplication::setApplicationName(), and then use the default
       
  2057     QSettings constructor:
       
  2058 
       
  2059     \snippet doc/src/snippets/settings/settings.cpp 1
       
  2060     \snippet doc/src/snippets/settings/settings.cpp 2
       
  2061     \snippet doc/src/snippets/settings/settings.cpp 3
       
  2062     \dots
       
  2063     \snippet doc/src/snippets/settings/settings.cpp 4
       
  2064 
       
  2065     (Here, we also specify the organization's Internet domain. When
       
  2066     the Internet domain is set, it is used on Mac OS X instead of the
       
  2067     organization name, since Mac OS X applications conventionally use
       
  2068     Internet domains to identify themselves. If no domain is set, a
       
  2069     fake domain is derived from the organization name. See the
       
  2070     \l{Platform-Specific Notes} below for details.)
       
  2071 
       
  2072     QSettings stores settings. Each setting consists of a QString
       
  2073     that specifies the setting's name (the \e key) and a QVariant
       
  2074     that stores the data associated with the key. To write a setting,
       
  2075     use setValue(). For example:
       
  2076 
       
  2077     \snippet doc/src/snippets/settings/settings.cpp 5
       
  2078 
       
  2079     If there already exists a setting with the same key, the existing
       
  2080     value is overwritten by the new value. For efficiency, the
       
  2081     changes may not be saved to permanent storage immediately. (You
       
  2082     can always call sync() to commit your changes.)
       
  2083 
       
  2084     You can get a setting's value back using value():
       
  2085 
       
  2086     \snippet doc/src/snippets/settings/settings.cpp 6
       
  2087 
       
  2088     If there is no setting with the specified name, QSettings
       
  2089     returns a null QVariant (which can be converted to the integer 0).
       
  2090     You can specify another default value by passing a second
       
  2091     argument to value():
       
  2092 
       
  2093     \snippet doc/src/snippets/settings/settings.cpp 7
       
  2094 
       
  2095     To test whether a given key exists, call contains(). To remove
       
  2096     the setting associated with a key, call remove(). To obtain the
       
  2097     list of all keys, call allKeys(). To remove all keys, call
       
  2098     clear().
       
  2099 
       
  2100     \section1 QVariant and GUI Types
       
  2101 
       
  2102     Because QVariant is part of the \l QtCore library, it cannot provide
       
  2103     conversion functions to data types such as QColor, QImage, and
       
  2104     QPixmap, which are part of \l QtGui. In other words, there is no
       
  2105     \c toColor(), \c toImage(), or \c toPixmap() functions in QVariant.
       
  2106 
       
  2107     Instead, you can use the QVariant::value() or the qVariantValue()
       
  2108     template function. For example:
       
  2109 
       
  2110     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 0
       
  2111 
       
  2112     The inverse conversion (e.g., from QColor to QVariant) is
       
  2113     automatic for all data types supported by QVariant, including
       
  2114     GUI-related types:
       
  2115 
       
  2116     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 1
       
  2117 
       
  2118     Custom types registered using qRegisterMetaType() and
       
  2119     qRegisterMetaTypeStreamOperators() can be stored using QSettings.
       
  2120 
       
  2121     \section1 Section and Key Syntax
       
  2122 
       
  2123     Setting keys can contain any Unicode characters. The Windows
       
  2124     registry and INI files use case-insensitive keys, whereas the
       
  2125     Carbon Preferences API on Mac OS X uses case-sensitive keys. To
       
  2126     avoid portability problems, follow these simple rules:
       
  2127 
       
  2128     \list 1
       
  2129     \o Always refer to the same key using the same case. For example,
       
  2130        if you refer to a key as "text fonts" in one place in your
       
  2131        code, don't refer to it as "Text Fonts" somewhere else.
       
  2132 
       
  2133     \o Avoid key names that are identical except for the case. For
       
  2134        example, if you have a key called "MainWindow", don't try to
       
  2135        save another key as "mainwindow".
       
  2136 
       
  2137     \o Do not use slashes ('/' and '\\') in section or key names; the
       
  2138        backslash character is used to separate sub keys (see below). On
       
  2139        windows '\\' are converted by QSettings to '/', which makes
       
  2140        them identical.
       
  2141     \endlist
       
  2142 
       
  2143     You can form hierarchical keys using the '/' character as a
       
  2144     separator, similar to Unix file paths. For example:
       
  2145 
       
  2146     \snippet doc/src/snippets/settings/settings.cpp 8
       
  2147     \snippet doc/src/snippets/settings/settings.cpp 9
       
  2148     \snippet doc/src/snippets/settings/settings.cpp 10
       
  2149 
       
  2150     If you want to save or restore many settings with the same
       
  2151     prefix, you can specify the prefix using beginGroup() and call
       
  2152     endGroup() at the end. Here's the same example again, but this
       
  2153     time using the group mechanism:
       
  2154 
       
  2155     \snippet doc/src/snippets/settings/settings.cpp 11
       
  2156     \codeline
       
  2157     \snippet doc/src/snippets/settings/settings.cpp 12
       
  2158 
       
  2159     If a group is set using beginGroup(), the behavior of most
       
  2160     functions changes consequently. Groups can be set recursively.
       
  2161 
       
  2162     In addition to groups, QSettings also supports an "array"
       
  2163     concept. See beginReadArray() and beginWriteArray() for details.
       
  2164 
       
  2165     \section1 Fallback Mechanism
       
  2166 
       
  2167     Let's assume that you have created a QSettings object with the
       
  2168     organization name MySoft and the application name Star Runner.
       
  2169     When you look up a value, up to four locations are searched in
       
  2170     that order:
       
  2171 
       
  2172     \list 1
       
  2173     \o a user-specific location for the Star Runner application
       
  2174     \o a user-specific location for all applications by MySoft
       
  2175     \o a system-wide location for the Star Runner application
       
  2176     \o a system-wide location for all applications by MySoft
       
  2177     \endlist
       
  2178 
       
  2179     (See \l{Platform-Specific Notes} below for information on what
       
  2180     these locations are on the different platforms supported by Qt.)
       
  2181 
       
  2182     If a key cannot be found in the first location, the search goes
       
  2183     on in the second location, and so on. This enables you to store
       
  2184     system-wide or organization-wide settings and to override them on
       
  2185     a per-user or per-application basis. To turn off this mechanism,
       
  2186     call setFallbacksEnabled(false).
       
  2187 
       
  2188     Although keys from all four locations are available for reading,
       
  2189     only the first file (the user-specific location for the
       
  2190     application at hand) is accessible for writing. To write to any
       
  2191     of the other files, omit the application name and/or specify
       
  2192     QSettings::SystemScope (as opposed to QSettings::UserScope, the
       
  2193     default).
       
  2194 
       
  2195     Let's see with an example:
       
  2196 
       
  2197     \snippet doc/src/snippets/settings/settings.cpp 13
       
  2198     \snippet doc/src/snippets/settings/settings.cpp 14
       
  2199 
       
  2200     The table below summarizes which QSettings objects access
       
  2201     which location. "\bold{X}" means that the location is the main
       
  2202     location associated to the QSettings object and is used both
       
  2203     for reading and for writing; "o" means that the location is used
       
  2204     as a fallback when reading.
       
  2205 
       
  2206     \table
       
  2207     \header \o Locations               \o \c{obj1} \o \c{obj2} \o \c{obj3} \o \c{obj4}
       
  2208     \row    \o 1. User, Application    \o \bold{X} \o          \o          \o
       
  2209     \row    \o 2. User, Organization   \o o        \o \bold{X} \o          \o
       
  2210     \row    \o 3. System, Application  \o o        \o          \o \bold{X} \o
       
  2211     \row    \o 4. System, Organization \o o        \o o        \o o        \o \bold{X}
       
  2212     \endtable
       
  2213 
       
  2214     The beauty of this mechanism is that it works on all platforms
       
  2215     supported by Qt and that it still gives you a lot of flexibility,
       
  2216     without requiring you to specify any file names or registry
       
  2217     paths.
       
  2218 
       
  2219     If you want to use INI files on all platforms instead of the
       
  2220     native API, you can pass QSettings::IniFormat as the first
       
  2221     argument to the QSettings constructor, followed by the scope, the
       
  2222     organization name, and the application name:
       
  2223 
       
  2224     \snippet doc/src/snippets/settings/settings.cpp 15
       
  2225 
       
  2226     The \l{tools/settingseditor}{Settings Editor} example lets you
       
  2227     experiment with different settings location and with fallbacks
       
  2228     turned on or off.
       
  2229 
       
  2230     \section1 Restoring the State of a GUI Application
       
  2231 
       
  2232     QSettings is often used to store the state of a GUI
       
  2233     application. The following example illustrates how to use QSettings
       
  2234     to save and restore the geometry of an application's main window.
       
  2235 
       
  2236     \snippet doc/src/snippets/settings/settings.cpp 16
       
  2237     \codeline
       
  2238     \snippet doc/src/snippets/settings/settings.cpp 17
       
  2239 
       
  2240     See \l{Window Geometry} for a discussion on why it is better to
       
  2241     call QWidget::resize() and QWidget::move() rather than QWidget::setGeometry()
       
  2242     to restore a window's geometry.
       
  2243 
       
  2244     The \c readSettings() and \c writeSettings() functions must be
       
  2245     called from the main window's constructor and close event handler
       
  2246     as follows:
       
  2247 
       
  2248     \snippet doc/src/snippets/settings/settings.cpp 18
       
  2249     \dots
       
  2250     \snippet doc/src/snippets/settings/settings.cpp 19
       
  2251     \snippet doc/src/snippets/settings/settings.cpp 20
       
  2252     \codeline
       
  2253     \snippet doc/src/snippets/settings/settings.cpp 21
       
  2254 
       
  2255     See the \l{mainwindows/application}{Application} example for a
       
  2256     self-contained example that uses QSettings.
       
  2257 
       
  2258     \section1 Accessing Settings from Multiple Threads or Processes Simultaneously
       
  2259 
       
  2260     QSettings is \l{reentrant}. This means that you can use
       
  2261     distinct QSettings object in different threads
       
  2262     simultaneously. This guarantee stands even when the QSettings
       
  2263     objects refer to the same files on disk (or to the same entries
       
  2264     in the system registry). If a setting is modified through one
       
  2265     QSettings object, the change will immediately be visible in
       
  2266     any other QSettings objects that operate on the same location
       
  2267     and that live in the same process.
       
  2268 
       
  2269     QSettings can safely be used from different processes (which can
       
  2270     be different instances of your application running at the same
       
  2271     time or different applications altogether) to read and write to
       
  2272     the same system locations. It uses advisory file locking and a
       
  2273     smart merging algorithm to ensure data integrity. Changes
       
  2274     performed by another process aren't visible in the current
       
  2275     process until sync() is called.
       
  2276 
       
  2277     \section1 Platform-Specific Notes
       
  2278 
       
  2279     \section2 Locations Where Application Settings Are Stored
       
  2280 
       
  2281     As mentioned in the \l{Fallback Mechanism} section, QSettings
       
  2282     stores settings for an application in up to four locations,
       
  2283     depending on whether the settings are user-specific or
       
  2284     system-wide and whether the settings are application-specific
       
  2285     or organization-wide. For simplicity, we're assuming the
       
  2286     organization is called MySoft and the application is called Star
       
  2287     Runner.
       
  2288 
       
  2289     On Unix systems, if the file format is NativeFormat, the
       
  2290     following files are used by default:
       
  2291 
       
  2292     \list 1
       
  2293     \o \c{$HOME/.config/MySoft/Star Runner.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.conf})
       
  2294     \o \c{$HOME/.config/MySoft.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.conf})
       
  2295     \o \c{/etc/xdg/MySoft/Star Runner.conf}
       
  2296     \o \c{/etc/xdg/MySoft.conf}
       
  2297     \endlist
       
  2298 
       
  2299     On Mac OS X versions 10.2 and 10.3, these files are used by
       
  2300     default:
       
  2301 
       
  2302     \list 1
       
  2303     \o \c{$HOME/Library/Preferences/com.MySoft.Star Runner.plist}
       
  2304     \o \c{$HOME/Library/Preferences/com.MySoft.plist}
       
  2305     \o \c{/Library/Preferences/com.MySoft.Star Runner.plist}
       
  2306     \o \c{/Library/Preferences/com.MySoft.plist}
       
  2307     \endlist
       
  2308 
       
  2309     On Windows, NativeFormat settings are stored in the following
       
  2310     registry paths:
       
  2311 
       
  2312     \list 1
       
  2313     \o \c{HKEY_CURRENT_USER\Software\MySoft\Star Runner}
       
  2314     \o \c{HKEY_CURRENT_USER\Software\MySoft}
       
  2315     \o \c{HKEY_LOCAL_MACHINE\Software\MySoft\Star Runner}
       
  2316     \o \c{HKEY_LOCAL_MACHINE\Software\MySoft}
       
  2317     \endlist
       
  2318 
       
  2319     \note On Windows, for 32-bit programs running in WOW64 mode, settings are
       
  2320     stored in the following registry path:
       
  2321     \c{HKEY_LOCAL_MACHINE\Software\WOW6432node}.
       
  2322 
       
  2323     If the file format is IniFormat, the following files are
       
  2324     used on Unix and Mac OS X:
       
  2325 
       
  2326     \list 1
       
  2327     \o \c{$HOME/.config/MySoft/Star Runner.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.ini})
       
  2328     \o \c{$HOME/.config/MySoft.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.ini})
       
  2329     \o \c{/etc/xdg/MySoft/Star Runner.ini}
       
  2330     \o \c{/etc/xdg/MySoft.ini}
       
  2331     \endlist
       
  2332 
       
  2333     On Windows, the following files are used:
       
  2334 
       
  2335     \list 1
       
  2336     \o \c{%APPDATA%\MySoft\Star Runner.ini}
       
  2337     \o \c{%APPDATA%\MySoft.ini}
       
  2338     \o \c{%COMMON_APPDATA%\MySoft\Star Runner.ini}
       
  2339     \o \c{%COMMON_APPDATA%\MySoft.ini}
       
  2340     \endlist
       
  2341 
       
  2342     The \c %APPDATA% path is usually \tt{C:\\Documents and
       
  2343     Settings\\\e{User Name}\\Application Data}; the \c
       
  2344     %COMMON_APPDATA% path is usually \tt{C:\\Documents and
       
  2345     Settings\\All Users\\Application Data}.
       
  2346 
       
  2347     The paths for the \c .ini and \c .conf files can be changed using
       
  2348     setPath(). On Unix and Mac OS X, the user can override them by by
       
  2349     setting the \c XDG_CONFIG_HOME environment variable; see
       
  2350     setPath() for details.
       
  2351 
       
  2352     \section2 Accessing INI and .plist Files Directly
       
  2353 
       
  2354     Sometimes you do want to access settings stored in a specific
       
  2355     file or registry path. On all platforms, if you want to read an
       
  2356     INI file directly, you can use the QSettings constructor that
       
  2357     takes a file name as first argument and pass QSettings::IniFormat
       
  2358     as second argument. For example:
       
  2359 
       
  2360     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 2
       
  2361 
       
  2362     You can then use the QSettings object to read and write settings
       
  2363     in the file.
       
  2364 
       
  2365     On Mac OS X, you can access XML-based \c .plist files by passing
       
  2366     QSettings::NativeFormat as second argument. For example:
       
  2367 
       
  2368     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 3
       
  2369 
       
  2370     \section2 Accessing the Windows Registry Directly
       
  2371 
       
  2372     On Windows, QSettings lets you access settings that have been
       
  2373     written with QSettings (or settings in a supported format, e.g., string
       
  2374     data) in the system registry. This is done by constructing a QSettings
       
  2375     object with a path in the registry and QSettings::NativeFormat.
       
  2376 
       
  2377     For example:
       
  2378 
       
  2379     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 4
       
  2380 
       
  2381     All the registry entries that appear under the specified path can
       
  2382     be read or written through the QSettings object as usual (using
       
  2383     forward slashes instead of backslashes). For example:
       
  2384 
       
  2385     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 5
       
  2386 
       
  2387     Note that the backslash character is, as mentioned, used by
       
  2388     QSettings to separate subkeys. As a result, you cannot read or
       
  2389     write windows registry entries that contain slashes or
       
  2390     backslashes; you should use a native windows API if you need to do
       
  2391     so.
       
  2392 
       
  2393     \section2 Accessing Common Registry Settings on Windows
       
  2394 
       
  2395     On Windows, it is possible for a key to have both a value and subkeys.
       
  2396     Its default value is accessed by using "Default" or "." in
       
  2397     place of a subkey:
       
  2398 
       
  2399     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 6
       
  2400 
       
  2401     On other platforms than Windows, "Default" and "." would be
       
  2402     treated as regular subkeys.
       
  2403 
       
  2404     \section2 Platform Limitations
       
  2405 
       
  2406     While QSettings attempts to smooth over the differences between
       
  2407     the different supported platforms, there are still a few
       
  2408     differences that you should be aware of when porting your
       
  2409     application:
       
  2410 
       
  2411     \list
       
  2412     \o  The Windows system registry has the following limitations: A
       
  2413         subkey may not exceed 255 characters, an entry's value may
       
  2414         not exceed 16,383 characters, and all the values of a key may
       
  2415         not exceed 65,535 characters. One way to work around these
       
  2416         limitations is to store the settings using the IniFormat
       
  2417         instead of the NativeFormat.
       
  2418 
       
  2419     \o  On Mac OS X, allKeys() will return some extra keys for global
       
  2420         settings that apply to all applications. These keys can be
       
  2421         read using value() but cannot be changed, only shadowed.
       
  2422         Calling setFallbacksEnabled(false) will hide these global
       
  2423         settings.
       
  2424 
       
  2425     \o  On Mac OS X, the CFPreferences API used by QSettings expects
       
  2426         Internet domain names rather than organization names. To
       
  2427         provide a uniform API, QSettings derives a fake domain name
       
  2428         from the organization name (unless the organization name
       
  2429         already is a domain name, e.g. OpenOffice.org). The algorithm
       
  2430         appends ".com" to the company name and replaces spaces and
       
  2431         other illegal characters with hyphens. If you want to specify
       
  2432         a different domain name, call
       
  2433         QCoreApplication::setOrganizationDomain(),
       
  2434         QCoreApplication::setOrganizationName(), and
       
  2435         QCoreApplication::setApplicationName() in your \c main()
       
  2436         function and then use the default QSettings constructor.
       
  2437         Another solution is to use preprocessor directives, for
       
  2438         example:
       
  2439 
       
  2440         \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 7
       
  2441 
       
  2442     \o On Unix and Mac OS X systems, the advisory file locking is disabled
       
  2443        if NFS (or AutoFS or CacheFS) is detected to work around a bug in the
       
  2444        NFS fcntl() implementation, which hangs forever if statd or lockd aren't
       
  2445        running. Also, the locking isn't performed when accessing \c .plist
       
  2446        files.
       
  2447 
       
  2448     \endlist
       
  2449 
       
  2450     \sa QVariant, QSessionManager, {Settings Editor Example}, {Application Example}
       
  2451 */
       
  2452 
       
  2453 /*! \enum QSettings::Status
       
  2454 
       
  2455     The following status values are possible:
       
  2456 
       
  2457     \value NoError  No error occurred.
       
  2458     \value AccessError  An access error occurred (e.g. trying to write to a read-only file).
       
  2459     \value FormatError  A format error occurred (e.g. loading a malformed INI file).
       
  2460 
       
  2461     \sa status()
       
  2462 */
       
  2463 
       
  2464 /*! \enum QSettings::Format
       
  2465 
       
  2466     This enum type specifies the storage format used by QSettings.
       
  2467 
       
  2468     \value NativeFormat  Store the settings using the most
       
  2469                          appropriate storage format for the platform.
       
  2470                          On Windows, this means the system registry;
       
  2471                          on Mac OS X, this means the CFPreferences
       
  2472                          API; on Unix, this means textual
       
  2473                          configuration files in INI format.
       
  2474     \value IniFormat  Store the settings in INI files.
       
  2475     \value InvalidFormat Special value returned by registerFormat().
       
  2476     \omitvalue CustomFormat1
       
  2477     \omitvalue CustomFormat2
       
  2478     \omitvalue CustomFormat3
       
  2479     \omitvalue CustomFormat4
       
  2480     \omitvalue CustomFormat5
       
  2481     \omitvalue CustomFormat6
       
  2482     \omitvalue CustomFormat7
       
  2483     \omitvalue CustomFormat8
       
  2484     \omitvalue CustomFormat9
       
  2485     \omitvalue CustomFormat10
       
  2486     \omitvalue CustomFormat11
       
  2487     \omitvalue CustomFormat12
       
  2488     \omitvalue CustomFormat13
       
  2489     \omitvalue CustomFormat14
       
  2490     \omitvalue CustomFormat15
       
  2491     \omitvalue CustomFormat16
       
  2492 
       
  2493     On Unix, NativeFormat and IniFormat mean the same thing, except
       
  2494     that the file extension is different (\c .conf for NativeFormat,
       
  2495     \c .ini for IniFormat).
       
  2496 
       
  2497     The INI file format is a Windows file format that Qt supports on
       
  2498     all platforms. In the absence of an INI standard, we try to
       
  2499     follow what Microsoft does, with the following exceptions:
       
  2500 
       
  2501     \list
       
  2502     \o  If you store types that QVariant can't convert to QString
       
  2503         (e.g., QPoint, QRect, and QSize), Qt uses an \c{@}-based
       
  2504         syntax to encode the type. For example:
       
  2505 
       
  2506         \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 8
       
  2507 
       
  2508         To minimize compatibility issues, any \c @ that doesn't
       
  2509         appear at the first position in the value or that isn't
       
  2510         followed by a Qt type (\c Point, \c Rect, \c Size, etc.) is
       
  2511         treated as a normal character.
       
  2512 
       
  2513     \o  Although backslash is a special character in INI files, most
       
  2514         Windows applications don't escape backslashes (\c{\}) in file
       
  2515         paths:
       
  2516 
       
  2517         \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 9
       
  2518 
       
  2519         QSettings always treats backslash as a special character and
       
  2520         provides no API for reading or writing such entries.
       
  2521 
       
  2522     \o  The INI file format has severe restrictions on the syntax of
       
  2523         a key. Qt works around this by using \c % as an escape
       
  2524         character in keys. In addition, if you save a top-level
       
  2525         setting (a key with no slashes in it, e.g., "someKey"), it
       
  2526         will appear in the INI file's "General" section. To avoid
       
  2527         overwriting other keys, if you save something using the a key
       
  2528         such as "General/someKey", the key will be located in the
       
  2529         "%General" section, \e not in the "General" section.
       
  2530 
       
  2531     \o  Following the philosophy that we should be liberal in what
       
  2532         we accept and conservative in what we generate, QSettings
       
  2533         will accept Latin-1 encoded INI files, but generate pure
       
  2534         ASCII files, where non-ASCII values are encoded using standard
       
  2535         INI escape sequences. To make the INI files more readable (but
       
  2536         potentially less compatible), call setIniCodec().
       
  2537     \endlist
       
  2538 
       
  2539     \sa registerFormat(), setPath()
       
  2540 */
       
  2541 
       
  2542 /*! \enum QSettings::Scope
       
  2543 
       
  2544     This enum specifies whether settings are user-specific or shared
       
  2545     by all users of the same system.
       
  2546 
       
  2547     \value UserScope  Store settings in a location specific to the
       
  2548                       current user (e.g., in the user's home
       
  2549                       directory).
       
  2550     \value SystemScope  Store settings in a global location, so that
       
  2551                         all users on the same machine access the same
       
  2552                         set of settings.
       
  2553     \omitvalue User
       
  2554     \omitvalue Global
       
  2555 
       
  2556     \sa setPath()
       
  2557 */
       
  2558 
       
  2559 #ifndef QT_NO_QOBJECT
       
  2560 /*!
       
  2561     Constructs a QSettings object for accessing settings of the
       
  2562     application called \a application from the organization called \a
       
  2563     organization, and with parent \a parent.
       
  2564 
       
  2565     Example:
       
  2566     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 10
       
  2567 
       
  2568     The scope is set to QSettings::UserScope, and the format is
       
  2569     set to QSettings::NativeFormat (i.e. calling setDefaultFormat()
       
  2570     before calling this constructor has no effect).
       
  2571 
       
  2572     \sa setDefaultFormat(), {Fallback Mechanism}
       
  2573 */
       
  2574 QSettings::QSettings(const QString &organization, const QString &application, QObject *parent)
       
  2575     : QObject(*QSettingsPrivate::create(NativeFormat, UserScope, organization, application),
       
  2576               parent)
       
  2577 {
       
  2578 }
       
  2579 
       
  2580 /*!
       
  2581     Constructs a QSettings object for accessing settings of the
       
  2582     application called \a application from the organization called \a
       
  2583     organization, and with parent \a parent.
       
  2584 
       
  2585     If \a scope is QSettings::UserScope, the QSettings object searches
       
  2586     user-specific settings first, before it searches system-wide
       
  2587     settings as a fallback. If \a scope is QSettings::SystemScope, the
       
  2588     QSettings object ignores user-specific settings and provides
       
  2589     access to system-wide settings.
       
  2590 
       
  2591     The storage format is set to QSettings::NativeFormat (i.e. calling
       
  2592     setDefaultFormat() before calling this constructor has no effect).
       
  2593 
       
  2594     If no application name is given, the QSettings object will
       
  2595     only access the organization-wide \l{Fallback Mechanism}{locations}.
       
  2596 
       
  2597     \sa setDefaultFormat()
       
  2598 */
       
  2599 QSettings::QSettings(Scope scope, const QString &organization, const QString &application,
       
  2600                      QObject *parent)
       
  2601     : QObject(*QSettingsPrivate::create(NativeFormat, scope, organization, application), parent)
       
  2602 {
       
  2603 }
       
  2604 
       
  2605 /*!
       
  2606     Constructs a QSettings object for accessing settings of the
       
  2607     application called \a application from the organization called
       
  2608     \a organization, and with parent \a parent.
       
  2609 
       
  2610     If \a scope is QSettings::UserScope, the QSettings object searches
       
  2611     user-specific settings first, before it searches system-wide
       
  2612     settings as a fallback. If \a scope is
       
  2613     QSettings::SystemScope, the QSettings object ignores user-specific
       
  2614     settings and provides access to system-wide settings.
       
  2615 
       
  2616     If \a format is QSettings::NativeFormat, the native API is used for
       
  2617     storing settings. If \a format is QSettings::IniFormat, the INI format
       
  2618     is used.
       
  2619 
       
  2620     If no application name is given, the QSettings object will
       
  2621     only access the organization-wide \l{Fallback Mechanism}{locations}.
       
  2622 */
       
  2623 QSettings::QSettings(Format format, Scope scope, const QString &organization,
       
  2624                      const QString &application, QObject *parent)
       
  2625     : QObject(*QSettingsPrivate::create(format, scope, organization, application), parent)
       
  2626 {
       
  2627 }
       
  2628 
       
  2629 /*!
       
  2630     Constructs a QSettings object for accessing the settings
       
  2631     stored in the file called \a fileName, with parent \a parent. If
       
  2632     the file doesn't already exist, it is created.
       
  2633 
       
  2634     If \a format is QSettings::NativeFormat, the meaning of \a
       
  2635     fileName depends on the platform. On Unix, \a fileName is the
       
  2636     name of an INI file. On Mac OS X, \a fileName is the name of a
       
  2637     \c .plist file. On Windows, \a fileName is a path in the system
       
  2638     registry.
       
  2639 
       
  2640     If \a format is QSettings::IniFormat, \a fileName is the name of an INI
       
  2641     file.
       
  2642 
       
  2643     \warning This function is provided for convenience. It works well for
       
  2644     accessing INI or \c .plist files generated by Qt, but might fail on some
       
  2645     syntaxes found in such files originated by other programs. In particular,
       
  2646     be aware of the following limitations:
       
  2647 
       
  2648     \list
       
  2649     \o QSettings provides no way of reading INI "path" entries, i.e., entries
       
  2650        with unescaped slash characters. (This is because these entries are
       
  2651        ambiguous and cannot be resolved automatically.)
       
  2652     \o In INI files, QSettings uses the \c @ character as a metacharacter in some
       
  2653        contexts, to encode Qt-specific data types (e.g., \c @Rect), and might
       
  2654        therefore misinterpret it when it occurs in pure INI files.
       
  2655     \endlist
       
  2656 
       
  2657     \sa fileName()
       
  2658 */
       
  2659 QSettings::QSettings(const QString &fileName, Format format, QObject *parent)
       
  2660     : QObject(*QSettingsPrivate::create(fileName, format), parent)
       
  2661 {
       
  2662 }
       
  2663 
       
  2664 /*!
       
  2665     Constructs a QSettings object for accessing settings of the
       
  2666     application and organization set previously with a call to
       
  2667     QCoreApplication::setOrganizationName(),
       
  2668     QCoreApplication::setOrganizationDomain(), and
       
  2669     QCoreApplication::setApplicationName().
       
  2670 
       
  2671     The scope is QSettings::UserScope and the format is
       
  2672     defaultFormat() (QSettings::NativeFormat by default).
       
  2673     Use setDefaultFormat() before calling this constructor
       
  2674     to change the default format used by this constructor.
       
  2675 
       
  2676     The code
       
  2677 
       
  2678     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 11
       
  2679 
       
  2680     is equivalent to
       
  2681 
       
  2682     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 12
       
  2683 
       
  2684     If QCoreApplication::setOrganizationName() and
       
  2685     QCoreApplication::setApplicationName() has not been previously
       
  2686     called, the QSettings object will not be able to read or write
       
  2687     any settings, and status() will return AccessError.
       
  2688 
       
  2689     On Mac OS X, if both a name and an Internet domain are specified
       
  2690     for the organization, the domain is preferred over the name. On
       
  2691     other platforms, the name is preferred over the domain.
       
  2692 
       
  2693     \sa QCoreApplication::setOrganizationName(),
       
  2694         QCoreApplication::setOrganizationDomain(),
       
  2695         QCoreApplication::setApplicationName(),
       
  2696         setDefaultFormat()
       
  2697 */
       
  2698 QSettings::QSettings(QObject *parent)
       
  2699     : QObject(*QSettingsPrivate::create(globalDefaultFormat, UserScope,
       
  2700 #ifdef Q_OS_MAC
       
  2701                                         QCoreApplication::organizationDomain().isEmpty()
       
  2702                                             ? QCoreApplication::organizationName()
       
  2703                                             : QCoreApplication::organizationDomain()
       
  2704 #else
       
  2705                                         QCoreApplication::organizationName().isEmpty()
       
  2706                                             ? QCoreApplication::organizationDomain()
       
  2707                                             : QCoreApplication::organizationName()
       
  2708 #endif
       
  2709                                         , QCoreApplication::applicationName()),
       
  2710               parent)
       
  2711 {
       
  2712 }
       
  2713 
       
  2714 #else
       
  2715 QSettings::QSettings(const QString &organization, const QString &application)
       
  2716     : d_ptr(QSettingsPrivate::create(globalDefaultFormat, QSettings::UserScope, organization, application))
       
  2717 {
       
  2718     d_ptr->q_ptr = this;
       
  2719 }
       
  2720 
       
  2721 QSettings::QSettings(Scope scope, const QString &organization, const QString &application)
       
  2722     : d_ptr(QSettingsPrivate::create(globalDefaultFormat, scope, organization, application))
       
  2723 {
       
  2724     d_ptr->q_ptr = this;
       
  2725 }
       
  2726 
       
  2727 QSettings::QSettings(Format format, Scope scope, const QString &organization,
       
  2728                      const QString &application)
       
  2729     : d_ptr(QSettingsPrivate::create(format, scope, organization, application))
       
  2730 {
       
  2731     d_ptr->q_ptr = this;
       
  2732 }
       
  2733 
       
  2734 QSettings::QSettings(const QString &fileName, Format format)
       
  2735     : d_ptr(QSettingsPrivate::create(fileName, format))
       
  2736 {
       
  2737     d_ptr->q_ptr = this;
       
  2738 }
       
  2739 #endif
       
  2740 
       
  2741 /*!
       
  2742     Destroys the QSettings object.
       
  2743 
       
  2744     Any unsaved changes will eventually be written to permanent
       
  2745     storage.
       
  2746 
       
  2747     \sa sync()
       
  2748 */
       
  2749 QSettings::~QSettings()
       
  2750 {
       
  2751     Q_D(QSettings);
       
  2752     if (d->pendingChanges) {
       
  2753         QT_TRY {
       
  2754             d->flush();
       
  2755         } QT_CATCH(...) {
       
  2756             ; // ok. then don't flush but at least don't throw in the destructor
       
  2757         }
       
  2758     }
       
  2759 }
       
  2760 
       
  2761 /*!
       
  2762     Removes all entries in the primary location associated to this
       
  2763     QSettings object.
       
  2764 
       
  2765     Entries in fallback locations are not removed.
       
  2766 
       
  2767     If you only want to remove the entries in the current group(),
       
  2768     use remove("") instead.
       
  2769 
       
  2770     \sa remove(), setFallbacksEnabled()
       
  2771 */
       
  2772 void QSettings::clear()
       
  2773 {
       
  2774     Q_D(QSettings);
       
  2775     d->clear();
       
  2776     d->requestUpdate();
       
  2777 }
       
  2778 
       
  2779 /*!
       
  2780     Writes any unsaved changes to permanent storage, and reloads any
       
  2781     settings that have been changed in the meantime by another
       
  2782     application.
       
  2783 
       
  2784     This function is called automatically from QSettings's destructor and
       
  2785     by the event loop at regular intervals, so you normally don't need to
       
  2786     call it yourself.
       
  2787 
       
  2788     \sa status()
       
  2789 */
       
  2790 void QSettings::sync()
       
  2791 {
       
  2792     Q_D(QSettings);
       
  2793     d->sync();
       
  2794 }
       
  2795 
       
  2796 /*!
       
  2797     Returns the path where settings written using this QSettings
       
  2798     object are stored.
       
  2799 
       
  2800     On Windows, if the format is QSettings::NativeFormat, the return value
       
  2801     is a system registry path, not a file path.
       
  2802 
       
  2803     \sa isWritable(), format()
       
  2804 */
       
  2805 QString QSettings::fileName() const
       
  2806 {
       
  2807     Q_D(const QSettings);
       
  2808     return d->fileName();
       
  2809 }
       
  2810 
       
  2811 /*!
       
  2812     \since 4.4
       
  2813 
       
  2814     Returns the format used for storing the settings.
       
  2815 
       
  2816     \sa defaultFormat(), fileName(), scope(), organizationName(), applicationName()
       
  2817 */
       
  2818 QSettings::Format QSettings::format() const
       
  2819 {
       
  2820     Q_D(const QSettings);
       
  2821     return d->format;
       
  2822 }
       
  2823 
       
  2824 /*!
       
  2825     \since 4.4
       
  2826 
       
  2827     Returns the scope used for storing the settings.
       
  2828 
       
  2829     \sa format(), organizationName(), applicationName()
       
  2830 */
       
  2831 QSettings::Scope QSettings::scope() const
       
  2832 {
       
  2833     Q_D(const QSettings);
       
  2834     return d->scope;
       
  2835 }
       
  2836 
       
  2837 /*!
       
  2838     \since 4.4
       
  2839 
       
  2840     Returns the organization name used for storing the settings.
       
  2841 
       
  2842     \sa QCoreApplication::organizationName(), format(), scope(), applicationName()
       
  2843 */
       
  2844 QString QSettings::organizationName() const
       
  2845 {
       
  2846     Q_D(const QSettings);
       
  2847     return d->organizationName;
       
  2848 }
       
  2849 
       
  2850 /*!
       
  2851     \since 4.4
       
  2852 
       
  2853     Returns the application name used for storing the settings.
       
  2854 
       
  2855     \sa QCoreApplication::applicationName(), format(), scope(), organizationName()
       
  2856 */
       
  2857 QString QSettings::applicationName() const
       
  2858 {
       
  2859     Q_D(const QSettings);
       
  2860     return d->applicationName;
       
  2861 }
       
  2862 
       
  2863 #ifndef QT_NO_TEXTCODEC
       
  2864 
       
  2865 /*!
       
  2866     \since 4.5
       
  2867 
       
  2868     Sets the codec for accessing INI files (including \c .conf files on Unix)
       
  2869     to \a codec. The codec is used for decoding any data that is read from
       
  2870     the INI file, and for encoding any data that is written to the file. By
       
  2871     default, no codec is used, and non-ASCII characters are encoded using
       
  2872     standard INI escape sequences.
       
  2873 
       
  2874     \warning The codec must be set immediately after creating the QSettings
       
  2875     object, before accessing any data.
       
  2876 
       
  2877     \sa iniCodec()
       
  2878 */
       
  2879 void QSettings::setIniCodec(QTextCodec *codec)
       
  2880 {
       
  2881     Q_D(QSettings);
       
  2882     d->iniCodec = codec;
       
  2883 }
       
  2884 
       
  2885 /*!
       
  2886     \since 4.5
       
  2887     \overload
       
  2888 
       
  2889     Sets the codec for accessing INI files (including \c .conf files on Unix)
       
  2890     to the QTextCodec for the encoding specified by \a codecName. Common
       
  2891     values for \c codecName include "ISO 8859-1", "UTF-8", and "UTF-16".
       
  2892     If the encoding isn't recognized, nothing happens.
       
  2893 
       
  2894     \sa QTextCodec::codecForName()
       
  2895 */
       
  2896 void QSettings::setIniCodec(const char *codecName)
       
  2897 {
       
  2898     Q_D(QSettings);
       
  2899     if (QTextCodec *codec = QTextCodec::codecForName(codecName))
       
  2900         d->iniCodec = codec;
       
  2901 }
       
  2902 
       
  2903 /*!
       
  2904     \since 4.5
       
  2905 
       
  2906     Returns the codec that is used for accessing INI files. By default,
       
  2907     no codec is used, so a null pointer is returned.
       
  2908 */
       
  2909 
       
  2910 QTextCodec *QSettings::iniCodec() const
       
  2911 {
       
  2912     Q_D(const QSettings);
       
  2913     return d->iniCodec;
       
  2914 }
       
  2915 
       
  2916 #endif // QT_NO_TEXTCODEC
       
  2917 
       
  2918 /*!
       
  2919     Returns a status code indicating the first error that was met by
       
  2920     QSettings, or QSettings::NoError if no error occurred.
       
  2921 
       
  2922     Be aware that QSettings delays performing some operations. For this
       
  2923     reason, you might want to call sync() to ensure that the data stored
       
  2924     in QSettings is written to disk before calling status().
       
  2925 
       
  2926     \sa sync()
       
  2927 */
       
  2928 QSettings::Status QSettings::status() const
       
  2929 {
       
  2930     Q_D(const QSettings);
       
  2931     return d->status;
       
  2932 }
       
  2933 
       
  2934 /*!
       
  2935     Appends \a prefix to the current group.
       
  2936 
       
  2937     The current group is automatically prepended to all keys
       
  2938     specified to QSettings. In addition, query functions such as
       
  2939     childGroups(), childKeys(), and allKeys() are based on the group.
       
  2940     By default, no group is set.
       
  2941 
       
  2942     Groups are useful to avoid typing in the same setting paths over
       
  2943     and over. For example:
       
  2944 
       
  2945     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 13
       
  2946 
       
  2947     This will set the value of three settings:
       
  2948 
       
  2949     \list
       
  2950     \o \c mainwindow/size
       
  2951     \o \c mainwindow/fullScreen
       
  2952     \o \c outputpanel/visible
       
  2953     \endlist
       
  2954 
       
  2955     Call endGroup() to reset the current group to what it was before
       
  2956     the corresponding beginGroup() call. Groups can be nested.
       
  2957 
       
  2958     \sa endGroup(), group()
       
  2959 */
       
  2960 void QSettings::beginGroup(const QString &prefix)
       
  2961 {
       
  2962     Q_D(QSettings);
       
  2963     d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix)));
       
  2964 }
       
  2965 
       
  2966 /*!
       
  2967     Resets the group to what it was before the corresponding
       
  2968     beginGroup() call.
       
  2969 
       
  2970     Example:
       
  2971 
       
  2972     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 14
       
  2973 
       
  2974     \sa beginGroup(), group()
       
  2975 */
       
  2976 void QSettings::endGroup()
       
  2977 {
       
  2978     Q_D(QSettings);
       
  2979     if (d->groupStack.isEmpty()) {
       
  2980         qWarning("QSettings::endGroup: No matching beginGroup()");
       
  2981         return;
       
  2982     }
       
  2983 
       
  2984     QSettingsGroup group = d->groupStack.pop();
       
  2985     int len = group.toString().size();
       
  2986     if (len > 0)
       
  2987         d->groupPrefix.truncate(d->groupPrefix.size() - (len + 1));
       
  2988 
       
  2989     if (group.isArray())
       
  2990         qWarning("QSettings::endGroup: Expected endArray() instead");
       
  2991 }
       
  2992 
       
  2993 /*!
       
  2994     Returns the current group.
       
  2995 
       
  2996     \sa beginGroup(), endGroup()
       
  2997 */
       
  2998 QString QSettings::group() const
       
  2999 {
       
  3000     Q_D(const QSettings);
       
  3001     return d->groupPrefix.left(d->groupPrefix.size() - 1);
       
  3002 }
       
  3003 
       
  3004 /*!
       
  3005     Adds \a prefix to the current group and starts reading from an
       
  3006     array. Returns the size of the array.
       
  3007 
       
  3008     Example:
       
  3009 
       
  3010     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 15
       
  3011 
       
  3012     Use beginWriteArray() to write the array in the first place.
       
  3013 
       
  3014     \sa beginWriteArray(), endArray(), setArrayIndex()
       
  3015 */
       
  3016 int QSettings::beginReadArray(const QString &prefix)
       
  3017 {
       
  3018     Q_D(QSettings);
       
  3019     d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix), false));
       
  3020     return value(QLatin1String("size")).toInt();
       
  3021 }
       
  3022 
       
  3023 /*!
       
  3024     Adds \a prefix to the current group and starts writing an array
       
  3025     of size \a size. If \a size is -1 (the default), it is automatically
       
  3026     determined based on the indexes of the entries written.
       
  3027 
       
  3028     If you have many occurrences of a certain set of keys, you can
       
  3029     use arrays to make your life easier. For example, let's suppose
       
  3030     that you want to save a variable-length list of user names and
       
  3031     passwords. You could then write:
       
  3032 
       
  3033     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 16
       
  3034 
       
  3035     The generated keys will have the form
       
  3036 
       
  3037     \list
       
  3038     \o \c logins/size
       
  3039     \o \c logins/1/userName
       
  3040     \o \c logins/1/password
       
  3041     \o \c logins/2/userName
       
  3042     \o \c logins/2/password
       
  3043     \o \c logins/3/userName
       
  3044     \o \c logins/3/password
       
  3045     \o ...
       
  3046     \endlist
       
  3047 
       
  3048     To read back an array, use beginReadArray().
       
  3049 
       
  3050     \sa beginReadArray(), endArray(), setArrayIndex()
       
  3051 */
       
  3052 void QSettings::beginWriteArray(const QString &prefix, int size)
       
  3053 {
       
  3054     Q_D(QSettings);
       
  3055     d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix), size < 0));
       
  3056 
       
  3057     if (size < 0)
       
  3058         remove(QLatin1String("size"));
       
  3059     else
       
  3060         setValue(QLatin1String("size"), size);
       
  3061 }
       
  3062 
       
  3063 /*!
       
  3064     Closes the array that was started using beginReadArray() or
       
  3065     beginWriteArray().
       
  3066 
       
  3067     \sa beginReadArray(), beginWriteArray()
       
  3068 */
       
  3069 void QSettings::endArray()
       
  3070 {
       
  3071     Q_D(QSettings);
       
  3072     if (d->groupStack.isEmpty()) {
       
  3073         qWarning("QSettings::endArray: No matching beginArray()");
       
  3074         return;
       
  3075     }
       
  3076 
       
  3077     QSettingsGroup group = d->groupStack.top();
       
  3078     int len = group.toString().size();
       
  3079     d->groupStack.pop();
       
  3080     if (len > 0)
       
  3081         d->groupPrefix.truncate(d->groupPrefix.size() - (len + 1));
       
  3082 
       
  3083     if (group.arraySizeGuess() != -1)
       
  3084         setValue(group.name() + QLatin1String("/size"), group.arraySizeGuess());
       
  3085 
       
  3086     if (!group.isArray())
       
  3087         qWarning("QSettings::endArray: Expected endGroup() instead");
       
  3088 }
       
  3089 
       
  3090 /*!
       
  3091     Sets the current array index to \a i. Calls to functions such as
       
  3092     setValue(), value(), remove(), and contains() will operate on the
       
  3093     array entry at that index.
       
  3094 
       
  3095     You must call beginReadArray() or beginWriteArray() before you
       
  3096     can call this function.
       
  3097 */
       
  3098 void QSettings::setArrayIndex(int i)
       
  3099 {
       
  3100     Q_D(QSettings);
       
  3101     if (d->groupStack.isEmpty() || !d->groupStack.top().isArray()) {
       
  3102         qWarning("QSettings::setArrayIndex: Missing beginArray()");
       
  3103         return;
       
  3104     }
       
  3105 
       
  3106     QSettingsGroup &top = d->groupStack.top();
       
  3107     int len = top.toString().size();
       
  3108     top.setArrayIndex(qMax(i, 0));
       
  3109     d->groupPrefix.replace(d->groupPrefix.size() - len - 1, len, top.toString());
       
  3110 }
       
  3111 
       
  3112 /*!
       
  3113     Returns a list of all keys, including subkeys, that can be read
       
  3114     using the QSettings object.
       
  3115 
       
  3116     Example:
       
  3117 
       
  3118     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 17
       
  3119 
       
  3120     If a group is set using beginGroup(), only the keys in the group
       
  3121     are returned, without the group prefix:
       
  3122 
       
  3123     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 18
       
  3124 
       
  3125     \sa childGroups(), childKeys()
       
  3126 */
       
  3127 QStringList QSettings::allKeys() const
       
  3128 {
       
  3129     Q_D(const QSettings);
       
  3130     return d->children(d->groupPrefix, QSettingsPrivate::AllKeys);
       
  3131 }
       
  3132 
       
  3133 /*!
       
  3134     Returns a list of all top-level keys that can be read using the
       
  3135     QSettings object.
       
  3136 
       
  3137     Example:
       
  3138 
       
  3139     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 19
       
  3140 
       
  3141     If a group is set using beginGroup(), the top-level keys in that
       
  3142     group are returned, without the group prefix:
       
  3143 
       
  3144     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 20
       
  3145 
       
  3146     You can navigate through the entire setting hierarchy using
       
  3147     childKeys() and childGroups() recursively.
       
  3148 
       
  3149     \sa childGroups(), allKeys()
       
  3150 */
       
  3151 QStringList QSettings::childKeys() const
       
  3152 {
       
  3153     Q_D(const QSettings);
       
  3154     return d->children(d->groupPrefix, QSettingsPrivate::ChildKeys);
       
  3155 }
       
  3156 
       
  3157 /*!
       
  3158     Returns a list of all key top-level groups that contain keys that
       
  3159     can be read using the QSettings object.
       
  3160 
       
  3161     Example:
       
  3162 
       
  3163     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 21
       
  3164 
       
  3165     If a group is set using beginGroup(), the first-level keys in
       
  3166     that group are returned, without the group prefix.
       
  3167 
       
  3168     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 22
       
  3169 
       
  3170     You can navigate through the entire setting hierarchy using
       
  3171     childKeys() and childGroups() recursively.
       
  3172 
       
  3173     \sa childKeys(), allKeys()
       
  3174 */
       
  3175 QStringList QSettings::childGroups() const
       
  3176 {
       
  3177     Q_D(const QSettings);
       
  3178     return d->children(d->groupPrefix, QSettingsPrivate::ChildGroups);
       
  3179 }
       
  3180 
       
  3181 /*!
       
  3182     Returns true if settings can be written using this QSettings
       
  3183     object; returns false otherwise.
       
  3184 
       
  3185     One reason why isWritable() might return false is if
       
  3186     QSettings operates on a read-only file.
       
  3187 
       
  3188     \warning This function is not perfectly reliable, because the
       
  3189     file permissions can change at any time.
       
  3190 
       
  3191     \sa fileName(), status(), sync()
       
  3192 */
       
  3193 bool QSettings::isWritable() const
       
  3194 {
       
  3195     Q_D(const QSettings);
       
  3196     return d->isWritable();
       
  3197 }
       
  3198 
       
  3199 /*!
       
  3200   
       
  3201   Sets the value of setting \a key to \a value. If the \a key already
       
  3202   exists, the previous value is overwritten.
       
  3203 
       
  3204   Note that the Windows registry and INI files use case-insensitive
       
  3205   keys, whereas the Carbon Preferences API on Mac OS X uses
       
  3206   case-sensitive keys. To avoid portability problems, see the
       
  3207   \l{Section and Key Syntax} rules.
       
  3208 
       
  3209   Example:
       
  3210 
       
  3211   \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 23
       
  3212 
       
  3213   \sa value(), remove(), contains()
       
  3214 */
       
  3215 void QSettings::setValue(const QString &key, const QVariant &value)
       
  3216 {
       
  3217     Q_D(QSettings);
       
  3218     QString k = d->actualKey(key);
       
  3219     d->set(k, value);
       
  3220     d->requestUpdate();
       
  3221 }
       
  3222 
       
  3223 /*!
       
  3224     Removes the setting \a key and any sub-settings of \a key.
       
  3225 
       
  3226     Example:
       
  3227 
       
  3228     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 24
       
  3229 
       
  3230     Be aware that if one of the fallback locations contains a setting
       
  3231     with the same key, that setting will be visible after calling
       
  3232     remove().
       
  3233 
       
  3234     If \a key is an empty string, all keys in the current group() are
       
  3235     removed. For example:
       
  3236 
       
  3237     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 25
       
  3238 
       
  3239     Note that the Windows registry and INI files use case-insensitive
       
  3240     keys, whereas the Carbon Preferences API on Mac OS X uses
       
  3241     case-sensitive keys. To avoid portability problems, see the
       
  3242     \l{Section and Key Syntax} rules.
       
  3243 
       
  3244     \sa setValue(), value(), contains()
       
  3245 */
       
  3246 void QSettings::remove(const QString &key)
       
  3247 {
       
  3248     Q_D(QSettings);
       
  3249     /*
       
  3250         We cannot use actualKey(), because remove() supports empty
       
  3251         keys. The code is also tricky because of slash handling.
       
  3252     */
       
  3253     QString theKey = d->normalizedKey(key);
       
  3254     if (theKey.isEmpty())
       
  3255         theKey = group();
       
  3256     else
       
  3257         theKey.prepend(d->groupPrefix);
       
  3258 
       
  3259     if (theKey.isEmpty()) {
       
  3260         d->clear();
       
  3261     } else {
       
  3262         d->remove(theKey);
       
  3263     }
       
  3264     d->requestUpdate();
       
  3265 }
       
  3266 
       
  3267 /*!
       
  3268     Returns true if there exists a setting called \a key; returns
       
  3269     false otherwise.
       
  3270 
       
  3271     If a group is set using beginGroup(), \a key is taken to be
       
  3272     relative to that group.
       
  3273 
       
  3274     Note that the Windows registry and INI files use case-insensitive
       
  3275     keys, whereas the Carbon Preferences API on Mac OS X uses
       
  3276     case-sensitive keys. To avoid portability problems, see the
       
  3277     \l{Section and Key Syntax} rules.
       
  3278 
       
  3279     \sa value(), setValue()
       
  3280 */
       
  3281 bool QSettings::contains(const QString &key) const
       
  3282 {
       
  3283     Q_D(const QSettings);
       
  3284     QString k = d->actualKey(key);
       
  3285     return d->get(k, 0);
       
  3286 }
       
  3287 
       
  3288 /*!
       
  3289     Sets whether fallbacks are enabled to \a b.
       
  3290 
       
  3291     By default, fallbacks are enabled.
       
  3292 
       
  3293     \sa fallbacksEnabled()
       
  3294 */
       
  3295 void QSettings::setFallbacksEnabled(bool b)
       
  3296 {
       
  3297     Q_D(QSettings);
       
  3298     d->fallbacks = !!b;
       
  3299 }
       
  3300 
       
  3301 /*!
       
  3302     Returns true if fallbacks are enabled; returns false otherwise.
       
  3303 
       
  3304     By default, fallbacks are enabled.
       
  3305 
       
  3306     \sa setFallbacksEnabled()
       
  3307 */
       
  3308 bool QSettings::fallbacksEnabled() const
       
  3309 {
       
  3310     Q_D(const QSettings);
       
  3311     return d->fallbacks;
       
  3312 }
       
  3313 
       
  3314 #ifndef QT_NO_QOBJECT
       
  3315 /*!
       
  3316     \reimp
       
  3317 */
       
  3318 bool QSettings::event(QEvent *event)
       
  3319 {
       
  3320     Q_D(QSettings);
       
  3321     if (event->type() == QEvent::UpdateRequest) {
       
  3322         d->update();
       
  3323         return true;
       
  3324     }
       
  3325     return QObject::event(event);
       
  3326 }
       
  3327 #endif
       
  3328 
       
  3329 /*!
       
  3330     Returns the value for setting \a key. If the setting doesn't
       
  3331     exist, returns \a defaultValue.
       
  3332 
       
  3333     If no default value is specified, a default QVariant is
       
  3334     returned.
       
  3335 
       
  3336     Note that the Windows registry and INI files use case-insensitive
       
  3337     keys, whereas the Carbon Preferences API on Mac OS X uses
       
  3338     case-sensitive keys. To avoid portability problems, see the
       
  3339     \l{Section and Key Syntax} rules.
       
  3340 
       
  3341     Example:
       
  3342 
       
  3343     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 26
       
  3344 
       
  3345     \sa setValue(), contains(), remove()
       
  3346 */
       
  3347 QVariant QSettings::value(const QString &key, const QVariant &defaultValue) const
       
  3348 {
       
  3349     Q_D(const QSettings);
       
  3350     QVariant result = defaultValue;
       
  3351     QString k = d->actualKey(key);
       
  3352     d->get(k, &result);
       
  3353     return result;
       
  3354 }
       
  3355 
       
  3356 /*!
       
  3357     \since 4.4
       
  3358 
       
  3359     Sets the default file format to the given \a format, which is used
       
  3360     for storing settings for the QSettings(QObject *) constructor.
       
  3361 
       
  3362     If no default format is set, QSettings::NativeFormat is used. See
       
  3363     the documentation for the QSettings constructor you are using to
       
  3364     see if that constructor will ignore this function.
       
  3365 
       
  3366     \sa format()
       
  3367 */
       
  3368 void QSettings::setDefaultFormat(Format format)
       
  3369 {
       
  3370     globalDefaultFormat = format;
       
  3371 }
       
  3372 
       
  3373 /*!
       
  3374     \since 4.4
       
  3375 
       
  3376     Returns default file format used for storing settings for the QSettings(QObject *) constructor.
       
  3377     If no default format is set, QSettings::NativeFormat is used.
       
  3378 
       
  3379     \sa format()
       
  3380 */
       
  3381 QSettings::Format QSettings::defaultFormat()
       
  3382 {
       
  3383     return globalDefaultFormat;
       
  3384 }
       
  3385 
       
  3386 /*!
       
  3387     \obsolete
       
  3388 
       
  3389     Use setPath() instead.
       
  3390 
       
  3391     \oldcode
       
  3392         setSystemIniPath(path);
       
  3393     \newcode
       
  3394         setPath(QSettings::NativeFormat, QSettings::SystemScope, path);
       
  3395         setPath(QSettings::IniFormat, QSettings::SystemScope, path);
       
  3396     \endcode
       
  3397 */
       
  3398 void QSettings::setSystemIniPath(const QString &dir)
       
  3399 {
       
  3400     setPath(IniFormat, SystemScope, dir);
       
  3401 #if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
       
  3402     setPath(NativeFormat, SystemScope, dir);
       
  3403 #endif
       
  3404 }
       
  3405 
       
  3406 /*!
       
  3407     \obsolete
       
  3408 
       
  3409     Use setPath() instead.
       
  3410 */
       
  3411 
       
  3412 void QSettings::setUserIniPath(const QString &dir)
       
  3413 {
       
  3414     setPath(IniFormat, UserScope, dir);
       
  3415 #if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
       
  3416     setPath(NativeFormat, UserScope, dir);
       
  3417 #endif
       
  3418 }
       
  3419 
       
  3420 /*!
       
  3421     \since 4.1
       
  3422 
       
  3423     Sets the path used for storing settings for the given \a format
       
  3424     and \a scope, to \a path. The \a format can be a custom format.
       
  3425 
       
  3426     The table below summarizes the default values:
       
  3427 
       
  3428     \table
       
  3429     \header \o Platform         \o Format                       \o Scope       \o Path
       
  3430     \row    \o{1,2} Windows     \o{1,2} IniFormat               \o UserScope   \o \c %APPDATA%
       
  3431     \row                                                        \o SystemScope \o \c %COMMON_APPDATA%
       
  3432     \row    \o{1,2} Unix        \o{1,2} NativeFormat, IniFormat \o UserScope   \o \c $HOME/.config
       
  3433     \row                                                        \o SystemScope \o \c /etc/xdg
       
  3434     \row    \o{1,2} Qt for Embedded Linux \o{1,2} NativeFormat, IniFormat \o UserScope   \o \c $HOME/Settings
       
  3435     \row                                                        \o SystemScope \o \c /etc/xdg
       
  3436     \row    \o{1,2} Mac OS X    \o{1,2} IniFormat               \o UserScope   \o \c $HOME/.config
       
  3437     \row                                                        \o SystemScope \o \c /etc/xdg
       
  3438     \endtable
       
  3439 
       
  3440     The default UserScope paths on Unix and Mac OS X (\c
       
  3441     $HOME/.config or $HOME/Settings) can be overridden by the user by setting the
       
  3442     \c XDG_CONFIG_HOME environment variable. The default SystemScope
       
  3443     paths on Unix and Mac OS X (\c /etc/xdg) can be overridden when
       
  3444     building the Qt library using the \c configure script's \c
       
  3445     --sysconfdir flag (see QLibraryInfo for details).
       
  3446 
       
  3447     Setting the NativeFormat paths on Windows and Mac OS X has no
       
  3448     effect.
       
  3449 
       
  3450     \warning This function doesn't affect existing QSettings objects.
       
  3451 
       
  3452     \sa registerFormat()
       
  3453 */
       
  3454 void QSettings::setPath(Format format, Scope scope, const QString &path)
       
  3455 {
       
  3456     QMutexLocker locker(globalMutex());
       
  3457     PathHash *pathHash = pathHashFunc();
       
  3458     pathHash->insert(pathHashKey(format, scope), path + QDir::separator());
       
  3459 }
       
  3460 
       
  3461 /*!
       
  3462     \typedef QSettings::SettingsMap
       
  3463 
       
  3464     Typedef for QMap<QString, QVariant>.
       
  3465 	
       
  3466     \sa registerFormat()
       
  3467 */
       
  3468 
       
  3469 /*!
       
  3470     \typedef QSettings::ReadFunc
       
  3471 
       
  3472     Typedef for a pointer to a function with the following signature:
       
  3473 
       
  3474     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 27
       
  3475 
       
  3476     \c ReadFunc is used in \c registerFormat() as a pointer to a function
       
  3477     that reads a set of key/value pairs. \c ReadFunc should read all the 
       
  3478     options in one pass, and return all the settings in the \c SettingsMap 
       
  3479     container, which is initially empty.
       
  3480 
       
  3481     \sa WriteFunc, registerFormat()
       
  3482 */
       
  3483 
       
  3484 /*!
       
  3485     \typedef QSettings::WriteFunc
       
  3486 
       
  3487     Typedef for a pointer to a function with the following signature:
       
  3488 
       
  3489     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 28
       
  3490 
       
  3491     \c WriteFunc is used in \c registerFormat() as a pointer to a function 
       
  3492     that writes a set of key/value pairs. \c WriteFunc is only called once,
       
  3493     so you need to output the settings in one go.
       
  3494 
       
  3495     \sa ReadFunc, registerFormat()
       
  3496 */
       
  3497 
       
  3498 /*!
       
  3499     \since 4.1
       
  3500     \threadsafe
       
  3501 
       
  3502     Registers a custom storage format. On success, returns a special
       
  3503     Format value that can then be passed to the QSettings constuctor.
       
  3504     On failure, returns InvalidFormat.
       
  3505 
       
  3506     The \a extension is the file
       
  3507     extension associated to the format (without the '.').
       
  3508 
       
  3509     The \a readFunc and \a writeFunc parameters are pointers to
       
  3510     functions that read and write a set of key/value pairs. The
       
  3511     QIODevice parameter to the read and write functions is always
       
  3512     opened in binary mode (i.e., without the QIODevice::Text flag).
       
  3513 
       
  3514     The \a caseSensitivity parameter specifies whether keys are case
       
  3515     sensitive or not. This makes a difference when looking up values
       
  3516     using QSettings. The default is case sensitive.
       
  3517 
       
  3518     By default, if you use one of the constructors that work in terms
       
  3519     of an organization name and an application name, the file system
       
  3520     locations used are the same as for IniFormat. Use setPath() to
       
  3521     specify other locations.
       
  3522 
       
  3523     Example:
       
  3524 
       
  3525     \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 29
       
  3526 
       
  3527     \sa setPath()
       
  3528 */
       
  3529 QSettings::Format QSettings::registerFormat(const QString &extension, ReadFunc readFunc,
       
  3530                                             WriteFunc writeFunc,
       
  3531                                             Qt::CaseSensitivity caseSensitivity)
       
  3532 {
       
  3533 #ifdef QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
       
  3534     Q_ASSERT(caseSensitivity == Qt::CaseSensitive);
       
  3535 #endif
       
  3536 
       
  3537     QMutexLocker locker(globalMutex());
       
  3538     CustomFormatVector *customFormatVector = customFormatVectorFunc();
       
  3539     int index = customFormatVector->size();
       
  3540     if (index == 16) // the QSettings::Format enum has room for 16 custom formats
       
  3541         return QSettings::InvalidFormat;
       
  3542 
       
  3543     QConfFileCustomFormat info;
       
  3544     info.extension = QLatin1Char('.');
       
  3545     info.extension += extension;
       
  3546     info.readFunc = readFunc;
       
  3547     info.writeFunc = writeFunc;
       
  3548     info.caseSensitivity = caseSensitivity;
       
  3549     customFormatVector->append(info);
       
  3550 
       
  3551     return QSettings::Format((int)QSettings::CustomFormat1 + index);
       
  3552 }
       
  3553 
       
  3554 #ifdef QT3_SUPPORT
       
  3555 void QSettings::setPath_helper(Scope scope, const QString &organization, const QString &application)
       
  3556 {
       
  3557     Q_D(QSettings);
       
  3558     if (d->pendingChanges)
       
  3559         d->flush();
       
  3560     QSettingsPrivate *oldPriv = d;
       
  3561     QSettingsPrivate *newPriv = QSettingsPrivate::create(oldPriv->format, scope, organization, application);
       
  3562     static_cast<QObjectPrivate &>(*newPriv) = static_cast<QObjectPrivate &>(*oldPriv);  // copy the QObject stuff over (hack)
       
  3563     d_ptr.reset(newPriv);
       
  3564 }
       
  3565 
       
  3566 /*! \fn bool QSettings::writeEntry(const QString &key, bool value)
       
  3567 
       
  3568     Sets the value of setting \a key to \a value.
       
  3569 
       
  3570     Use setValue() instead.
       
  3571 */
       
  3572 
       
  3573 /*! \fn bool QSettings::writeEntry(const QString &key, double value)
       
  3574 
       
  3575     \overload
       
  3576 */
       
  3577 
       
  3578 /*! \fn bool QSettings::writeEntry(const QString &key, int value)
       
  3579 
       
  3580     \overload
       
  3581 */
       
  3582 
       
  3583 /*! \fn bool QSettings::writeEntry(const QString &key, const char *value)
       
  3584 
       
  3585     \overload
       
  3586 */
       
  3587 
       
  3588 /*! \fn bool QSettings::writeEntry(const QString &key, const QString &value)
       
  3589 
       
  3590     \overload
       
  3591 */
       
  3592 
       
  3593 /*! \fn bool QSettings::writeEntry(const QString &key, const QStringList &value)
       
  3594 
       
  3595     \overload
       
  3596 */
       
  3597 
       
  3598 /*! \fn bool QSettings::writeEntry(const QString &key, const QStringList &value, QChar separator)
       
  3599 
       
  3600     \overload
       
  3601 
       
  3602     Use setValue(\a key, \a value) instead. You don't need \a separator.
       
  3603 */
       
  3604 
       
  3605 /*! \fn QStringList QSettings::readListEntry(const QString &key, bool *ok = 0)
       
  3606 
       
  3607     Returns the value of setting \a key converted to a QStringList.
       
  3608 
       
  3609     If \a ok is not 0, *\a{ok} is set to true if the key exists,
       
  3610     otherwise *\a{ok} is set to false.
       
  3611 
       
  3612     Use value() instead.
       
  3613 
       
  3614     \oldcode
       
  3615         bool ok;
       
  3616         QStringList list = settings.readListEntry("recentFiles", &ok);
       
  3617     \newcode
       
  3618         bool ok = settings.contains("recentFiles");
       
  3619         QStringList list = settings.value("recentFiles").toStringList();
       
  3620     \endcode
       
  3621 */
       
  3622 
       
  3623 /*! \fn QStringList QSettings::readListEntry(const QString &key, QChar separator, bool *ok)
       
  3624 
       
  3625     Returns the value of setting \a key converted to a QStringList.
       
  3626     \a separator is ignored.
       
  3627 
       
  3628     If \a ok is not 0, *\a{ok} is set to true if the key exists,
       
  3629     otherwise *\a{ok} is set to false.
       
  3630 
       
  3631     Use value() instead.
       
  3632 
       
  3633     \oldcode
       
  3634         bool ok;
       
  3635         QStringList list = settings.readListEntry("recentFiles", ":", &ok);
       
  3636     \newcode
       
  3637         bool ok = settings.contains("recentFiles");
       
  3638         QStringList list = settings.value("recentFiles").toStringList();
       
  3639     \endcode
       
  3640 */
       
  3641 
       
  3642 /*! \fn QString QSettings::readEntry(const QString &key, const QString &defaultValue, bool *ok)
       
  3643 
       
  3644     Returns the value for setting \a key converted to a QString. If
       
  3645     the setting doesn't exist, returns \a defaultValue.
       
  3646 
       
  3647     If \a ok is not 0, *\a{ok} is set to true if the key exists,
       
  3648     otherwise *\a{ok} is set to false.
       
  3649 
       
  3650     Use value() instead.
       
  3651 
       
  3652     \oldcode
       
  3653         bool ok;
       
  3654         QString str = settings.readEntry("userName", "administrator", &ok);
       
  3655     \newcode
       
  3656         bool ok = settings.contains("userName");
       
  3657         QString str = settings.value("userName", "administrator").toString();
       
  3658     \endcode
       
  3659 */
       
  3660 
       
  3661 /*! \fn int QSettings::readNumEntry(const QString &key, int defaultValue, bool *ok)
       
  3662 
       
  3663     Returns the value for setting \a key converted to an \c int. If
       
  3664     the setting doesn't exist, returns \a defaultValue.
       
  3665 
       
  3666     If \a ok is not 0, *\a{ok} is set to true if the key exists,
       
  3667     otherwise *\a{ok} is set to false.
       
  3668 
       
  3669     Use value() instead.
       
  3670 
       
  3671     \oldcode
       
  3672         bool ok;
       
  3673         int max = settings.readNumEntry("maxConnections", 30, &ok);
       
  3674     \newcode
       
  3675         bool ok = settings.contains("maxConnections");
       
  3676         int max = settings.value("maxConnections", 30).toInt();
       
  3677     \endcode
       
  3678 */
       
  3679 
       
  3680 /*! \fn double QSettings::readDoubleEntry(const QString &key, double defaultValue, bool *ok)
       
  3681 
       
  3682     Returns the value for setting \a key converted to a \c double. If
       
  3683     the setting doesn't exist, returns \a defaultValue.
       
  3684 
       
  3685     If \a ok is not 0, *\a{ok} is set to true if the key exists,
       
  3686     otherwise *\a{ok} is set to false.
       
  3687 
       
  3688     Use value() instead.
       
  3689 
       
  3690     \oldcode
       
  3691         bool ok;
       
  3692         double pi = settings.readDoubleEntry("pi", 3.141592, &ok);
       
  3693     \newcode
       
  3694         bool ok = settings.contains("pi");
       
  3695         double pi = settings.value("pi", 3.141592).toDouble();
       
  3696     \endcode
       
  3697 */
       
  3698 
       
  3699 /*! \fn bool QSettings::readBoolEntry(const QString &key, bool defaultValue, bool *ok)
       
  3700 
       
  3701     Returns the value for setting \a key converted to a \c bool. If
       
  3702     the setting doesn't exist, returns \a defaultValue.
       
  3703 
       
  3704     If \a ok is not 0, *\a{ok} is set to true if the key exists,
       
  3705     otherwise *\a{ok} is set to false.
       
  3706 
       
  3707     Use value() instead.
       
  3708 
       
  3709     \oldcode
       
  3710         bool ok;
       
  3711         bool grid = settings.readBoolEntry("showGrid", true, &ok);
       
  3712     \newcode
       
  3713         bool ok = settings.contains("showGrid");
       
  3714         bool grid = settings.value("showGrid", true).toBool();
       
  3715     \endcode
       
  3716 */
       
  3717 
       
  3718 /*! \fn bool QSettings::removeEntry(const QString &key)
       
  3719 
       
  3720     Use remove() instead.
       
  3721 */
       
  3722 
       
  3723 /*! \enum QSettings::System
       
  3724     \compat
       
  3725 
       
  3726     \value Unix Unix systems (X11 and Embedded Linux)
       
  3727     \value Windows Microsoft Windows systems
       
  3728     \value Mac Mac OS X systems
       
  3729 
       
  3730     \sa insertSearchPath(), removeSearchPath()
       
  3731 */
       
  3732 
       
  3733 /*! \fn void QSettings::insertSearchPath(System system, const QString &path)
       
  3734 
       
  3735     This function is implemented as a no-op. It is provided for
       
  3736     source compatibility with Qt 3. The new QSettings class has no
       
  3737     concept of "search path".
       
  3738 */
       
  3739 
       
  3740 /*! \fn void QSettings::removeSearchPath(System system, const QString &path)
       
  3741 
       
  3742     This function is implemented as a no-op. It is provided for
       
  3743     source compatibility with Qt 3. The new QSettings class has no
       
  3744     concept of "search path".
       
  3745 */
       
  3746 
       
  3747 /*! \fn void QSettings::setPath(const QString &organization, const QString &application, \
       
  3748                                 Scope scope)
       
  3749 
       
  3750     Specifies the \a organization, \a application, and \a scope to
       
  3751     use by the QSettings object.
       
  3752 
       
  3753     Use the appropriate constructor instead, with QSettings::UserScope
       
  3754     instead of QSettings::User and QSettings::SystemScope instead of
       
  3755     QSettings::Global.
       
  3756 
       
  3757     \oldcode
       
  3758         QSettings settings;
       
  3759         settings.setPath("twikimaster.com", "Kanooth", QSettings::Global);
       
  3760     \newcode
       
  3761         QSettings settings(QSettings::SystemScope, "twikimaster.com", "Kanooth");
       
  3762     \endcode
       
  3763 */
       
  3764 
       
  3765 /*! \fn void QSettings::resetGroup()
       
  3766 
       
  3767     Sets the current group to be the empty string.
       
  3768 
       
  3769     Use endGroup() instead (possibly multiple times).
       
  3770 
       
  3771     \oldcode
       
  3772         QSettings settings;
       
  3773         settings.beginGroup("mainWindow");
       
  3774         settings.beginGroup("leftPanel");
       
  3775         ...
       
  3776         settings.resetGroup();
       
  3777     \newcode
       
  3778         QSettings settings;
       
  3779         settings.beginGroup("mainWindow");
       
  3780         settings.beginGroup("leftPanel");
       
  3781         ...
       
  3782         settings.endGroup();
       
  3783         settings.endGroup();
       
  3784     \endcode
       
  3785 */
       
  3786 
       
  3787 /*! \fn QStringList QSettings::entryList(const QString &key) const
       
  3788 
       
  3789     Returns a list of all sub-keys of \a key.
       
  3790 
       
  3791     Use childKeys() instead.
       
  3792 
       
  3793     \oldcode
       
  3794         QSettings settings;
       
  3795         QStringList keys = settings.entryList("cities");
       
  3796         ...
       
  3797     \newcode
       
  3798         QSettings settings;
       
  3799         settings.beginGroup("cities");
       
  3800         QStringList keys = settings.childKeys();
       
  3801         ...
       
  3802         settings.endGroup();
       
  3803     \endcode
       
  3804 */
       
  3805 
       
  3806 /*! \fn QStringList QSettings::subkeyList(const QString &key) const
       
  3807 
       
  3808     Returns a list of all sub-keys of \a key.
       
  3809 
       
  3810     Use childGroups() instead.
       
  3811 
       
  3812     \oldcode
       
  3813         QSettings settings;
       
  3814         QStringList groups = settings.entryList("cities");
       
  3815         ...
       
  3816     \newcode
       
  3817         QSettings settings;
       
  3818         settings.beginGroup("cities");
       
  3819         QStringList groups = settings.childKeys();
       
  3820         ...
       
  3821         settings.endGroup();
       
  3822     \endcode
       
  3823 */
       
  3824 #endif
       
  3825 
       
  3826 QT_END_NAMESPACE
       
  3827 
       
  3828 #endif // QT_NO_SETTINGS