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