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

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

corelib: More OS/2 bits for QSettings.

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