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

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

trunk: Merged in qt 4.6.2 sources.

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