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