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