source: trunk/src/corelib/io/qsettings.cpp@ 846

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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