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 §ionData = (*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 §ion, 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