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

Last change on this file since 22 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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