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

Last change on this file since 494 was 425, checked in by Dmitry A. Kuminov, 15 years ago

corelib/io: QSettings: Use IniFormat (plain INI files) when NativeFormat is requested instead of the Open32 registry which is known to be unstable and can be easily corrupted. The old behavior may be restored using the QT_PM_REGISTRY environment variable (#111).

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