~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/corelib/io/qsettings.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the core module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qplatformdefs.h"
 
30
 
 
31
#include "qsettings.h"
 
32
 
 
33
#ifndef QT_NO_SETTINGS
 
34
 
 
35
#include "qcache.h"
 
36
#include "qsettings_p.h"
 
37
#include "qfile.h"
 
38
#include "qdir.h"
 
39
#include "qfileinfo.h"
 
40
#include "qrect.h"
 
41
#include "qmutex.h"
 
42
#include "qlibraryinfo.h"
 
43
#include "qtemporaryfile.h"
 
44
 
 
45
#ifndef QT_NO_QOBJECT
 
46
#include "qcoreapplication.h"
 
47
 
 
48
#ifdef Q_OS_WIN // for homedirpath reading from registry
 
49
#include "qt_windows.h"
 
50
#include "qlibrary.h"
 
51
 
 
52
#endif // Q_OS_WIN
 
53
#endif // QT_NO_QOBJECT
 
54
 
 
55
#include <stdlib.h>
 
56
 
 
57
#ifndef CSIDL_COMMON_APPDATA
 
58
#define CSIDL_COMMON_APPDATA    0x0023  // All Users\Application Data
 
59
#endif
 
60
 
 
61
#ifndef CSIDL_APPDATA
 
62
#define CSIDL_APPDATA           0x001a  // <username>\Application Data
 
63
#endif
 
64
 
 
65
// ************************************************************************
 
66
// QConfFile
 
67
 
 
68
/*
 
69
    QConfFile objects are explicitly shared within the application.
 
70
    This ensures that modification to the settings done through one
 
71
    QSettings object are immediately reflected in other setting
 
72
    objects of the same application.
 
73
*/
 
74
 
 
75
typedef QHash<QString, QConfFile *> ConfFileHash;
 
76
typedef QCache<QString, QConfFile> ConfFileCache;
 
77
 
 
78
Q_GLOBAL_STATIC(ConfFileHash, usedHashFunc)
 
79
Q_GLOBAL_STATIC(ConfFileCache, unusedCacheFunc)
 
80
Q_GLOBAL_STATIC(QMutex, mutex)
 
81
Q_GLOBAL_STATIC(QString, defaultSystemIniPath)
 
82
Q_GLOBAL_STATIC(QString, defaultUserIniPath)
 
83
 
 
84
QConfFile::QConfFile(const QString &fileName)
 
85
    : name(fileName), size(0), ref(1)
 
86
{
 
87
    usedHashFunc()->insert(name, this);
 
88
#ifdef Q_OS_WIN
 
89
    semHandle = 0;
 
90
#endif
 
91
}
 
92
 
 
93
bool QConfFile::mergeKeyMaps()
 
94
{
 
95
    if (addedKeys.isEmpty() && removedKeys.isEmpty())
 
96
        return false;
 
97
 
 
98
    SettingsKeyMap::const_iterator i;
 
99
 
 
100
    for (i = removedKeys.begin(); i != removedKeys.end(); ++i)
 
101
        originalKeys.remove(i.key());
 
102
    removedKeys.clear();
 
103
 
 
104
    for (i = addedKeys.begin(); i != addedKeys.end(); ++i)
 
105
        originalKeys.insert(i.key(), i.value());
 
106
    addedKeys.clear();
 
107
 
 
108
    return true;
 
109
}
 
110
 
 
111
QConfFile *QConfFile::fromName(const QString &fileName)
 
112
{
 
113
    QConfFile *confFile;
 
114
    QString absPath = QFileInfo(fileName).absoluteFilePath();
 
115
 
 
116
    ConfFileHash *usedHash = usedHashFunc();
 
117
    ConfFileCache *unusedCache = unusedCacheFunc();
 
118
 
 
119
    QMutexLocker locker(mutex());
 
120
 
 
121
    if (!(confFile = usedHash->value(absPath))) {
 
122
        if ((confFile = unusedCache->take(absPath)))
 
123
            usedHash->insert(absPath, confFile);
 
124
    }
 
125
    if (confFile) {
 
126
        confFile->ref.ref();
 
127
        return confFile;
 
128
    }
 
129
    return new QConfFile(absPath);
 
130
}
 
131
 
 
132
void QConfFile::clearCache()
 
133
{
 
134
    QMutexLocker locker(mutex());
 
135
    unusedCacheFunc()->clear();
 
136
}
 
137
 
 
138
// ************************************************************************
 
139
// QSettingsPrivate
 
140
 
 
141
QSettingsPrivate::QSettingsPrivate()
 
142
    : spec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError)
 
143
{
 
144
}
 
145
 
 
146
QSettingsPrivate::~QSettingsPrivate()
 
147
{
 
148
}
 
149
 
 
150
QString QSettingsPrivate::actualKey(const QString &key) const
 
151
{
 
152
    QString n = normalizedKey(key);
 
153
    Q_ASSERT_X(!n.isEmpty(), "QSettings", "empty key");
 
154
    n.prepend(groupPrefix);
 
155
    return n;
 
156
}
 
157
 
 
158
/*
 
159
    Returns a string that never starts nor ends with a slash (or an
 
160
    empty string). Examples:
 
161
 
 
162
            "foo"            becomes   "foo"
 
163
            "/foo//bar///"   becomes   "foo/bar"
 
164
            "///"            becomes   ""
 
165
 
 
166
    This function is optimized to avoid a QString deep copy in the
 
167
    common case where the key is already normalized.
 
168
*/
 
169
QString QSettingsPrivate::normalizedKey(const QString &key)
 
170
{
 
171
    QString result = key;
 
172
 
 
173
    int i = 0;
 
174
    while (i < result.size()) {
 
175
        while (result.at(i) == QLatin1Char('/')) {
 
176
            result.remove(i, 1);
 
177
            if (i == result.size())
 
178
                goto after_loop;
 
179
        }
 
180
        while (result.at(i) != QLatin1Char('/')) {
 
181
            ++i;
 
182
            if (i == result.size())
 
183
                return result;
 
184
        }
 
185
        ++i; // leave the slash alone
 
186
    }
 
187
 
 
188
after_loop:
 
189
    if (!result.isEmpty())
 
190
        result.truncate(i - 1); // remove the trailing slash
 
191
    return result;
 
192
}
 
193
 
 
194
// see also qsettings_win.cpp and qsettings_mac.cpp
 
195
 
 
196
#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
 
197
QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format,
 
198
                                           QSettings::Scope scope,
 
199
                                           const QString &organization,
 
200
                                           const QString &application)
 
201
{
 
202
    QConfFileSettingsPrivate *p = new QConfFileSettingsPrivate(format, scope,
 
203
                                                               organization, application);
 
204
    p->init();
 
205
    return p;
 
206
}
 
207
#endif
 
208
 
 
209
#if !defined(Q_OS_WIN)
 
210
QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
 
211
{
 
212
    QConfFileSettingsPrivate *p = new QConfFileSettingsPrivate(fileName, format);
 
213
    p->init();
 
214
    return p;
 
215
}
 
216
#endif
 
217
 
 
218
void QSettingsPrivate::processChild(QString key, ChildSpec spec, QMap<QString, QString> &result)
 
219
{
 
220
    if (spec != AllKeys) {
 
221
        int slashPos = key.indexOf(QLatin1Char('/'));
 
222
        if (slashPos == -1) {
 
223
            if (spec != ChildKeys)
 
224
                return;
 
225
        } else {
 
226
            if (spec != ChildGroups)
 
227
                return;
 
228
            key.truncate(slashPos);
 
229
        }
 
230
    }
 
231
    result.insert(key, QString());
 
232
}
 
233
 
 
234
void QSettingsPrivate::beginGroupOrArray(const QSettingsGroup &group)
 
235
{
 
236
    groupStack.push(group);
 
237
    if (!group.name().isEmpty()) {
 
238
        groupPrefix += group.name();
 
239
        groupPrefix += QLatin1Char('/');
 
240
    }
 
241
}
 
242
 
 
243
/*
 
244
    We only set an error if there isn't one set already. This way the user always gets the
 
245
    first error that occurred. We always allow clearing errors.
 
246
*/
 
247
 
 
248
void QSettingsPrivate::setStatus(QSettings::Status status)
 
249
{
 
250
    if (status == QSettings::NoError || this->status == QSettings::NoError)
 
251
        this->status = status;
 
252
}
 
253
 
 
254
void QSettingsPrivate::update()
 
255
{
 
256
    flush();
 
257
    pendingChanges = false;
 
258
}
 
259
 
 
260
void QSettingsPrivate::requestUpdate()
 
261
{
 
262
    if (!pendingChanges) {
 
263
        pendingChanges = true;
 
264
#ifndef QT_NO_QOBJECT
 
265
        Q_Q(QSettings);
 
266
        QCoreApplication::postEvent(q, new QEvent(QEvent::UpdateRequest));
 
267
#else
 
268
        update();
 
269
#endif
 
270
    }
 
271
}
 
272
 
 
273
QStringList QSettingsPrivate::variantListToStringList(const QVariantList &l) const
 
274
{
 
275
    QStringList result;
 
276
    QVariantList::const_iterator it = l.constBegin();
 
277
    for (; it != l.constEnd(); ++it)
 
278
        result.append(variantToString(*it));
 
279
    return result;
 
280
}
 
281
 
 
282
QVariant QSettingsPrivate::stringListToVariantList(const QStringList &l) const
 
283
{
 
284
    QVariantList variantList;
 
285
    bool foundNonStringItem = false;
 
286
    bool foundEscapedStringItem = false;
 
287
 
 
288
    QStringList::const_iterator it = l.constBegin();
 
289
    for (; it != l.constEnd(); ++it) {
 
290
        QVariant variant = stringToVariant(*it);
 
291
        variantList.append(variant);
 
292
 
 
293
        if (variant.type() != QVariant::String)
 
294
            foundNonStringItem = true;
 
295
        else if (variant.toString() != *it)
 
296
            foundEscapedStringItem = true;
 
297
    }
 
298
 
 
299
    if (foundNonStringItem) {
 
300
        return variantList;
 
301
    } else if (foundEscapedStringItem) {
 
302
        return QVariant(variantList).toStringList();
 
303
    }
 
304
    return l;
 
305
}
 
306
 
 
307
QString &QSettingsPrivate::escapedLeadingAt(QString &s)
 
308
{
 
309
    if (s.length() > 0 && s.at(0) == QLatin1Char('@'))
 
310
        s.prepend(QLatin1Char('@'));
 
311
    return s;
 
312
}
 
313
 
 
314
QString &QSettingsPrivate::unescapedLeadingAt(QString &s)
 
315
{
 
316
    if (s.startsWith(QLatin1String("@@")))
 
317
        s.remove(0, 1);
 
318
    return s;
 
319
}
 
320
 
 
321
QString QSettingsPrivate::variantToString(const QVariant &v)
 
322
{
 
323
    QString result;
 
324
 
 
325
    switch (v.type()) {
 
326
        case QVariant::Invalid:
 
327
            result = QLatin1String("@Invalid()");
 
328
            break;
 
329
 
 
330
        case QVariant::ByteArray: {
 
331
            QByteArray a = v.toByteArray();
 
332
            result = QLatin1String("@ByteArray(");
 
333
            result += QString::fromLatin1(a.constData(), a.size());
 
334
            result += QLatin1Char(')');
 
335
            break;
 
336
        }
 
337
 
 
338
        case QVariant::String:
 
339
        case QVariant::LongLong:
 
340
        case QVariant::ULongLong:
 
341
        case QVariant::Int:
 
342
        case QVariant::UInt:
 
343
        case QVariant::Bool:
 
344
        case QVariant::Double: {
 
345
            result = v.toString();
 
346
            result = escapedLeadingAt(result);
 
347
            break;
 
348
        }
 
349
        case QVariant::Rect: {
 
350
            QRect r = qvariant_cast<QRect>(v);
 
351
            result += QLatin1String("@Rect(");
 
352
            result += QString::number(r.x());
 
353
            result += QLatin1Char(' ');
 
354
            result += QString::number(r.y());
 
355
            result += QLatin1Char(' ');
 
356
            result += QString::number(r.width());
 
357
            result += QLatin1Char(' ');
 
358
            result += QString::number(r.height());
 
359
            result += QLatin1Char(')');
 
360
            break;
 
361
        }
 
362
        case QVariant::Size: {
 
363
            QSize s = qvariant_cast<QSize>(v);
 
364
            result += QLatin1String("@Size(");
 
365
            result += QString::number(s.width());
 
366
            result += QLatin1Char(' ');
 
367
            result += QString::number(s.height());
 
368
            result += QLatin1Char(')');
 
369
            break;
 
370
        }
 
371
        case QVariant::Point: {
 
372
            QPoint p = qvariant_cast<QPoint>(v);
 
373
            result += QLatin1String("@Point(");
 
374
            result += QString::number(p.x());
 
375
            result += QLatin1Char(' ');
 
376
            result += QString::number(p.y());
 
377
            result += QLatin1Char(')');
 
378
            break;
 
379
        }
 
380
 
 
381
        default: {
 
382
#ifndef QT_NO_DATASTREAM
 
383
            QByteArray a;
 
384
            {
 
385
                QDataStream s(&a, QIODevice::WriteOnly);
 
386
                s << v;
 
387
            }
 
388
 
 
389
            result = QLatin1String("@Variant(");
 
390
            result += QString::fromLatin1(a.constData(), a.size());
 
391
            result += QLatin1Char(')');
 
392
#else
 
393
            Q_ASSERT("QSettings: Cannot save custom types without QDataStream support");
 
394
#endif
 
395
            break;
 
396
        }
 
397
    }
 
398
 
 
399
    return result;
 
400
}
 
401
 
 
402
QVariant QSettingsPrivate::stringToVariant(const QString &s)
 
403
{
 
404
    if (s.length() > 3
 
405
            && s.at(0) == QLatin1Char('@')
 
406
            && s.at(s.length() - 1) == QLatin1Char(')')) {
 
407
 
 
408
        if (s.startsWith(QLatin1String("@ByteArray("))) {
 
409
            return QVariant(s.toLatin1().mid(11, s.size() - 12));
 
410
        } else if (s.startsWith(QLatin1String("@Variant("))) {
 
411
#ifndef QT_NO_DATASTREAM
 
412
            QByteArray a(s.toLatin1().mid(9));
 
413
            QDataStream stream(&a, QIODevice::ReadOnly);
 
414
            QVariant result;
 
415
            stream >> result;
 
416
            return result;
 
417
#else
 
418
            Q_ASSERT("QSettings: Cannot load custom types without QDataStream support");
 
419
#endif
 
420
#ifndef QT_NO_GEOM_VARIANT
 
421
        } else if (s.startsWith(QLatin1String("@Rect("))) {
 
422
            QStringList args = QSettingsPrivate::splitArgs(s, 5);
 
423
            if (args.size() == 4) {
 
424
                return QVariant(QRect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()));
 
425
            }
 
426
        } else if (s.startsWith(QLatin1String("@Size("))) {
 
427
            QStringList args = QSettingsPrivate::splitArgs(s, 5);
 
428
            if (args.size() == 2) {
 
429
                return QVariant(QSize(args[0].toInt(), args[1].toInt()));
 
430
            }
 
431
        } else if (s.startsWith(QLatin1String("@Point("))) {
 
432
            QStringList args = QSettingsPrivate::splitArgs(s, 6);
 
433
            if (args.size() == 2) {
 
434
                return QVariant(QPoint(args[0].toInt(), args[1].toInt()));
 
435
            }
 
436
#endif
 
437
        } else if (s == QLatin1String("@Invalid()")) {
 
438
            return QVariant();
 
439
        }
 
440
    }
 
441
 
 
442
    QString tmp = s;
 
443
    return QVariant(unescapedLeadingAt(tmp));
 
444
}
 
445
 
 
446
static const char hexDigits[] = "0123456789ABCDEF";
 
447
 
 
448
void QSettingsPrivate::iniEscapedKey(const QString &key, QByteArray &result)
 
449
{
 
450
    for (int i = 0; i < key.size(); ++i) {
 
451
        uint ch = key.at(i).unicode();
 
452
 
 
453
        if (ch == '/') {
 
454
            result += '\\';
 
455
        } else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9'
 
456
                || ch == '_' || ch == '-' || ch == '.') {
 
457
            result += (char)ch;
 
458
        } else if (ch <= 0xFF) {
 
459
            result += '%';
 
460
            result += hexDigits[ch / 16];
 
461
            result += hexDigits[ch % 16];
 
462
        } else {
 
463
            result += "%U";
 
464
            QByteArray hexCode;
 
465
            for (int i = 0; i < 4; ++i) {
 
466
                hexCode.prepend(hexDigits[ch % 16]);
 
467
                ch >>= 4;
 
468
            }
 
469
            result += hexCode;
 
470
        }
 
471
    }
 
472
}
 
473
 
 
474
bool QSettingsPrivate::iniUnescapedKey(const QByteArray &key, int from, int to, QString &result)
 
475
{
 
476
    bool lowerCaseOnly = true;
 
477
    int i = from;
 
478
    while (i < to) {
 
479
        int ch = (uchar)key.at(i);
 
480
 
 
481
        if (ch == '\\') {
 
482
            result += QLatin1Char('/');
 
483
            ++i;
 
484
            continue;
 
485
        }
 
486
 
 
487
        if (ch != '%' || i == to - 1) {
 
488
            if (isupper((uchar)ch))
 
489
                lowerCaseOnly = false;
 
490
            result += QLatin1Char(ch);
 
491
            ++i;
 
492
            continue;
 
493
        }
 
494
 
 
495
        int numDigits = 2;
 
496
        int firstDigitPos = i + 1;
 
497
 
 
498
        ch = key.at(i + 1);
 
499
        if (ch == 'U') {
 
500
            ++firstDigitPos;
 
501
            numDigits = 4;
 
502
        }
 
503
 
 
504
        if (firstDigitPos + numDigits > to) {
 
505
            result += QLatin1Char('%');
 
506
            ++i;
 
507
            continue;
 
508
        }
 
509
 
 
510
        bool ok;
 
511
        ch = key.mid(firstDigitPos, numDigits).toInt(&ok, 16);
 
512
        if (!ok) {
 
513
            result += QLatin1Char('%');
 
514
            ++i;
 
515
            continue;
 
516
        }
 
517
 
 
518
        QChar qch(ch);
 
519
        if (qch.toLower() != qch)
 
520
            lowerCaseOnly = false;
 
521
        result += qch;
 
522
        i = firstDigitPos + numDigits;
 
523
    }
 
524
    return lowerCaseOnly;
 
525
}
 
526
 
 
527
void QSettingsPrivate::iniEscapedString(const QString &str, QByteArray &result)
 
528
{
 
529
    bool needsQuotes = false;
 
530
    bool escapeNextIfDigit = false;
 
531
    int i;
 
532
    int startPos = result.size();
 
533
 
 
534
    for (i = 0; i < str.size(); ++i) {
 
535
        uint ch = str.at(i).unicode();
 
536
        if (ch == ';' || ch == ',' || ch == '=')
 
537
            needsQuotes = true;
 
538
 
 
539
        if (escapeNextIfDigit
 
540
                && ((ch >= '0' && ch <= '9')
 
541
                    || (ch >= 'a' && ch <= 'f')
 
542
                    || (ch >= 'A' && ch <= 'F'))) {
 
543
            result += "\\x";
 
544
            result += QByteArray::number(ch, 16);
 
545
            continue;
 
546
        }
 
547
 
 
548
        escapeNextIfDigit = false;
 
549
 
 
550
        switch (ch) {
 
551
        case '\0':
 
552
            result += "\\0";
 
553
            escapeNextIfDigit = true;
 
554
            break;
 
555
        case '\a':
 
556
            result += "\\a";
 
557
            break;
 
558
        case '\b':
 
559
            result += "\\b";
 
560
            break;
 
561
        case '\f':
 
562
            result += "\\f";
 
563
            break;
 
564
        case '\n':
 
565
            result += "\\n";
 
566
            break;
 
567
        case '\r':
 
568
            result += "\\r";
 
569
            break;
 
570
        case '\t':
 
571
            result += "\\t";
 
572
            break;
 
573
        case '\v':
 
574
            result += "\\v";
 
575
            break;
 
576
        case '"':
 
577
        case '\\':
 
578
            result += '\\';
 
579
            result += (char)ch;
 
580
            break;
 
581
        default:
 
582
            if (ch <= 0x1F || ch >= 0x7F) {
 
583
                result += "\\x";
 
584
                result += QByteArray::number(ch, 16);
 
585
                escapeNextIfDigit = true;
 
586
            } else {
 
587
                result += (char)ch;
 
588
            }
 
589
        }
 
590
    }
 
591
 
 
592
    if (needsQuotes
 
593
            || (startPos < result.size() && (result.at(startPos) == ' '
 
594
                                                || result.at(result.size() - 1) == ' '))) {
 
595
        result.insert(startPos, '"');
 
596
        result += '"';
 
597
    }
 
598
}
 
599
 
 
600
void QSettingsPrivate::iniChopTrailingSpaces(QString *str)
 
601
{
 
602
    int n = str->size();
 
603
    while (n > 0
 
604
            && (str->at(n - 1) == QLatin1Char(' ') || str->at(n - 1) == QLatin1Char('\t')))
 
605
        str->truncate(--n);
 
606
}
 
607
 
 
608
void QSettingsPrivate::iniEscapedStringList(const QStringList &strs, QByteArray &result)
 
609
{
 
610
    for (int i = 0; i < strs.size(); ++i) {
 
611
        if (i != 0)
 
612
            result += ", ";
 
613
        iniEscapedString(strs.at(i), result);
 
614
    }
 
615
}
 
616
 
 
617
QStringList *QSettingsPrivate::iniUnescapedStringList(const QByteArray &str, int from, int to,
 
618
                                                      QString &result)
 
619
{
 
620
    static const char escapeCodes[][2] =
 
621
    {
 
622
        { 'a', '\a' },
 
623
        { 'b', '\b' },
 
624
        { 'f', '\f' },
 
625
        { 'n', '\n' },
 
626
        { 'r', '\r' },
 
627
        { 't', '\t' },
 
628
        { 'v', '\v' },
 
629
        { '"', '"' },
 
630
        { '?', '?' },
 
631
        { '\'', '\'' },
 
632
        { '\\', '\\' }
 
633
    };
 
634
    static const int numEscapeCodes = sizeof(escapeCodes) / sizeof(escapeCodes[0]);
 
635
 
 
636
    QStringList *strList = 0;
 
637
    int i = from;
 
638
 
 
639
    enum State { StNormal, StSkipSpaces, StEscape, StHexEscapeFirstChar, StHexEscape,
 
640
                    StOctEscape };
 
641
    State state = StSkipSpaces;
 
642
    int escapeVal = 0;
 
643
    bool inQuotedString = false;
 
644
    bool currentValueIsQuoted = false;
 
645
 
 
646
    while (i < to) {
 
647
        char ch = str.at(i);
 
648
 
 
649
        switch (state) {
 
650
        case StNormal:
 
651
            switch (ch) {
 
652
            case '\\':
 
653
                state = StEscape;
 
654
                break;
 
655
            case '"':
 
656
                currentValueIsQuoted = true;
 
657
                inQuotedString = !inQuotedString;
 
658
                if (!inQuotedString)
 
659
                    state = StSkipSpaces;
 
660
                break;
 
661
            case ',':
 
662
                if (!inQuotedString) {
 
663
                    if (!currentValueIsQuoted)
 
664
                        iniChopTrailingSpaces(&result);
 
665
                    if (!strList)
 
666
                        strList = new QStringList;
 
667
                    strList->append(result);
 
668
                    result.clear();
 
669
                    currentValueIsQuoted = false;
 
670
                    state = StSkipSpaces;
 
671
                    break;
 
672
                }
 
673
                /* fallthrough */
 
674
            default:
 
675
                result += QLatin1Char(ch);
 
676
            }
 
677
            ++i;
 
678
            break;
 
679
        case StSkipSpaces:
 
680
            if (ch == ' ' || ch == '\t')
 
681
                ++i;
 
682
            else
 
683
                state = StNormal;
 
684
            break;
 
685
        case StEscape:
 
686
            for (int j = 0; j < numEscapeCodes; ++j) {
 
687
                if (ch == escapeCodes[j][0]) {
 
688
                    result += QLatin1Char(escapeCodes[j][1]);
 
689
                    ++i;
 
690
                    state = StNormal;
 
691
                    goto end_of_switch;
 
692
                }
 
693
            }
 
694
 
 
695
            if (ch == 'x') {
 
696
                escapeVal = 0;
 
697
                state = StHexEscapeFirstChar;
 
698
            } else if (ch >= '0' && ch <= '7') {
 
699
                escapeVal = ch - '0';
 
700
                state = StOctEscape;
 
701
            } else {
 
702
                state = StNormal;
 
703
            }
 
704
            ++i;
 
705
            break;
 
706
        case StHexEscapeFirstChar:
 
707
            if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')
 
708
                    || (ch >= 'a' && ch <= 'f'))
 
709
                state = StHexEscape;
 
710
            else
 
711
                state = StNormal;
 
712
            break;
 
713
        case StHexEscape:
 
714
            if (ch >= 'a')
 
715
                ch -= 'a' - 'A';
 
716
            if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')) {
 
717
                escapeVal <<= 4;
 
718
                escapeVal += strchr(hexDigits, ch) - hexDigits;
 
719
                ++i;
 
720
            } else {
 
721
                result += QChar(escapeVal);
 
722
                state = StNormal;
 
723
            }
 
724
            break;
 
725
        case StOctEscape:
 
726
            if (ch >= '0' && ch <= '7') {
 
727
                escapeVal <<= 3;
 
728
                escapeVal += ch - '0';
 
729
                ++i;
 
730
            } else {
 
731
                result += QChar(escapeVal);
 
732
                state = StNormal;
 
733
            }
 
734
        }
 
735
end_of_switch:
 
736
        ;
 
737
    }
 
738
 
 
739
    if (state == StHexEscape || state == StOctEscape)
 
740
        result += QChar(escapeVal);
 
741
    if (!currentValueIsQuoted)
 
742
        iniChopTrailingSpaces(&result);
 
743
    if (strList)
 
744
        strList->append(result);
 
745
    return strList;
 
746
}
 
747
 
 
748
QStringList QSettingsPrivate::splitArgs(const QString &s, int idx)
 
749
{
 
750
    int l = s.length();
 
751
    Q_ASSERT(l > 0);
 
752
    Q_ASSERT(s.at(idx) == QLatin1Char('('));
 
753
    Q_ASSERT(s.at(l - 1) == QLatin1Char(')'));
 
754
 
 
755
    QStringList result;
 
756
    QString item;
 
757
 
 
758
    for (++idx; idx < l; ++idx) {
 
759
        QChar c = s.at(idx);
 
760
        if (c == QLatin1Char(')')) {
 
761
            Q_ASSERT(idx == l - 1);
 
762
            result.append(item);
 
763
        } else if (c == QLatin1Char(' ')) {
 
764
            result.append(item);
 
765
            item.clear();
 
766
        } else {
 
767
            item.append(c);
 
768
        }
 
769
    }
 
770
 
 
771
    return result;
 
772
}
 
773
 
 
774
// ************************************************************************
 
775
// QConfFileSettingsPrivate
 
776
 
 
777
static void checkAccess(const QString &name, bool *read, bool *write)
 
778
{
 
779
    QFileInfo fileInfo(name);
 
780
 
 
781
    if (fileInfo.exists()) {
 
782
        /*
 
783
            The best way to check that an existing file is
 
784
            writable is to open it for writing.
 
785
        */
 
786
        QFile file(name);
 
787
        *read = file.open(QIODevice::ReadOnly);
 
788
        file.close();
 
789
 
 
790
        *write = file.open(QIODevice::Append);
 
791
    } else {
 
792
        // files that don't exist are considered readable
 
793
        *read = true;
 
794
 
 
795
        QDir dir;
 
796
        if (QDir::isRelativePath(name))
 
797
            dir = QDir::current();
 
798
        else
 
799
            dir = QDir::root();
 
800
 
 
801
        /*
 
802
            Create the directories to the file.
 
803
        */
 
804
        QStringList pathElements = name.split(QLatin1Char('/'), QString::SkipEmptyParts);
 
805
        for (int i = 0; i < pathElements.size() - 1; ++i) {
 
806
            QString elt = pathElements[i];
 
807
            if (dir.cd(elt))
 
808
                continue;
 
809
 
 
810
            if (!dir.mkdir(elt) || !dir.cd(elt))
 
811
                break;
 
812
        }
 
813
 
 
814
        /*
 
815
            The best way to check if we can create the file is to
 
816
            try to create a temporary file.
 
817
        */
 
818
        QTemporaryFile file(name + QLatin1String(".XXXXXX"));
 
819
        *write = file.open();
 
820
    }
 
821
}
 
822
 
 
823
void QConfFileSettingsPrivate::init()
 
824
{
 
825
    if (confFiles[spec] == 0) {
 
826
        readAccess = false;
 
827
        writeAccess = false;
 
828
    } else {
 
829
        checkAccess(confFiles[spec]->name, &readAccess, &writeAccess);
 
830
    }
 
831
    if (!readAccess)
 
832
        setStatus(QSettings::AccessError);
 
833
 
 
834
#ifdef Q_OS_MAC
 
835
    cs = (format == QSettings::NativeFormat) ? Qt::CaseSensitive : Qt::CaseInsensitive;
 
836
#else
 
837
    cs = Qt::CaseInsensitive;
 
838
#endif
 
839
    sync();       // loads the files the first time
 
840
}
 
841
 
 
842
#ifdef Q_OS_WIN
 
843
static QString windowsConfigPath(int type)
 
844
{
 
845
    QString result;
 
846
 
 
847
#ifndef QT_NO_QOBJECT
 
848
    // We can't use QLibrary if there is QT_NO_QOBJECT is defined
 
849
    // This only happens when bootstrapping qmake.
 
850
    QLibrary library("shell32");
 
851
    QT_WA( {
 
852
        typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL);
 
853
        GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW");
 
854
        if (SHGetSpecialFolderPath) {
 
855
            TCHAR path[MAX_PATH];
 
856
            SHGetSpecialFolderPath(0, path, type, FALSE);
 
857
            result = QString::fromUtf16((ushort*)path);
 
858
        }
 
859
    } , {
 
860
        typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL);
 
861
        GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathA");
 
862
        if (SHGetSpecialFolderPath) {
 
863
            char path[MAX_PATH];
 
864
            SHGetSpecialFolderPath(0, path, type, FALSE);
 
865
            result = QString::fromLocal8Bit(path);
 
866
        }
 
867
    } );
 
868
#endif // QT_NO_QOBJECT
 
869
 
 
870
    if (result.isEmpty()) {
 
871
        switch (type) {
 
872
            case CSIDL_COMMON_APPDATA:
 
873
                result = QLatin1String("C:\\temp\\qt-common");
 
874
                break;
 
875
            case CSIDL_APPDATA:
 
876
                result = QLatin1String("C:\\temp\\qt-user");
 
877
                break;
 
878
            default:
 
879
                break;
 
880
        }
 
881
    }
 
882
 
 
883
    return result;
 
884
}
 
885
#endif // Q_OS_WIN
 
886
 
 
887
static QString systemIniPath()
 
888
{
 
889
    QString result;
 
890
 
 
891
    result = *defaultSystemIniPath();
 
892
    if (result.isEmpty()) {
 
893
#ifdef Q_OS_WIN
 
894
        result = windowsConfigPath(CSIDL_COMMON_APPDATA);
 
895
#else
 
896
        result = QLibraryInfo::location(QLibraryInfo::SettingsPath);
 
897
#endif // Q_OS_WIN
 
898
    }
 
899
 
 
900
    return result + QDir::separator();
 
901
}
 
902
 
 
903
static QString userIniPath()
 
904
{
 
905
    QString result;
 
906
 
 
907
    result = *defaultUserIniPath();
 
908
    if (result.isEmpty()) {
 
909
#ifdef Q_OS_WIN
 
910
        result = windowsConfigPath(CSIDL_APPDATA);
 
911
#else
 
912
        char *env = getenv("XDG_CONFIG_HOME");
 
913
        if (env == 0)
 
914
            result = QDir::homePath() + QDir::separator() + QLatin1String(".config");
 
915
        else if (*env == '/')
 
916
            result = QLatin1String(env);
 
917
        else
 
918
            result = QDir::homePath() + QDir::separator() + QLatin1String(env);
 
919
#endif // Q_OS_WIN
 
920
    }
 
921
 
 
922
    return result + QDir::separator();
 
923
}
 
924
 
 
925
QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
 
926
                                                   QSettings::Scope scope,
 
927
                                                   const QString &organization,
 
928
                                                   const QString &application)
 
929
{
 
930
    int i;
 
931
    this->format = format;
 
932
    for (i = 0; i < NumConfFiles; ++i)
 
933
        confFiles[i] = 0;
 
934
 
 
935
    QString org = organization;
 
936
    if (org.isEmpty()) {
 
937
        setStatus(QSettings::AccessError);
 
938
        org = QLatin1String("Unknown Organization");
 
939
    }
 
940
 
 
941
    const char *extension = format == QSettings::IniFormat ? ".ini" : ".conf";
 
942
 
 
943
    QString appFile = org + QDir::separator() + application + QLatin1String(extension);
 
944
    QString orgFile = org + QLatin1String(extension);
 
945
 
 
946
    if (scope == QSettings::UserScope) {
 
947
        if (!application.isEmpty())
 
948
            confFiles[F_User | F_Application] = QConfFile::fromName(userIniPath() + appFile);
 
949
        confFiles[F_User | F_Organization] = QConfFile::fromName(userIniPath() + orgFile);
 
950
    }
 
951
    if (!application.isEmpty())
 
952
        confFiles[F_Global | F_Application] = QConfFile::fromName(systemIniPath() + appFile);
 
953
    confFiles[F_Global | F_Organization] = QConfFile::fromName(systemIniPath() + orgFile);
 
954
 
 
955
    for (i = 0; i < NumConfFiles; ++i) {
 
956
        if (confFiles[i]) {
 
957
            spec = i;
 
958
            break;
 
959
        }
 
960
    }
 
961
}
 
962
 
 
963
QConfFileSettingsPrivate::QConfFileSettingsPrivate(const QString &fileName,
 
964
                                                   QSettings::Format format)
 
965
{
 
966
    confFiles[0] = QConfFile::fromName(fileName);
 
967
    for (int i = 1; i < NumConfFiles; ++i)
 
968
        confFiles[i] = 0;
 
969
    this->format = format;
 
970
}
 
971
 
 
972
QConfFileSettingsPrivate::~QConfFileSettingsPrivate()
 
973
{
 
974
    QMutexLocker locker(mutex());
 
975
    ConfFileHash *usedHash = usedHashFunc();
 
976
    ConfFileCache *unusedCache = unusedCacheFunc();
 
977
 
 
978
    for (int i = 0; i < NumConfFiles; ++i) {
 
979
        if (confFiles[i] && !confFiles[i]->ref.deref()) {
 
980
            if (usedHash)
 
981
                usedHash->remove(confFiles[i]->name);
 
982
 
 
983
            if (confFiles[i]->size == 0) {
 
984
                delete confFiles[i];
 
985
            } else if (unusedCache) {
 
986
                unusedCache->insert(confFiles[i]->name, confFiles[i],
 
987
                                      10 + (confFiles[i]->originalKeys.size() / 4));
 
988
            }
 
989
        }
 
990
    }
 
991
}
 
992
 
 
993
void QConfFileSettingsPrivate::remove(const QString &key)
 
994
{
 
995
    if (!writeAccess) {
 
996
        setStatus(QSettings::AccessError);
 
997
        return;
 
998
    }
 
999
 
 
1000
    QSettingsKey theKey(key, cs);
 
1001
    QSettingsKey prefix(key + QLatin1Char('/'), cs);
 
1002
 
 
1003
    QConfFile *confFile = confFiles[spec];
 
1004
    QMutexLocker locker(mutex());
 
1005
 
 
1006
    SettingsKeyMap::iterator i = confFile->addedKeys.lowerBound(prefix);
 
1007
    while (i != confFile->addedKeys.end() && i.key().startsWith(prefix))
 
1008
        i = confFile->addedKeys.erase(i);
 
1009
    confFile->addedKeys.remove(theKey);
 
1010
 
 
1011
    SettingsKeyMap::const_iterator j = confFile->originalKeys.lowerBound(prefix);
 
1012
    while (j != confFile->originalKeys.constEnd() && j.key().startsWith(prefix)) {
 
1013
        confFile->removedKeys.insert(j.key(), QVariant());
 
1014
        ++j;
 
1015
    }
 
1016
    if (confFile->originalKeys.contains(theKey))
 
1017
        confFile->removedKeys.insert(theKey, QVariant());
 
1018
}
 
1019
 
 
1020
void QConfFileSettingsPrivate::set(const QString &key, const QVariant &value)
 
1021
{
 
1022
    if (!writeAccess) {
 
1023
        setStatus(QSettings::AccessError);
 
1024
        return;
 
1025
    }
 
1026
 
 
1027
    QSettingsKey theKey(key, cs);
 
1028
 
 
1029
    QConfFile *confFile = confFiles[spec];
 
1030
    QMutexLocker locker(mutex());
 
1031
    confFile->removedKeys.remove(theKey);
 
1032
    confFile->addedKeys.insert(theKey, value);
 
1033
}
 
1034
 
 
1035
bool QConfFileSettingsPrivate::get(const QString &key, QVariant *value) const
 
1036
{
 
1037
    QSettingsKey theKey(key, cs);
 
1038
    SettingsKeyMap::const_iterator j;
 
1039
    bool found = false;
 
1040
 
 
1041
    QMutexLocker locker(mutex());
 
1042
 
 
1043
    for (int i = 0; i < NumConfFiles; ++i) {
 
1044
        if (QConfFile *confFile = confFiles[i]) {
 
1045
            if (!confFile->addedKeys.isEmpty()) {
 
1046
                j = confFile->addedKeys.find(theKey);
 
1047
                found = (j != confFile->addedKeys.constEnd());
 
1048
            }
 
1049
            if (!found) {
 
1050
                j = confFile->originalKeys.find(theKey);
 
1051
                found = (j != confFile->originalKeys.constEnd()
 
1052
                         && !confFile->removedKeys.contains(theKey));
 
1053
            }
 
1054
 
 
1055
            if (found && value)
 
1056
                *value = *j;
 
1057
 
 
1058
            if (found)
 
1059
                return true;
 
1060
            if (!fallbacks)
 
1061
                break;
 
1062
        }
 
1063
    }
 
1064
    return false;
 
1065
}
 
1066
 
 
1067
QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec spec) const
 
1068
{
 
1069
    QMap<QString, QString> result;
 
1070
    SettingsKeyMap::const_iterator j;
 
1071
 
 
1072
    QSettingsKey thePrefix(prefix, cs);
 
1073
    int startPos = prefix.size();
 
1074
 
 
1075
    QMutexLocker locker(mutex());
 
1076
 
 
1077
    for (int i = 0; i < NumConfFiles; ++i) {
 
1078
        if (QConfFile *confFile = confFiles[i]) {
 
1079
            j = confFile->originalKeys.lowerBound(thePrefix);
 
1080
            while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) {
 
1081
                if (!confFile->removedKeys.contains(j.key()))
 
1082
                    processChild(j.key().realKey().mid(startPos), spec, result);
 
1083
                ++j;
 
1084
            }
 
1085
 
 
1086
            j = confFile->addedKeys.lowerBound(thePrefix);
 
1087
            while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) {
 
1088
                processChild(j.key().realKey().mid(startPos), spec, result);
 
1089
                ++j;
 
1090
            }
 
1091
 
 
1092
            if (!fallbacks)
 
1093
                break;
 
1094
        }
 
1095
    }
 
1096
    return result.keys();
 
1097
}
 
1098
 
 
1099
void QConfFileSettingsPrivate::clear()
 
1100
{
 
1101
    if (!writeAccess) {
 
1102
        setStatus(QSettings::AccessError);
 
1103
        return;
 
1104
    }
 
1105
 
 
1106
    QConfFile *confFile = confFiles[spec];
 
1107
    QMutexLocker locker(mutex());
 
1108
    confFile->addedKeys.clear();
 
1109
    confFile->removedKeys = confFiles[spec]->originalKeys;
 
1110
}
 
1111
 
 
1112
void QConfFileSettingsPrivate::sync()
 
1113
{
 
1114
    QMutexLocker locker(mutex());
 
1115
 
 
1116
    // people probably won't be checking the status a whole lot, so in case of
 
1117
    // error we just try to go on and make the best of it
 
1118
 
 
1119
    for (int i = 0; i < NumConfFiles; ++i) {
 
1120
        QConfFile *confFile = confFiles[i];
 
1121
        if (confFile) {
 
1122
            if (!readFile(confFile)) {
 
1123
                // Only problems with the file we actually write to change the status. The
 
1124
                // other files are just optional fallbacks.
 
1125
                if (i == spec)
 
1126
                    setStatus(QSettings::FormatError);
 
1127
            }
 
1128
            if (i == spec && confFile->mergeKeyMaps()) {
 
1129
                if (!writeFile(confFile))
 
1130
                    setStatus(QSettings::AccessError);
 
1131
            }
 
1132
        }
 
1133
    }
 
1134
}
 
1135
 
 
1136
void QConfFileSettingsPrivate::flush()
 
1137
{
 
1138
    sync();
 
1139
}
 
1140
 
 
1141
QString QConfFileSettingsPrivate::fileName() const
 
1142
{
 
1143
    QConfFile *confFile = confFiles[spec];
 
1144
    if (confFile == 0)
 
1145
        return QString();
 
1146
    return confFile->name;
 
1147
}
 
1148
 
 
1149
bool QConfFileSettingsPrivate::isWritable() const
 
1150
{
 
1151
    return writeAccess;
 
1152
}
 
1153
 
 
1154
/*
 
1155
    The following openFile() and closeFile() functions lock the file
 
1156
    (using fcntl() on Unix and a global mutex on Windows), ensuring
 
1157
    that if two instances of the same applications access the file at
 
1158
    the same time, the file isn't corrupted.
 
1159
*/
 
1160
 
 
1161
#ifdef Q_OS_UNIX
 
1162
const int ReadFlags = O_RDONLY | O_CREAT;
 
1163
const int WriteFlags = O_WRONLY | O_CREAT | O_APPEND;
 
1164
#else
 
1165
static const int FileLockSemMax = 50;
 
1166
static const int ReadFlags = 1;
 
1167
static const int WriteFlags = 2;
 
1168
const char SemNamePrefix[] = "QSettings semaphore ";
 
1169
#endif
 
1170
 
 
1171
static bool openFile(QFile &file, QConfFile &confFile, int flags)
 
1172
{
 
1173
#ifdef Q_OS_UNIX
 
1174
    Q_UNUSED(confFile);
 
1175
    int fd = QT_OPEN(QFile::encodeName(file.fileName()), flags, S_IRUSR | S_IWUSR);
 
1176
    if (fd < 0)
 
1177
        return false;
 
1178
 
 
1179
    struct flock fl;
 
1180
    fl.l_whence = SEEK_SET;
 
1181
    fl.l_start = 0;
 
1182
    fl.l_len = 0;
 
1183
    fl.l_type = (flags == WriteFlags) ? F_WRLCK : F_RDLCK;
 
1184
    fcntl(fd, F_SETLKW, &fl);
 
1185
 
 
1186
    if (flags == WriteFlags)
 
1187
        QT_FTRUNCATE(fd, 0);
 
1188
 
 
1189
    return file.open(fd, flags == WriteFlags ? QIODevice::WriteOnly | QIODevice::Text
 
1190
                     : QIODevice::OpenMode(QIODevice::ReadOnly));
 
1191
#else
 
1192
    // on Windows we use a named semaphore
 
1193
    if (confFile.semHandle == 0) {
 
1194
        QString semName = QString::fromAscii(SemNamePrefix);
 
1195
        semName.append(file.fileName());
 
1196
        QT_WA( {
 
1197
            confFile.semHandle = CreateSemaphoreW(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(semName.utf16()));
 
1198
        } , {
 
1199
            confFile.semHandle = CreateSemaphoreA(0, FileLockSemMax, FileLockSemMax, semName.toLocal8Bit());
 
1200
        } );
 
1201
    }
 
1202
 
 
1203
    if (confFile.semHandle != 0) {
 
1204
        int decrement;
 
1205
        if (flags == ReadFlags)
 
1206
            decrement = 1;
 
1207
        else
 
1208
            decrement = FileLockSemMax;
 
1209
 
 
1210
        for (int i = 0; i < decrement; ++i)
 
1211
            WaitForSingleObject(confFile.semHandle, INFINITE);
 
1212
    }
 
1213
 
 
1214
    return file.open(flags == WriteFlags ? QIODevice::WriteOnly | QIODevice::Text
 
1215
                                         : QIODevice::OpenMode(QIODevice::ReadOnly));
 
1216
#endif
 
1217
}
 
1218
 
 
1219
static void closeFile(QFile &file, QConfFile &confFile)
 
1220
{
 
1221
#ifdef Q_OS_UNIX
 
1222
    Q_UNUSED(confFile);
 
1223
    int fd = file.handle();
 
1224
    file.close();
 
1225
    QT_CLOSE(fd);
 
1226
#else
 
1227
    int increment;
 
1228
    if (file.openMode() & QIODevice::ReadOnly)
 
1229
        increment = 1;
 
1230
    else
 
1231
        increment = FileLockSemMax;
 
1232
 
 
1233
    ReleaseSemaphore(confFile.semHandle, increment, 0);
 
1234
    CloseHandle(confFile.semHandle);
 
1235
    confFile.semHandle = 0;
 
1236
 
 
1237
    file.close();
 
1238
#endif
 
1239
}
 
1240
 
 
1241
/*
 
1242
    This only returns false on format errors. Files which don't exist, or which
 
1243
    we don't have read permission for, are treated as empty sets of keys.
 
1244
*/
 
1245
bool QConfFileSettingsPrivate::readFile(QConfFile *confFile)
 
1246
{
 
1247
    QFileInfo fileInfo(confFile->name);
 
1248
    int actualSize = fileInfo.size();
 
1249
    QDateTime actualTimeStamp = fileInfo.lastModified();
 
1250
 
 
1251
    if (confFile->size == actualSize) {
 
1252
        // no need to reload the file if the timestamps and file sizes match
 
1253
        if (confFile->timeStamp == actualTimeStamp)
 
1254
            return true;
 
1255
    }
 
1256
 
 
1257
    SettingsKeyMap newKeys;
 
1258
 
 
1259
    bool ok = true; // we treat unexisting/unreadable files the same as empty files
 
1260
 
 
1261
    if (actualSize != 0) {
 
1262
#ifdef Q_OS_MAC
 
1263
        if (format == QSettings::NativeFormat) {
 
1264
            ok = readPlistFile(confFile->name, &newKeys);
 
1265
        } else
 
1266
#endif
 
1267
        {
 
1268
            QFile file(confFile->name);
 
1269
            if (openFile(file, *confFile, ReadFlags)) {
 
1270
                ok = readIniFile(file, &newKeys);
 
1271
                closeFile(file, *confFile);
 
1272
            }
 
1273
        }
 
1274
    }
 
1275
 
 
1276
    confFile->originalKeys = newKeys;
 
1277
    confFile->size = actualSize;
 
1278
    confFile->timeStamp = actualTimeStamp;
 
1279
 
 
1280
    return ok;
 
1281
}
 
1282
 
 
1283
bool QConfFileSettingsPrivate::writeFile(QConfFile *confFile)
 
1284
{
 
1285
    bool ok = false;
 
1286
 
 
1287
#ifdef Q_OS_MAC
 
1288
    if (format == QSettings::NativeFormat) {
 
1289
        ok = writePlistFile(confFile->name, confFile->originalKeys);
 
1290
    } else
 
1291
#endif
 
1292
    {
 
1293
        QFile file(confFile->name);
 
1294
        if (openFile(file, *confFile, WriteFlags)) {
 
1295
            ok = writeIniFile(file, confFile->originalKeys);
 
1296
            closeFile(file, *confFile);
 
1297
        } else {
 
1298
            return false;
 
1299
        }
 
1300
    }
 
1301
 
 
1302
    QFileInfo fileInfo(confFile->name);
 
1303
    confFile->size = fileInfo.size();
 
1304
    confFile->timeStamp = fileInfo.lastModified();
 
1305
 
 
1306
    return ok;
 
1307
}
 
1308
 
 
1309
bool QConfFileSettingsPrivate::readIniLine(QIODevice &device, QByteArray &line, int &len,
 
1310
                                           int &equalsCharPos)
 
1311
{
 
1312
#define MAYBE_GROW() \
 
1313
    if (pos + 4 > line.size()) { \
 
1314
        line.resize(pos << 1); \
 
1315
        data = line.data(); \
 
1316
    }
 
1317
 
 
1318
    char *data = line.data();
 
1319
    char ch, ch2;
 
1320
    int pos = 0;
 
1321
 
 
1322
    equalsCharPos = -1;
 
1323
 
 
1324
    while (device.getChar(&ch)) {
 
1325
    process_ch:
 
1326
        MAYBE_GROW();
 
1327
 
 
1328
        switch (ch) {
 
1329
        case '"':
 
1330
            data[pos++] = '"';
 
1331
            while (!device.getChar(&ch) || ch != '"') {
 
1332
                MAYBE_GROW();
 
1333
 
 
1334
                if (static_cast<signed char>(ch) == -1)
 
1335
                    goto end;
 
1336
 
 
1337
                if (ch == '\\') {
 
1338
                    data[pos++] = '\\';
 
1339
                    if (!device.getChar(&ch))
 
1340
                        goto end;
 
1341
                }
 
1342
                data[pos++] = ch;
 
1343
            }
 
1344
            data[pos++] = '"';
 
1345
            break;
 
1346
        case ' ':
 
1347
        case '\t':
 
1348
            if (pos > 0)
 
1349
                data[pos++] = ch;
 
1350
            break;
 
1351
        case '\n':
 
1352
        case '\r':
 
1353
        process_newline:
 
1354
            /*
 
1355
                According to the specs, a line ends with CF, LF,
 
1356
                CR+LF, or LF+CR. In practice, this is irrelevant and
 
1357
                the ungetch() call is expensive, so let's not do it.
 
1358
            */
 
1359
#if 0
 
1360
            if (!device.getChar(&ch2))
 
1361
                goto end;
 
1362
            if ((ch2 != '\n' && ch2 != '\r') || ch == ch2)
 
1363
                device.ungetChar(ch2);
 
1364
#endif
 
1365
            if (pos > 0)
 
1366
                goto end;
 
1367
            break;
 
1368
        case '\\':
 
1369
            if (!device.getChar(&ch))
 
1370
                goto end;
 
1371
 
 
1372
            if (ch == '\n' || ch == '\r') {
 
1373
                if (!device.getChar(&ch2)) {
 
1374
                    if ((ch2 != '\n' && ch2 != '\r') || ch == ch2) {
 
1375
                        ch = ch2;
 
1376
                        goto process_ch;
 
1377
                    }
 
1378
                }
 
1379
            } else {
 
1380
                data[pos++] = '\\';
 
1381
                data[pos++] = ch;
 
1382
            }
 
1383
            break;
 
1384
        case ';':
 
1385
            while (device.getChar(&ch)) {
 
1386
                if (ch == '\n' || ch == '\r')
 
1387
                    goto process_newline;
 
1388
            }
 
1389
            break;
 
1390
        case '=':
 
1391
            if (equalsCharPos == -1) {
 
1392
                while (pos > 0 && (ch = data[pos - 1]) == ' ' || ch == '\t')
 
1393
                    --pos;
 
1394
                equalsCharPos = pos;
 
1395
            }
 
1396
            data[pos++] = '=';
 
1397
            break;
 
1398
        default:
 
1399
            data[pos++] = ch;
 
1400
        }
 
1401
    }
 
1402
 
 
1403
end:
 
1404
    data[pos] = '\0';
 
1405
    len = pos;
 
1406
    return pos > 0;
 
1407
}
 
1408
 
 
1409
/*
 
1410
    Returns false on parse error. However, as many keys are read as
 
1411
    possible, so if the user doesn't check the status he will get the
 
1412
    most out of the file anyway.
 
1413
*/
 
1414
bool QConfFileSettingsPrivate::readIniFile(QIODevice &device, SettingsKeyMap *map)
 
1415
{
 
1416
    QString currentSection;
 
1417
    bool currentSectionIsLowerCase = true;
 
1418
    QByteArray line;
 
1419
    line.resize(512);
 
1420
    int equalsCharPos;
 
1421
    int len;
 
1422
 
 
1423
    bool ok = true;
 
1424
 
 
1425
    while (readIniLine(device, line, len, equalsCharPos)) {
 
1426
        if (line.at(0) == '[') {
 
1427
            // this is a section
 
1428
            QByteArray iniSection;
 
1429
            int idx = line.indexOf(']');
 
1430
            if (idx == -1) {
 
1431
                ok = false;
 
1432
                iniSection = line.mid(1);
 
1433
            } else {
 
1434
                iniSection = line.mid(1, idx - 1);
 
1435
            }
 
1436
 
 
1437
            iniSection = iniSection.trimmed();
 
1438
 
 
1439
            if (qstricmp(iniSection, "general") == 0) {
 
1440
                currentSection.clear();
 
1441
            } else if (qstricmp(iniSection, "%general") == 0) {
 
1442
                currentSection = QLatin1String("general");
 
1443
                currentSection += QLatin1Char('/');
 
1444
            } else {
 
1445
                currentSection.clear();
 
1446
                currentSectionIsLowerCase = iniUnescapedKey(iniSection, 0, iniSection.size(),
 
1447
                                                            currentSection);
 
1448
                currentSection += QLatin1Char('/');
 
1449
            }
 
1450
        } else {
 
1451
            if (equalsCharPos < 1) {
 
1452
                ok = false;
 
1453
                continue;
 
1454
            }
 
1455
 
 
1456
            QString key = currentSection;
 
1457
            bool keyIsLowerCase = (iniUnescapedKey(line, 0, equalsCharPos, key)
 
1458
                                   && currentSectionIsLowerCase);
 
1459
 
 
1460
            QString strValue;
 
1461
            strValue.reserve(len - equalsCharPos);
 
1462
            QStringList *strListValue = iniUnescapedStringList(line, equalsCharPos + 1, len,
 
1463
                                                               strValue);
 
1464
            QVariant variant;
 
1465
            if (strListValue) {
 
1466
                variant = stringListToVariantList(*strListValue);
 
1467
                delete strListValue;
 
1468
            } else {
 
1469
                variant = stringToVariant(strValue);
 
1470
            }
 
1471
 
 
1472
            /*
 
1473
                We try to avoid the expensive toLower() call in
 
1474
                QSettingsKey by passing Qt::CaseSensitive when the
 
1475
                key is already in lower-case.
 
1476
            */
 
1477
            map->insert(QSettingsKey(key, keyIsLowerCase ? Qt::CaseSensitive : Qt::CaseInsensitive),
 
1478
                        variant);
 
1479
        }
 
1480
    }
 
1481
 
 
1482
    return ok;
 
1483
}
 
1484
 
 
1485
bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const SettingsKeyMap &map)
 
1486
{
 
1487
    typedef QMap<QString, QVariantMap> IniMap;
 
1488
    IniMap iniMap;
 
1489
    IniMap::const_iterator i;
 
1490
 
 
1491
    for (SettingsKeyMap::const_iterator j = map.constBegin(); j != map.constEnd(); ++j) {
 
1492
        QString section;
 
1493
        QString key = j.key().realKey();
 
1494
        int slashPos;
 
1495
 
 
1496
        if ((slashPos = key.indexOf(QLatin1Char('/'))) != -1) {
 
1497
            section = key.left(slashPos);
 
1498
            key.remove(0, slashPos + 1);
 
1499
        }
 
1500
        iniMap[section][key] = j.value();
 
1501
    }
 
1502
 
 
1503
    bool writeError = false;
 
1504
    for (i = iniMap.constBegin(); !writeError && i != iniMap.constEnd(); ++i) {
 
1505
        QByteArray realSection;
 
1506
 
 
1507
        iniEscapedKey(i.key(), realSection);
 
1508
 
 
1509
        if (realSection.isEmpty()) {
 
1510
            realSection = "[General]";
 
1511
        } else if (qstricmp(realSection, "general") == 0) {
 
1512
            realSection = "[%General]";
 
1513
        } else {
 
1514
            realSection.prepend('[');
 
1515
            realSection.append(']');
 
1516
        }
 
1517
 
 
1518
        if (i != iniMap.constBegin())
 
1519
            realSection.prepend('\n');
 
1520
        realSection += '\n';
 
1521
 
 
1522
        device.write(realSection);
 
1523
 
 
1524
        const QVariantMap &ents = i.value();
 
1525
        for (QVariantMap::const_iterator j = ents.constBegin(); j != ents.constEnd(); ++j) {
 
1526
            QByteArray block;
 
1527
            iniEscapedKey(j.key(), block);
 
1528
            block += '=';
 
1529
 
 
1530
            const QVariant &value = j.value();
 
1531
            if (value.type() == QVariant::StringList || value.type() == QVariant::List) {
 
1532
                iniEscapedStringList(variantListToStringList(value.toList()), block);
 
1533
            } else {
 
1534
                iniEscapedString(variantToString(value), block);
 
1535
            }
 
1536
            block += '\n';
 
1537
            if (device.write(block) == -1) {
 
1538
                writeError = true;
 
1539
                break;
 
1540
            }
 
1541
        }
 
1542
    }
 
1543
    return !writeError;
 
1544
}
 
1545
 
 
1546
/*!
 
1547
    \class QSettings
 
1548
    \brief The QSettings class provides persistent platform-independent application settings.
 
1549
 
 
1550
    \ingroup io
 
1551
    \ingroup misc
 
1552
    \mainclass
 
1553
    \reentrant
 
1554
 
 
1555
    Users normally expect an application to remember its settings
 
1556
    (window sizes and positions, options, etc.) across sessions. This
 
1557
    information is often stored in the system registry on Windows,
 
1558
    and in XML preferences files on Mac OS X. On X11 and embedded Linux,
 
1559
    in the absense of a standard, many applications (including the KDE
 
1560
    applications) use INI text files.
 
1561
 
 
1562
    QSettings is an abstraction around these technologies,
 
1563
    enabling you to save and restore application settings in a
 
1564
    portable manner.
 
1565
 
 
1566
    QSettings's API is based on QVariant, allowing you to save
 
1567
    most value-based types, such as QString, QRect, and QImage,
 
1568
    with the minimum of effort.
 
1569
 
 
1570
    \tableofcontents section1
 
1571
 
 
1572
    \section1 Basic Usage
 
1573
 
 
1574
    When creating a QSettings object, you must pass the name of your
 
1575
    company or organization as well as the name of your application.
 
1576
    For example, if your product is called Star Runner and your
 
1577
    company is called MySoft, you would construct the QSettings
 
1578
    object as follows:
 
1579
 
 
1580
    \quotefromfile snippets/settings/settings.cpp
 
1581
    \skipuntil snippet_ctor1
 
1582
    \skipline {
 
1583
    \printline QSettings settings
 
1584
 
 
1585
    QSettings objects can be created either on the stack or on
 
1586
    the heap (i.e. using \c new). Constructing and destroying a
 
1587
    QSettings object is very fast.
 
1588
 
 
1589
    If you use QSettings from many places in your application, you
 
1590
    might want to specify the organization name and the application
 
1591
    name using QCoreApplication::setOrganizationName() and
 
1592
    QCoreApplication::setApplicationName(), and then use the default
 
1593
    QSettings constructor:
 
1594
 
 
1595
    \skipuntil snippet_ctor2
 
1596
    \skipline {
 
1597
    \printline setOrganizationName
 
1598
    \printline setOrganizationDomain
 
1599
    \printline setApplicationName
 
1600
    \dots
 
1601
    \printline QSettings settings;
 
1602
 
 
1603
    (Here, we also specify the organization's Internet domain. When
 
1604
    the Internet domain is set, it is used on Mac OS X instead of the
 
1605
    organization name, since Mac OS X applications conventionally use
 
1606
    Internet domains to identify themselves. If no domain is set, a
 
1607
    fake domain is derived from the organization name. See the
 
1608
    \l{Platform-Specific Notes} below for details.)
 
1609
 
 
1610
    QSettings stores settings. Each setting consists of a QString
 
1611
    that specifies the setting's name (the \e key) and a QVariant
 
1612
    that stores the data associated with the key. To write a setting,
 
1613
    use setValue(). For example:
 
1614
 
 
1615
    \printline setValue(
 
1616
 
 
1617
    If there already exists a setting with the same key, the existing
 
1618
    value is overwritten by the new value. For efficiency, the
 
1619
    changes may not be saved to permanent storage immediately. (You
 
1620
    can always call sync() to commit your changes.)
 
1621
 
 
1622
    You can get a setting's value back using value():
 
1623
 
 
1624
    \printline settings.value(
 
1625
 
 
1626
    If there is no setting with the specified name, QSettings
 
1627
    returns a null QVariant (which can be converted to the integer 0).
 
1628
    You can specify another default value by passing a second
 
1629
    argument to value():
 
1630
 
 
1631
    \skipline {
 
1632
    \printline /settings.value\(.*,.*\)/
 
1633
    \skipline }
 
1634
 
 
1635
    To test whether a given key exists, call contains(). To remove
 
1636
    the setting associated with a key, call remove(). To obtain the
 
1637
    list of all keys, call allKeys(). To remove all keys, call
 
1638
    clear().
 
1639
 
 
1640
    \section1 QVariant and GUI Types
 
1641
 
 
1642
    Because QVariant is part of the \l QtCore library, it cannot provide
 
1643
    conversion functions to data types such as QColor, QImage, and
 
1644
    QPixmap, which are part of \l QtGui. In other words, there is no
 
1645
    \c QVariant::toColor() function.
 
1646
 
 
1647
    Instead, you can use the QVariant::value() or the qVariantValue()
 
1648
    template function. For example:
 
1649
 
 
1650
    \code
 
1651
        QSettings settings("MySoft", "Star Runner");
 
1652
        QColor color = settings.value("DataPump/bgcolor").value<QColor>();
 
1653
    \endcode
 
1654
 
 
1655
    The inverse conversion (e.g., from QColor to QVariant) is
 
1656
    automatic for all data types supported by QVariant, including
 
1657
    GUI-related types:
 
1658
 
 
1659
    \code
 
1660
        QSettings settings("MySoft", "Star Runner");
 
1661
        QColor color = palette().background().color();
 
1662
        settings.setValue("DataPump/bgcolor", color);
 
1663
    \endcode
 
1664
 
 
1665
    \section1 Key Syntax
 
1666
 
 
1667
    Setting keys can contain any Unicode characters. The Windows
 
1668
    registry and INI files use case-insensitive keys, whereas the
 
1669
    Carbon Preferences API on Mac OS X uses case-sensitive keys. To
 
1670
    avoid portability problems, follow these two simple rules:
 
1671
 
 
1672
    \list 1
 
1673
    \o Always refer to the same key using the same case. For example,
 
1674
       if you refer to a key as "text fonts" in one place in your
 
1675
       code, don't refer to it as "Text Fonts" somewhere else.
 
1676
 
 
1677
    \o Avoid key names that are identical except for the case. For
 
1678
       example, if you have a key called "MainWindow", don't try to
 
1679
       save another key as "mainwindow".
 
1680
    \endlist
 
1681
 
 
1682
    You can form hierarchical keys using the '/' character as a
 
1683
    separator, similar to Unix file paths. For example:
 
1684
 
 
1685
    \printline setValue
 
1686
    \printline setValue
 
1687
    \printline setValue
 
1688
 
 
1689
    If you want to save or restore many settings with the same
 
1690
    prefix, you can specify the prefix using beginGroup() and call
 
1691
    endGroup() at the end. Here's the same example again, but this
 
1692
    time using the group mechanism:
 
1693
 
 
1694
    \printline beginGroup
 
1695
    \printuntil endGroup
 
1696
    \printline beginGroup
 
1697
    \printuntil endGroup
 
1698
 
 
1699
    If a group is set using beginGroup(), the behavior of most
 
1700
    functions changes consequently. Groups can be set recursively.
 
1701
 
 
1702
    In addition to groups, QSettings also supports an "array"
 
1703
    concept. See beginReadArray() and beginWriteArray() for details.
 
1704
 
 
1705
    \section1 Fallback Mechanism
 
1706
 
 
1707
    Let's assume that you have created a QSettings object with the
 
1708
    organization name MySoft and the application name Star Runner.
 
1709
    When you look up a value, up to four locations are searched in
 
1710
    that order:
 
1711
 
 
1712
    \list 1
 
1713
    \o a user-specific location for the Star Runner application
 
1714
    \o a user-spefific location for all applications by MySoft
 
1715
    \o a system-wide location for the Star Runner application
 
1716
    \o a system-wide location for all applications by MySoft
 
1717
    \endlist
 
1718
 
 
1719
    On Unix with X11 and on embedded Linux, these locations are the
 
1720
    following files:
 
1721
 
 
1722
    \list 1
 
1723
    \o \c{$HOME/.config/MySoft/Star Runner.conf}
 
1724
    \o \c{$HOME/.config/MySoft.conf}
 
1725
    \o \c{/etc/xdg/MySoft/Star Runner.conf}
 
1726
    \o \c{/etc/xdg/MySoft.conf}
 
1727
    \endlist
 
1728
 
 
1729
    On Mac OS X versions 10.2 and 10.3, these files are used:
 
1730
 
 
1731
    \list 1
 
1732
    \o \c{$HOME/Library/Preferences/com.MySoft.Star Runner.plist}
 
1733
    \o \c{$HOME/Library/Preferences/com.MySoft.plist}
 
1734
    \o \c{/Library/Preferences/com.MySoft.Star Runner.plist}
 
1735
    \o \c{/Library/Preferences/com.MySoft.plist}
 
1736
    \endlist
 
1737
 
 
1738
    On Windows, the settings are stored in the following registry
 
1739
    paths:
 
1740
 
 
1741
    \list 1
 
1742
    \o \c{HKEY_CURRENT_USER\Software\MySoft\Star Runner}
 
1743
    \o \c{HKEY_CURRENT_USER\Software\MySoft}
 
1744
    \o \c{HKEY_LOCAL_MACHINE\Software\MySoft\Star Runner}
 
1745
    \o \c{HKEY_LOCAL_MACHINE\Software\MySoft}
 
1746
    \endlist
 
1747
 
 
1748
    If a key cannot be found in the first location, the search goes
 
1749
    on in the second location, and so on. This enables you to store
 
1750
    system-wide or organization-wide settings and to override them on
 
1751
    a per-user or per-application basis. To turn off this mechanism,
 
1752
    call setFallbacksEnabled(false).
 
1753
 
 
1754
    Although keys from all four locations are available for reading,
 
1755
    only the first file (the user-specific location for the
 
1756
    application at hand) is accessible for writing. To write to any
 
1757
    of the other files, omit the application name and/or specify
 
1758
    QSettings::SystemScope (as opposed to QSettings::UserScope, the
 
1759
    default).
 
1760
 
 
1761
    Let's see with an example:
 
1762
 
 
1763
    \skipuntil snippet_locations
 
1764
    \skipline {
 
1765
    \printline obj1
 
1766
    \printuntil obj4
 
1767
 
 
1768
    The table below summarizes which QSettings objects access
 
1769
    which location. "\bold{X}" means that the location is the main
 
1770
    location associated to the QSettings object and is used both
 
1771
    for reading and for writing; "o" means that the location is used
 
1772
    as a fallback when reading.
 
1773
 
 
1774
    \table
 
1775
    \header \o Locations               \o \c{obj1} \o \c{obj2} \o \c{obj3} \o \c{obj4}
 
1776
    \row    \o 1. User, Application    \o \bold{X} \o          \o          \o
 
1777
    \row    \o 2. User, Organization   \o o        \o \bold{X} \o          \o
 
1778
    \row    \o 3. System, Application  \o o        \o          \o \bold{X} \o
 
1779
    \row    \o 4. System, Organization \o o        \o o        \o o        \o \bold{X}
 
1780
    \endtable
 
1781
 
 
1782
    The beauty of this mechanism is that it works on all platforms
 
1783
    supported by Qt and that it still gives you a lot of flexibility,
 
1784
    without requiring you to specify any file names or registry
 
1785
    paths.
 
1786
 
 
1787
    If you want to use INI files on all platforms instead of the
 
1788
    native API, you can pass QSettings::IniFormat as the first
 
1789
    argument to the QSettings constructor, followed by the scope, the
 
1790
    organization name, and the application name:
 
1791
 
 
1792
    \printline /settings\(.*,$/
 
1793
    \printline );
 
1794
 
 
1795
    Sometimes you do want to access settings stored in a specific
 
1796
    file or registry path. In that case, you can use a constructor
 
1797
    that takes a file name (or registry path) and a file format. For
 
1798
    example:
 
1799
 
 
1800
    \printline /QSettings settings.*Ini/
 
1801
 
 
1802
    The file format can either be QSettings::IniFormat or QSettings::NativeFormat.
 
1803
    On Mac OS X, the native format is an XML-based format called \e
 
1804
    plist. On Windows, the native format is the Windows registry, and
 
1805
    the first argument is a path in the registry rather than a file
 
1806
    name, for example:
 
1807
 
 
1808
    \printline HKEY
 
1809
    \printline Native
 
1810
 
 
1811
    On X11 and embedded Linux, QSettings::IniFormat and QSettings::NativeFormat have
 
1812
    the same meaning.
 
1813
 
 
1814
    The \l{tools/settingseditor}{Settings Editor} example lets you
 
1815
    experiment with different settings location and with fallbacks
 
1816
    turned on or off.
 
1817
 
 
1818
    \section1 Restoring the State of a GUI Application
 
1819
 
 
1820
    QSettings is often used to store the state of a GUI
 
1821
    application. The following example will illustrate how to use we
 
1822
    will use QSettings to save and restore the geometry of an
 
1823
    application's main window.
 
1824
 
 
1825
    \skipto ::writeSettings
 
1826
    \printuntil /^\}$/
 
1827
    \skipto ::readSettings
 
1828
    \printuntil /^\}$/
 
1829
 
 
1830
    See \l{Window Geometry} for a discussion on why it is better to
 
1831
    call QWidget::resize() and QWidget::move() rather than QWidget::setGeometry()
 
1832
    to restore a window's geometry.
 
1833
 
 
1834
    The \c readSettings() and \c writeSettings() functions must be
 
1835
    called from the main window's constructor and close event handler
 
1836
    as follows:
 
1837
 
 
1838
    \skipto ::MainWindow
 
1839
    \printuntil {
 
1840
    \dots
 
1841
    \printline readSettings
 
1842
    \printline }
 
1843
 
 
1844
    \skipto ::closeEvent
 
1845
    \printuntil /^\}/
 
1846
 
 
1847
    See the \l{mainwindows/application}{Application} example for a
 
1848
    self-contained example that uses QSettings.
 
1849
 
 
1850
    \section1 Accessing Settings from Multiple Threads or Processes Simultaneously
 
1851
 
 
1852
    QSettings is \l{reentrant}. This means that you can use
 
1853
    distinct QSettings object in different threads
 
1854
    simultaneously. This guarantee stands even when the QSettings
 
1855
    objects refer to the same files on disk (or to the same entries
 
1856
    in the system registry). If a setting is modified through one
 
1857
    QSettings object, the change will immediately be visible in
 
1858
    any other QSettings objects that operate on the same location
 
1859
    and that live in the same process.
 
1860
 
 
1861
    QSettings can safely be used from different processes (which
 
1862
    can be different instances of your application running at the
 
1863
    same time or different applications altogether) to read and write
 
1864
    to the same system locations. It uses a smart merging algorithm
 
1865
    to ensure data integrity. Changes performed by another process
 
1866
    aren't visible in the current process until sync() is called.
 
1867
 
 
1868
    \section1 Platform-Specific Notes
 
1869
 
 
1870
    While QSettings attempts to smooth over the differences
 
1871
    between the different supported platforms, there are still a few
 
1872
    differences that you should be aware of when porting your
 
1873
    application:
 
1874
 
 
1875
    \list
 
1876
    \o  The Windows system registry has the following limitations: A
 
1877
        subkey may not exceed 255 characters, an entry's value may
 
1878
        not exceed 16,383 characters, and all the values of a key may
 
1879
        not exceed 65,535 characters. One way to work around these
 
1880
        limitations is to store the settings using the IniFormat
 
1881
        instead of the NativeFormat.
 
1882
 
 
1883
    \o  On Mac OS X, allKeys() will return some extra keys for global
 
1884
        settings that apply to all applications. These keys can be
 
1885
        read using value() but cannot be changed, only shadowed.
 
1886
        Calling setFallbacksEnabled(false) will hide these global
 
1887
        settings.
 
1888
 
 
1889
    \o  On Mac OS X, the APIs used by QSettings expect an Internet
 
1890
        domain name rather than an organization name. To provide a
 
1891
        uniform API, QSettings derives a fake domain name from the
 
1892
        organization name (unless the organization name already is a
 
1893
        domain name, e.g. OpenOffice.org). The algorithm appends
 
1894
        ".com" to the company name and replaces spaces and other
 
1895
        illegal characters with hyphens. If you want to specify a
 
1896
        different domain name, call
 
1897
        QCoreApplication::setOrganizationDomain(),
 
1898
        QCoreApplication::setOrganizationName(), and
 
1899
        QCoreApplication::setApplicationName() in your \c main()
 
1900
        function and then use the default QSettings constructor.
 
1901
        Another solution is to use preprocessor directives, for
 
1902
        example:
 
1903
 
 
1904
        \code
 
1905
        #ifdef Q_WS_MAC
 
1906
            QSettings settings("grenoullelogique.fr", "Squash");
 
1907
        #else
 
1908
            QSettings settings("Grenoulle Logique", "Squash");
 
1909
        #endif
 
1910
        \endcode
 
1911
    \endlist
 
1912
 
 
1913
    \sa {tools/settingseditor}{Settings Editor Example},
 
1914
        QVariant, QSessionManager
 
1915
*/
 
1916
 
 
1917
/*! \enum QSettings::Status
 
1918
 
 
1919
    The following status values are possible:
 
1920
 
 
1921
    \value NoError  No error occurred.
 
1922
    \value AccessError  An access error occurred (e.g. trying to write to a read-only file).
 
1923
    \value FormatError  A format error occurred (e.g. loading a malformed INI file).
 
1924
 
 
1925
    \sa status()
 
1926
*/
 
1927
 
 
1928
/*! \enum QSettings::Format
 
1929
 
 
1930
    This enum type specifies the storage format used by QSettings.
 
1931
 
 
1932
    \value NativeFormat  Store the settings using the most
 
1933
                         appropriate storage format for the platform.
 
1934
                         On Windows, this means the system registry;
 
1935
                         on Mac OS X, this means the CFPreferences
 
1936
                         API; on Unix/X11, this means textual
 
1937
                         configuration files in INI format.
 
1938
    \value IniFormat  Store the settings in INI files.
 
1939
 
 
1940
    On Unix/X11, NativeFormat and IniFormat mean the same
 
1941
    thing, except that the file extension is different (\c .conf for
 
1942
    NativeFormat, \c .ini for IniFormat).
 
1943
 
 
1944
    The INI file format is a Windows file format that Qt supports on
 
1945
    all platforms.
 
1946
*/
 
1947
 
 
1948
/*! \enum QSettings::Scope
 
1949
 
 
1950
    This enum specifies whether settings are user-specific or shared
 
1951
    by all users of the same system.
 
1952
 
 
1953
    \value UserScope  Store settings in a location specific to the
 
1954
                      current user (e.g., in the user's home
 
1955
                      directory).
 
1956
    \value SystemScope  Store settings in a global location, so that
 
1957
                        all users on the same machine access the same
 
1958
                        set of settings.
 
1959
    \omitvalue User
 
1960
    \omitvalue Global
 
1961
*/
 
1962
 
 
1963
#ifndef QT_NO_QOBJECT
 
1964
/*!
 
1965
    Constructs a QSettings object for accessing settings of the
 
1966
    application called \a application from the organization called \a
 
1967
    organization, and with parent \a parent.
 
1968
 
 
1969
    Example:
 
1970
    \code
 
1971
        QSettings settings("Moose Tech", "Facturo-Pro");
 
1972
    \endcode
 
1973
 
 
1974
    The scope is QSettings::UserScope and the format is
 
1975
    QSettings::NativeFormat.
 
1976
 
 
1977
    \sa {Fallback Mechanism}
 
1978
*/
 
1979
QSettings::QSettings(const QString &organization, const QString &application, QObject *parent)
 
1980
    : QObject(*QSettingsPrivate::create(NativeFormat, UserScope, organization, application),
 
1981
              parent)
 
1982
{
 
1983
}
 
1984
 
 
1985
/*!
 
1986
    Constructs a QSettings object for accessing settings of the
 
1987
    application called \a application from the organization called \a
 
1988
    organization, and with parent \a parent.
 
1989
 
 
1990
    If \a scope is QSettings::UserScope, the QSettings object searches
 
1991
    user-specific settings first, before it searches system-wide
 
1992
    settings as a fallback. If \a scope is
 
1993
    QSettings::SystemScope, the QSettings object ignores user-specific
 
1994
    settings and provides access to system-wide settings.
 
1995
 
 
1996
    The storage format is always QSettings::NativeFormat.
 
1997
 
 
1998
    If no application name is given, the QSettings object will
 
1999
    only access the organization-wide \l{Fallback Mechanism}{locations}.
 
2000
*/
 
2001
QSettings::QSettings(Scope scope, const QString &organization, const QString &application,
 
2002
                     QObject *parent)
 
2003
    : QObject(*QSettingsPrivate::create(NativeFormat, scope, organization, application), parent)
 
2004
{
 
2005
}
 
2006
 
 
2007
/*!
 
2008
    Constructs a QSettings object for accessing settings of the
 
2009
    application called \a application from the organization called
 
2010
    \a organization, and with parent \a parent.
 
2011
 
 
2012
    If \a scope is QSettings::UserScope, the QSettings object searches
 
2013
    user-specific settings first, before it searches system-wide
 
2014
    settings as a fallback. If \a scope is
 
2015
    QSettings::SystemScope, the QSettings object ignores user-specific
 
2016
    settings and provides access to system-wide settings.
 
2017
 
 
2018
    If \a format is QSettings::NativeFormat, the native API is used for
 
2019
    storing settings. If \a format is QSettings::IniFormat, the INI format
 
2020
    is used.
 
2021
 
 
2022
    If no application name is given, the QSettings object will
 
2023
    only access the organization-wide \l{Fallback Mechanism}{locations}.
 
2024
*/
 
2025
QSettings::QSettings(Format format, Scope scope, const QString &organization,
 
2026
                     const QString &application, QObject *parent)
 
2027
    : QObject(*QSettingsPrivate::create(format, scope, organization, application),
 
2028
              parent)
 
2029
{
 
2030
}
 
2031
 
 
2032
/*!
 
2033
    Constructs a QSettings object for accessing the settings
 
2034
    stored in the file called \a fileName, with parent \a parent. If
 
2035
    the file doesn't already exist, it is created.
 
2036
 
 
2037
    If \a format is QSettings::NativeFormat, the meaning of \a fileName
 
2038
    depends on the platform. On Unix/X11, \a fileName is the name of
 
2039
    an INI file. On Mac OS X, \a fileName is the name of a .plist
 
2040
    file. On Windows, \a fileName is a path in the system registry.
 
2041
 
 
2042
    If \a format is QSettings::IniFormat, \a fileName is the name of an INI
 
2043
    file.
 
2044
 
 
2045
    \sa fileName()
 
2046
*/
 
2047
QSettings::QSettings(const QString &fileName, Format format, QObject *parent)
 
2048
    : QObject(*QSettingsPrivate::create(fileName, format), parent)
 
2049
{
 
2050
}
 
2051
 
 
2052
/*!
 
2053
    Constructs a QSettings object for accessing settings of the
 
2054
    application and organization set previously with a call to
 
2055
    QCoreApplication::setOrganizationName(),
 
2056
    QCoreApplication::setOrganizationDomain(), and
 
2057
    QCoreApplication::setApplicationName().
 
2058
 
 
2059
    The scope is QSettings::UserScope and the format is QSettings::NativeFormat.
 
2060
 
 
2061
    The code
 
2062
 
 
2063
    \code
 
2064
        QSettings settings("Moose Soft", "Facturo-Pro");
 
2065
    \endcode
 
2066
 
 
2067
    is equivalent to
 
2068
 
 
2069
    \code
 
2070
        QCoreApplication::setOrganizationName("Moose Soft");
 
2071
        QCoreApplication::setApplicationName("Facturo-Pro");
 
2072
        QSettings settings;
 
2073
    \endcode
 
2074
 
 
2075
    If QCoreApplication::setOrganizationName() and
 
2076
    QCoreApplication::setApplicationName() has not been previously
 
2077
    called, the QSettings object will not be able to read or write
 
2078
    any settings, and status() will return AccessError.
 
2079
 
 
2080
    On Mac OS X, if both a name and an Internet domain are specified
 
2081
    for the organization, the domain is preferred over the name. On
 
2082
    other platforms, the name is preferred over the domain.
 
2083
 
 
2084
    \sa QCoreApplication::setOrganizationName(),
 
2085
        QCoreApplication::setOrganizationDomain(),
 
2086
        QCoreApplication::setApplicationName()
 
2087
*/
 
2088
QSettings::QSettings(QObject *parent)
 
2089
    : QObject(*QSettingsPrivate::create(NativeFormat, UserScope,
 
2090
#ifdef Q_OS_MAC
 
2091
                                        QCoreApplication::organizationDomain().isEmpty()
 
2092
                                            ? QCoreApplication::organizationName()
 
2093
                                            : QCoreApplication::organizationDomain()
 
2094
#else
 
2095
                                        QCoreApplication::organizationName().isEmpty()
 
2096
                                            ? QCoreApplication::organizationDomain()
 
2097
                                            : QCoreApplication::organizationName()
 
2098
#endif
 
2099
                                        , QCoreApplication::applicationName()),
 
2100
              parent)
 
2101
{
 
2102
}
 
2103
 
 
2104
#else
 
2105
QSettings::QSettings(const QString &organization, const QString &application)
 
2106
    : d_ptr(QSettingsPrivate::create(QSettings::NativeFormat, QSettings::UserScope, organization, application))
 
2107
{
 
2108
    d_ptr->q_ptr = this;
 
2109
}
 
2110
 
 
2111
QSettings::QSettings(Scope scope, const QString &organization, const QString &application)
 
2112
    : d_ptr(QSettingsPrivate::create(QSettings::NativeFormat, scope, organization, application))
 
2113
{
 
2114
    d_ptr->q_ptr = this;
 
2115
}
 
2116
 
 
2117
QSettings::QSettings(Format format, Scope scope, const QString &organization,
 
2118
                     const QString &application)
 
2119
    : d_ptr(QSettingsPrivate::create(format, scope, organization, application))
 
2120
{
 
2121
    d_ptr->q_ptr = this;
 
2122
}
 
2123
 
 
2124
QSettings::QSettings(const QString &fileName, Format format)
 
2125
    : d_ptr(QSettingsPrivate::create(fileName, format))
 
2126
{
 
2127
    d_ptr->q_ptr = this;
 
2128
}
 
2129
#endif
 
2130
 
 
2131
/*!
 
2132
    Destroys the QSettings object.
 
2133
 
 
2134
    Any unsaved changes will eventually be written to permanent
 
2135
    storage.
 
2136
 
 
2137
    \sa sync()
 
2138
*/
 
2139
QSettings::~QSettings()
 
2140
{
 
2141
    Q_D(QSettings);
 
2142
    if (d->pendingChanges)
 
2143
        d->flush();
 
2144
#ifdef QT_NO_QOBJECT
 
2145
    delete d;
 
2146
#endif
 
2147
}
 
2148
 
 
2149
/*!
 
2150
    Removes all entries in the primary location associated to this
 
2151
    QSettings object.
 
2152
 
 
2153
    Entries in fallback locations are not removed.
 
2154
 
 
2155
    If you only want to remove the entries in the current group(),
 
2156
    use remove("") instead.
 
2157
 
 
2158
    \sa remove(), setFallbacksEnabled()
 
2159
*/
 
2160
void QSettings::clear()
 
2161
{
 
2162
    Q_D(QSettings);
 
2163
    d->clear();
 
2164
    d->requestUpdate();
 
2165
}
 
2166
 
 
2167
/*!
 
2168
    Writes any unsaved changes to permanent storage, and reloads any
 
2169
    settings that have been changed in the meantime by another
 
2170
    application.
 
2171
 
 
2172
    Unless you use QSettings as a communication mechanism between
 
2173
    different processes, you normally don't need to call this
 
2174
    function.
 
2175
*/
 
2176
void QSettings::sync()
 
2177
{
 
2178
    Q_D(QSettings);
 
2179
    d->sync();
 
2180
}
 
2181
 
 
2182
/*!
 
2183
    Returns the path where settings written using this QSettings
 
2184
    object are stored.
 
2185
 
 
2186
    On Windows, if the format is QSettings::NativeFormat, the return value
 
2187
    is a system registry path, not a file path.
 
2188
 
 
2189
    \sa isWritable()
 
2190
*/
 
2191
QString QSettings::fileName() const
 
2192
{
 
2193
    Q_D(const QSettings);
 
2194
    return d->fileName();
 
2195
}
 
2196
 
 
2197
/*!
 
2198
    Returns a status code indicating the first error that was met by
 
2199
    QSettings, or QSettings::NoError if no error occurred.
 
2200
*/
 
2201
QSettings::Status QSettings::status() const
 
2202
{
 
2203
    Q_D(const QSettings);
 
2204
    return d->status;
 
2205
}
 
2206
 
 
2207
/*!
 
2208
    Appends \a prefix to the current group.
 
2209
 
 
2210
    The current group is automatically prepended to all keys
 
2211
    specified to QSettings. In addition, query functions such as
 
2212
    childGroups(), childKeys(), and allKeys() are based on the group.
 
2213
    By default, no group is set.
 
2214
 
 
2215
    Groups are useful to avoid typing in the same setting paths over
 
2216
    and over. For example:
 
2217
 
 
2218
    \code
 
2219
        settings.beginGroup("mainwindow");
 
2220
        settings.setValue("size", win->size());
 
2221
        settings.setValue("fullScreen", win->isFullScreen());
 
2222
        settings.endGroup();
 
2223
 
 
2224
        settings.beginGroup("outputpanel");
 
2225
        settings.setValue("visible", panel->isVisible());
 
2226
        settings.endGroup();
 
2227
    \endcode
 
2228
 
 
2229
    This will set the value of three settings:
 
2230
 
 
2231
    \list
 
2232
    \o \c mainwindow/size
 
2233
    \o \c mainwindow/fullScreen
 
2234
    \o \c outputpanel/visible
 
2235
    \endlist
 
2236
 
 
2237
    Call endGroup() to reset the current group to what it was before
 
2238
    the corresponding beginGroup() call. Groups can be nested.
 
2239
 
 
2240
    \sa endGroup(), group()
 
2241
*/
 
2242
void QSettings::beginGroup(const QString &prefix)
 
2243
{
 
2244
    Q_D(QSettings);
 
2245
    d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix)));
 
2246
}
 
2247
 
 
2248
/*!
 
2249
    Resets the group to what it was before the corresponding
 
2250
    beginGroup() call.
 
2251
 
 
2252
    Example:
 
2253
 
 
2254
    \code
 
2255
        settings.beginGroup("alpha");
 
2256
        // settings.group() == "alpha"
 
2257
 
 
2258
        settings.beginGroup("beta");
 
2259
        // settings.group() == "alpha/beta"
 
2260
 
 
2261
        settings.endGroup();
 
2262
        // settings.group() == "alpha"
 
2263
 
 
2264
        settings.endGroup();
 
2265
        // settings.group() == ""
 
2266
    \endcode
 
2267
 
 
2268
    \sa beginGroup(), group()
 
2269
*/
 
2270
void QSettings::endGroup()
 
2271
{
 
2272
    Q_D(QSettings);
 
2273
    if (d->groupStack.isEmpty()) {
 
2274
        qWarning("QSettings::endGroup: No matching beginGroup()");
 
2275
        return;
 
2276
    }
 
2277
 
 
2278
    QSettingsGroup group = d->groupStack.pop();
 
2279
    int len = group.toString().size();
 
2280
    if (len > 0)
 
2281
        d->groupPrefix.truncate(d->groupPrefix.size() - (len + 1));
 
2282
 
 
2283
    if (group.isArray())
 
2284
        qWarning("QSettings::endGroup: Expected endArray() instead");
 
2285
}
 
2286
 
 
2287
/*!
 
2288
    Returns the current group.
 
2289
 
 
2290
    \sa beginGroup(), endGroup()
 
2291
*/
 
2292
QString QSettings::group() const
 
2293
{
 
2294
    Q_D(const QSettings);
 
2295
    return d->groupPrefix.left(d->groupPrefix.size() - 1);
 
2296
}
 
2297
 
 
2298
/*!
 
2299
    Adds \a prefix to the current group and starts reading from an
 
2300
    array. Returns the size of the array.
 
2301
 
 
2302
    Example:
 
2303
 
 
2304
    \code
 
2305
        struct Login {
 
2306
            QString userName;
 
2307
            QString password;
 
2308
        };
 
2309
        QList<Login> logins;
 
2310
        ...
 
2311
 
 
2312
        QSettings settings;
 
2313
        int size = settings.beginReadArray("logins");
 
2314
        for (int i = 0; i < size; ++i) {
 
2315
            settings.setArrayIndex(i);
 
2316
            Login login;
 
2317
            login.userName = settings.value("userName");
 
2318
            login.password = settings.value("password");
 
2319
            logins.append(login);
 
2320
        }
 
2321
        settings.endArray();
 
2322
    \endcode
 
2323
 
 
2324
    Use beginWriteArray() to write the array in the first place.
 
2325
 
 
2326
    \sa beginWriteArray(), endArray(), setArrayIndex()
 
2327
*/
 
2328
int QSettings::beginReadArray(const QString &prefix)
 
2329
{
 
2330
    Q_D(QSettings);
 
2331
    d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix), false));
 
2332
    return value(QLatin1String("size")).toInt();
 
2333
}
 
2334
 
 
2335
/*!
 
2336
    Adds \a prefix to the current group and starts writing an array
 
2337
    of size \a size. If \a size is -1 (the default), it is automatically
 
2338
    determined based on the indexes of the entries written.
 
2339
 
 
2340
    If you have many occurrences of a certain set of keys, you can
 
2341
    use arrays to make your life easier. For example, let's suppose
 
2342
    that you want to save a variable-length list of user names and
 
2343
    passwords. You could then write:
 
2344
 
 
2345
    \code
 
2346
        struct Login {
 
2347
            QString userName;
 
2348
            QString password;
 
2349
        };
 
2350
        QList<Login> logins;
 
2351
        ...
 
2352
 
 
2353
        QSettings settings;
 
2354
        settings.beginWriteArray("logins");
 
2355
        for (int i = 0; i < logins.size(); ++i) {
 
2356
            settings.setArrayIndex(i);
 
2357
            settings.setValue("userName", list.at(i).userName);
 
2358
            settings.setValue("password", list.at(i).password);
 
2359
        }
 
2360
        settings.endArray();
 
2361
    \endcode
 
2362
 
 
2363
    The generated keys will have the form
 
2364
 
 
2365
    \list
 
2366
    \o \c logins/1/userName
 
2367
    \o \c logins/1/password
 
2368
    \o \c logins/2/userName
 
2369
    \o \c logins/2/password
 
2370
    \o \c logins/3/userName
 
2371
    \o \c logins/3/password
 
2372
    \o ...
 
2373
    \endlist
 
2374
 
 
2375
    To read back an array, use beginReadArray().
 
2376
 
 
2377
    \sa beginReadArray(), endArray(), setArrayIndex()
 
2378
*/
 
2379
void QSettings::beginWriteArray(const QString &prefix, int size)
 
2380
{
 
2381
    Q_D(QSettings);
 
2382
    d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix), size < 0));
 
2383
 
 
2384
    if (size < 0)
 
2385
        remove(QLatin1String("size"));
 
2386
    else
 
2387
        setValue(QLatin1String("size"), size);
 
2388
}
 
2389
 
 
2390
/*!
 
2391
    Closes the array that was started using beginReadArray() or
 
2392
    beginWriteArray().
 
2393
 
 
2394
    \sa beginReadArray(), beginWriteArray()
 
2395
*/
 
2396
void QSettings::endArray()
 
2397
{
 
2398
    Q_D(QSettings);
 
2399
    if (d->groupStack.isEmpty()) {
 
2400
        qWarning("QSettings::endArray: No matching beginArray()");
 
2401
        return;
 
2402
    }
 
2403
 
 
2404
    QSettingsGroup group = d->groupStack.top();
 
2405
    int len = group.toString().size();
 
2406
    d->groupStack.pop();
 
2407
    if (len > 0)
 
2408
        d->groupPrefix.truncate(d->groupPrefix.size() - (len + 1));
 
2409
 
 
2410
    if (group.arraySizeGuess() != -1)
 
2411
        setValue(group.name() + QLatin1String("/size"), group.arraySizeGuess());
 
2412
 
 
2413
    if (!group.isArray())
 
2414
        qWarning("QSettings::endArray: Expected endGroup() instead");
 
2415
}
 
2416
 
 
2417
/*!
 
2418
    Sets the current array index to \a i. Calls to functions such as
 
2419
    setValue(), value(), remove(), and contains() will operate on the
 
2420
    array entry at that index.
 
2421
 
 
2422
    You must call beginReadArray() or beginWriteArray() before you
 
2423
    can call this function.
 
2424
*/
 
2425
void QSettings::setArrayIndex(int i)
 
2426
{
 
2427
    Q_D(QSettings);
 
2428
    if (d->groupStack.isEmpty() || !d->groupStack.top().isArray()) {
 
2429
        qWarning("QSettings::setArrayIndex: Missing beginArray()");
 
2430
        return;
 
2431
    }
 
2432
 
 
2433
    QSettingsGroup &top = d->groupStack.top();
 
2434
    int len = top.toString().size();
 
2435
    top.setArrayIndex(qMax(i, 0));
 
2436
    d->groupPrefix.replace(d->groupPrefix.size() - len - 1, len, top.toString());
 
2437
}
 
2438
 
 
2439
/*!
 
2440
    Returns a list of all keys, including subkeys, that can be read
 
2441
    using the QSettings object.
 
2442
 
 
2443
    Example:
 
2444
 
 
2445
    \code
 
2446
        QSettings settings;
 
2447
        settings.setValue("fridge/color", Qt::white);
 
2448
        settings.setValue("fridge/size", QSize(32, 96));
 
2449
        settings.setValue("sofa", true);
 
2450
        settings.setValue("tv", false);
 
2451
 
 
2452
        QStringList keys = settings.allKeys();
 
2453
        // keys: ["fridge/color", "fridge/size", "sofa", "tv"]
 
2454
    \endcode
 
2455
 
 
2456
    If a group is set using beginGroup(), only the keys in the group
 
2457
    are returned, without the group prefix:
 
2458
 
 
2459
    \code
 
2460
        settings.beginGroup("fridge");
 
2461
        keys = settings.allKeys();
 
2462
        // keys: ["color", "size"]
 
2463
    \endcode
 
2464
 
 
2465
    \sa childGroups(), childKeys()
 
2466
*/
 
2467
QStringList QSettings::allKeys() const
 
2468
{
 
2469
    Q_D(const QSettings);
 
2470
    return d->children(d->groupPrefix, QSettingsPrivate::AllKeys);
 
2471
}
 
2472
 
 
2473
/*!
 
2474
    Returns a list of all top-level keys that can be read using the
 
2475
    QSettings object.
 
2476
 
 
2477
    Example:
 
2478
 
 
2479
    \code
 
2480
        QSettings settings;
 
2481
        settings.setValue("fridge/color", Qt::white);
 
2482
        settings.setValue("fridge/size", QSize(32, 96));
 
2483
        settings.setValue("sofa", true);
 
2484
        settings.setValue("tv", false);
 
2485
 
 
2486
        QStringList keys = settings.childKeys();
 
2487
        // keys: ["sofa", "tv"]
 
2488
    \endcode
 
2489
 
 
2490
    If a group is set using beginGroup(), the top-level keys in that
 
2491
    group are returned, without the group prefix:
 
2492
 
 
2493
    \code
 
2494
        settings.beginGroup("fridge");
 
2495
        keys = settings.childKeys();
 
2496
        // keys: ["color", "size"]
 
2497
    \endcode
 
2498
 
 
2499
    You can navigate through the entire setting hierarchy using
 
2500
    childKeys() and childGroups() recursively.
 
2501
 
 
2502
    \sa childGroups(), allKeys()
 
2503
*/
 
2504
QStringList QSettings::childKeys() const
 
2505
{
 
2506
    Q_D(const QSettings);
 
2507
    return d->children(d->groupPrefix, QSettingsPrivate::ChildKeys);
 
2508
}
 
2509
 
 
2510
/*!
 
2511
    Returns a list of all key top-level groups that contain keys that
 
2512
    can be read using the QSettings object.
 
2513
 
 
2514
    Example:
 
2515
 
 
2516
    \code
 
2517
        QSettings settings;
 
2518
        settings.setValue("fridge/color", Qt::white);
 
2519
        settings.setValue("fridge/size", QSize(32, 96));
 
2520
        settings.setValue("sofa", true);
 
2521
        settings.setValue("tv", false);
 
2522
 
 
2523
        QStringList groups = settings.childGroups();
 
2524
        // group: ["fridge"]
 
2525
    \endcode
 
2526
 
 
2527
    If a group is set using beginGroup(), the first-level keys in
 
2528
    that group are returned, without the group prefix.
 
2529
 
 
2530
    \code
 
2531
        settings.beginGroup("fridge");
 
2532
        groups = settings.childGroups();
 
2533
        // groups: []
 
2534
    \endcode
 
2535
 
 
2536
    You can navigate through the entire setting hierarchy using
 
2537
    childKeys() and childGroups() recursively.
 
2538
 
 
2539
    \sa childKeys(), allKeys()
 
2540
*/
 
2541
QStringList QSettings::childGroups() const
 
2542
{
 
2543
    Q_D(const QSettings);
 
2544
    return d->children(d->groupPrefix, QSettingsPrivate::ChildGroups);
 
2545
}
 
2546
 
 
2547
/*!
 
2548
    Returns true if settings can be written using this QSettings
 
2549
    object; returns false otherwise.
 
2550
 
 
2551
    One reason why isWritable() might return false is if
 
2552
    QSettings operates on a read-only file.
 
2553
 
 
2554
    \sa fileName(), status()
 
2555
*/
 
2556
bool QSettings::isWritable() const
 
2557
{
 
2558
    Q_D(const QSettings);
 
2559
    return d->isWritable();
 
2560
}
 
2561
 
 
2562
/*!
 
2563
    Sets the value of setting \a key to \a value.
 
2564
 
 
2565
    If the key already exists, the previous value is overwritten.
 
2566
 
 
2567
    Example:
 
2568
 
 
2569
    \code
 
2570
        QSettings settings;
 
2571
        settings.setValue("interval", 30);
 
2572
        settings.value("interval").toInt();     // returns 30
 
2573
 
 
2574
        settings.setValue("interval", 6.55);
 
2575
        settings.value("interval").toDouble();  // returns 6.55
 
2576
    \endcode
 
2577
 
 
2578
    \sa value(), remove(), contains()
 
2579
*/
 
2580
void QSettings::setValue(const QString &key, const QVariant &value)
 
2581
{
 
2582
    Q_D(QSettings);
 
2583
    QString k = d->actualKey(key);
 
2584
    d->set(k, value);
 
2585
    d->requestUpdate();
 
2586
}
 
2587
 
 
2588
/*!
 
2589
    Removes the setting \a key and any sub-settings of \a key.
 
2590
 
 
2591
    Example:
 
2592
 
 
2593
    \code
 
2594
        QSettings settings;
 
2595
        settings.setValue("ape");
 
2596
        settings.setValue("monkey", 1);
 
2597
        settings.setValue("monkey/sea", 2);
 
2598
        settings.setValue("monkey/doe", 4);
 
2599
 
 
2600
        settings.remove("monkey");
 
2601
        QStringList keys = settings.allKeys();
 
2602
        // keys: ["ape"]
 
2603
    \endcode
 
2604
 
 
2605
    Be aware that if one of the fallback locations contains a setting
 
2606
    with the same key, that setting will be visible after calling
 
2607
    remove().
 
2608
 
 
2609
    If \a key is an empty string, all keys in the current group() are
 
2610
    removed. For example:
 
2611
 
 
2612
    \code
 
2613
        QSettings settings;
 
2614
        settings.setValue("ape");
 
2615
        settings.setValue("monkey", 1);
 
2616
        settings.setValue("monkey/sea", 2);
 
2617
        settings.setValue("monkey/doe", 4);
 
2618
 
 
2619
        settings.beginGroup("monkey");
 
2620
        settings.remove("");
 
2621
        settings.endGroup();
 
2622
 
 
2623
        QStringList keys = settings.allKeys();
 
2624
        // keys: ["ape"]
 
2625
    \endcode
 
2626
 
 
2627
    \sa setValue(), value(), contains()
 
2628
*/
 
2629
void QSettings::remove(const QString &key)
 
2630
{
 
2631
    Q_D(QSettings);
 
2632
    /*
 
2633
        We cannot use actualKey(), because remove() supports empty
 
2634
        keys. The code is also tricky because of slash handling.
 
2635
    */
 
2636
    QString theKey = d->normalizedKey(key);
 
2637
    if (theKey.isEmpty())
 
2638
        theKey = group();
 
2639
    else
 
2640
        theKey.prepend(d->groupPrefix);
 
2641
 
 
2642
    if (theKey.isEmpty()) {
 
2643
        d->clear();
 
2644
    } else {
 
2645
        d->remove(theKey);
 
2646
    }
 
2647
    d->requestUpdate();
 
2648
}
 
2649
 
 
2650
/*!
 
2651
    Returns true if there exists a setting called \a key; returns
 
2652
    false otherwise.
 
2653
 
 
2654
    If a group is set using beginGroup(), \a key is taken to be
 
2655
    relative to that group.
 
2656
 
 
2657
    \sa value(), setValue()
 
2658
*/
 
2659
bool QSettings::contains(const QString &key) const
 
2660
{
 
2661
    Q_D(const QSettings);
 
2662
    QString k = d->actualKey(key);
 
2663
    return d->get(k, 0);
 
2664
}
 
2665
 
 
2666
/*!
 
2667
    Sets whether fallbacks are enabled to \a b.
 
2668
 
 
2669
    By default, fallbacks are enabled.
 
2670
 
 
2671
    \sa fallbacksEnabled()
 
2672
*/
 
2673
void QSettings::setFallbacksEnabled(bool b)
 
2674
{
 
2675
    Q_D(QSettings);
 
2676
    d->fallbacks = !!b;
 
2677
}
 
2678
 
 
2679
/*!
 
2680
    Returns true if fallbacks are enabled; returns false otherwise.
 
2681
 
 
2682
    By default, fallbacks are enabled.
 
2683
 
 
2684
    \sa setFallbacksEnabled()
 
2685
*/
 
2686
bool QSettings::fallbacksEnabled() const
 
2687
{
 
2688
    Q_D(const QSettings);
 
2689
    return d->fallbacks;
 
2690
}
 
2691
 
 
2692
#ifndef QT_NO_QOBJECT
 
2693
/*!
 
2694
    \reimp
 
2695
*/
 
2696
bool QSettings::event(QEvent *event)
 
2697
{
 
2698
    Q_D(QSettings);
 
2699
    if (event->type() == QEvent::UpdateRequest) {
 
2700
        d->update();
 
2701
        return true;
 
2702
    }
 
2703
    return QObject::event(event);
 
2704
}
 
2705
#endif
 
2706
 
 
2707
/*!
 
2708
    Returns the value for setting \a key. If the setting doesn't
 
2709
    exist, returns \a defaultValue.
 
2710
 
 
2711
    If no default value is specified, a default QVariant is
 
2712
    returned.
 
2713
 
 
2714
    Example:
 
2715
 
 
2716
    \code
 
2717
        QSettings settings;
 
2718
        settings.setValue("animal/snake", 58);
 
2719
        settings.value("animal/snake", 1024).toInt();   // returns 58
 
2720
        settings.value("animal/zebra", 1024).toInt();   // returns 1024
 
2721
        settings.value("animal/zebra").toInt();         // returns 0
 
2722
    \endcode
 
2723
 
 
2724
    \sa setValue(), contains(), remove()
 
2725
*/
 
2726
QVariant QSettings::value(const QString &key, const QVariant &defaultValue) const
 
2727
{
 
2728
    Q_D(const QSettings);
 
2729
    QVariant result = defaultValue;
 
2730
    QString k = d->actualKey(key);
 
2731
    d->get(k, &result);
 
2732
    return result;
 
2733
}
 
2734
 
 
2735
/*!
 
2736
    Sets the directory where QSettings stores its SystemScope \c .ini files to \a dir.
 
2737
 
 
2738
    On Unix systems, the default directory is \c /etc/xdg in accordance with FreeDesktop's
 
2739
    XDG Base Directory Specification. This default can be changed when compiling Qt by passing
 
2740
    the \c --sysconfdir flag to \c configure.
 
2741
 
 
2742
    On Windows, the default directory is \c{C:\Documents and Settings\All Users\Application Data}.
 
2743
 
 
2744
    A call to this function should precede any instantiations of QSettings objects.
 
2745
 
 
2746
    \sa setUserIniPath()
 
2747
*/
 
2748
void QSettings::setSystemIniPath(const QString &dir)
 
2749
{
 
2750
    *defaultSystemIniPath() = dir;
 
2751
}
 
2752
 
 
2753
/*!
 
2754
    Sets the directory where QSettings stores its UserScope \c .ini files to \a dir.
 
2755
 
 
2756
    On Unix systems, the default directory is read from the \c $XDG_CONFIG_HOME environment
 
2757
    variable. If this variable is empty or unset, \c $HOME/.config is used, in accordance with
 
2758
    the FreeDesktop's XDG Base Directory Specification. Calling this function overrides the
 
2759
    path specified in \c $XDG_CONFIG_HOME.
 
2760
 
 
2761
    On Windows, the default directory is \c{C:\Documents and Settings\<username>\Application Data}.
 
2762
 
 
2763
    A call to this function should precede any instantiations of QSettings objects.
 
2764
 
 
2765
    \sa setSystemIniPath()
 
2766
*/
 
2767
 
 
2768
void QSettings::setUserIniPath(const QString &dir)
 
2769
{
 
2770
    *defaultUserIniPath() = dir;
 
2771
}
 
2772
 
 
2773
#ifdef QT3_SUPPORT
 
2774
/*! \fn bool QSettings::writeEntry(const QString &key, bool value)
 
2775
 
 
2776
    Sets the value of setting \a key to \a value.
 
2777
 
 
2778
    Use setValue() instead.
 
2779
*/
 
2780
 
 
2781
/*! \fn bool QSettings::writeEntry(const QString &key, double value)
 
2782
 
 
2783
    \overload
 
2784
*/
 
2785
 
 
2786
/*! \fn bool QSettings::writeEntry(const QString &key, int value)
 
2787
 
 
2788
    \overload
 
2789
*/
 
2790
 
 
2791
/*! \fn bool QSettings::writeEntry(const QString &key, const char *value)
 
2792
 
 
2793
    \overload
 
2794
*/
 
2795
 
 
2796
/*! \fn bool QSettings::writeEntry(const QString &key, const QString &value)
 
2797
 
 
2798
    \overload
 
2799
*/
 
2800
 
 
2801
/*! \fn bool QSettings::writeEntry(const QString &key, const QStringList &value)
 
2802
 
 
2803
    \overload
 
2804
*/
 
2805
 
 
2806
/*! \fn bool QSettings::writeEntry(const QString &key, const QStringList &value, QChar separator)
 
2807
 
 
2808
    \overload
 
2809
 
 
2810
    Use setValue(\a key, \a value) instead. You don't need \a separator.
 
2811
*/
 
2812
 
 
2813
/*! \fn QStringList QSettings::readListEntry(const QString &key, bool *ok = 0)
 
2814
 
 
2815
    Returns the value of setting \a key converted to a QStringList.
 
2816
 
 
2817
    If \a ok is not 0, *\a{ok} is set to true if the key exists,
 
2818
    otherwise *\a{ok} is set to false.
 
2819
 
 
2820
    Use value() instead.
 
2821
 
 
2822
    \oldcode
 
2823
        bool ok;
 
2824
        QStringList list = settings.readListEntry("recentFiles", &ok);
 
2825
    \newcode
 
2826
        bool ok = settings.contains("recentFiles");
 
2827
        QStringList list = settings.value("recentFiles").toStringList();
 
2828
    \endcode
 
2829
*/
 
2830
 
 
2831
/*! \fn QStringList QSettings::readListEntry(const QString &key, QChar separator, bool *ok)
 
2832
 
 
2833
    Returns the value of setting \a key converted to a QStringList.
 
2834
    \a separator is ignored.
 
2835
 
 
2836
    If \a ok is not 0, *\a{ok} is set to true if the key exists,
 
2837
    otherwise *\a{ok} is set to false.
 
2838
 
 
2839
    Use value() instead.
 
2840
 
 
2841
    \oldcode
 
2842
        bool ok;
 
2843
        QStringList list = settings.readListEntry("recentFiles", ":", &ok);
 
2844
    \newcode
 
2845
        bool ok = settings.contains("recentFiles");
 
2846
        QStringList list = settings.value("recentFiles").toStringList();
 
2847
    \endcode
 
2848
*/
 
2849
 
 
2850
/*! \fn QString QSettings::readEntry(const QString &key, const QString &defaultValue, bool *ok)
 
2851
 
 
2852
    Returns the value for setting \a key converted to a QString. If
 
2853
    the setting doesn't exist, returns \a defaultValue.
 
2854
 
 
2855
    If \a ok is not 0, *\a{ok} is set to true if the key exists,
 
2856
    otherwise *\a{ok} is set to false.
 
2857
 
 
2858
    Use value() instead.
 
2859
 
 
2860
    \oldcode
 
2861
        bool ok;
 
2862
        QString str = settings.readEntry("userName", "administrator", &ok);
 
2863
    \newcode
 
2864
        bool ok = settings.contains("userName");
 
2865
        QString str = settings.value("userName", "administrator").toString();
 
2866
    \endcode
 
2867
*/
 
2868
 
 
2869
/*! \fn int QSettings::readNumEntry(const QString &key, int defaultValue, bool *ok)
 
2870
 
 
2871
    Returns the value for setting \a key converted to an \c int. If
 
2872
    the setting doesn't exist, returns \a defaultValue.
 
2873
 
 
2874
    If \a ok is not 0, *\a{ok} is set to true if the key exists,
 
2875
    otherwise *\a{ok} is set to false.
 
2876
 
 
2877
    Use value() instead.
 
2878
 
 
2879
    \oldcode
 
2880
        bool ok;
 
2881
        int max = settings.readNumEntry("maxConnections", 30, &ok);
 
2882
    \newcode
 
2883
        bool ok = settings.contains("maxConnections");
 
2884
        int max = settings.value("maxConnections", 30).toInt();
 
2885
    \endcode
 
2886
*/
 
2887
 
 
2888
/*! \fn double QSettings::readDoubleEntry(const QString &key, double defaultValue, bool *ok)
 
2889
 
 
2890
    Returns the value for setting \a key converted to a \c double. If
 
2891
    the setting doesn't exist, returns \a defaultValue.
 
2892
 
 
2893
    If \a ok is not 0, *\a{ok} is set to true if the key exists,
 
2894
    otherwise *\a{ok} is set to false.
 
2895
 
 
2896
    Use value() instead.
 
2897
 
 
2898
    \oldcode
 
2899
        bool ok;
 
2900
        double pi = settings.readDoubleEntry("pi", 3.141592, &ok);
 
2901
    \newcode
 
2902
        bool ok = settings.contains("pi");
 
2903
        double pi = settings.value("pi", 3.141592).toDouble();
 
2904
    \endcode
 
2905
*/
 
2906
 
 
2907
/*! \fn bool QSettings::readBoolEntry(const QString &key, bool defaultValue, bool *ok)
 
2908
 
 
2909
    Returns the value for setting \a key converted to a \c bool. If
 
2910
    the setting doesn't exist, returns \a defaultValue.
 
2911
 
 
2912
    If \a ok is not 0, *\a{ok} is set to true if the key exists,
 
2913
    otherwise *\a{ok} is set to false.
 
2914
 
 
2915
    Use value() instead.
 
2916
 
 
2917
    \oldcode
 
2918
        bool ok;
 
2919
        bool grid = settings.readBoolEntry("showGrid", true, &ok);
 
2920
    \newcode
 
2921
        bool ok = settings.contains("showGrid");
 
2922
        bool grid = settings.value("showGrid", true).toBool();
 
2923
    \endcode
 
2924
*/
 
2925
 
 
2926
/*! \fn bool QSettings::removeEntry(const QString &key)
 
2927
 
 
2928
    Use remove() instead.
 
2929
*/
 
2930
 
 
2931
/*! \enum QSettings::System
 
2932
    \compat
 
2933
 
 
2934
    \value Unix Unix/X11 systems
 
2935
    \value Windows Microsoft Windows systems
 
2936
    \value Mac Mac OS X systems
 
2937
 
 
2938
    \sa insertSearchPath(), removeSearchPath()
 
2939
*/
 
2940
 
 
2941
/*! \fn void QSettings::insertSearchPath(System system, const QString &path)
 
2942
 
 
2943
    This function is implemented as a no-op. It is provided for
 
2944
    source compatibility with Qt 3. The new QSettings class has no
 
2945
    concept of "search path".
 
2946
*/
 
2947
 
 
2948
/*! \fn void QSettings::removeSearchPath(System system, const QString &path)
 
2949
 
 
2950
    This function is implemented as a no-op. It is provided for
 
2951
    source compatibility with Qt 3. The new QSettings class has no
 
2952
    concept of "search path".
 
2953
*/
 
2954
 
 
2955
/*! \fn void QSettings::setPath(const QString &organization, const QString &application, \
 
2956
                                Scope scope)
 
2957
 
 
2958
    Specifies the \a organization, \a application, and \a scope to
 
2959
    use by the QSettings object.
 
2960
 
 
2961
    Use the appropriate constructor instead, with QSettings::UserScope
 
2962
    instead of QSettings::User and QSettings::SystemScope instead of
 
2963
    QSettings::Global.
 
2964
 
 
2965
    \oldcode
 
2966
        QSettings settings;
 
2967
        settings.setPath("twikimaster.com", "Kanooth", QSettings::Global);
 
2968
    \newcode
 
2969
        QSettings settings(QSettings::SystemScope, "twikimaster.com", "Kanooth");
 
2970
    \endcode
 
2971
*/
 
2972
 
 
2973
/*! \fn void QSettings::resetGroup()
 
2974
 
 
2975
    Sets the current group to be the empty string.
 
2976
 
 
2977
    Use endGroup() instead (possibly multiple times).
 
2978
 
 
2979
    \oldcode
 
2980
        QSettings settings;
 
2981
        settings.beginGroup("mainWindow");
 
2982
        settings.beginGroup("leftPanel");
 
2983
        ...
 
2984
        settings.resetGroup();
 
2985
    \newcode
 
2986
        QSettings settings;
 
2987
        settings.beginGroup("mainWindow");
 
2988
        settings.beginGroup("leftPanel");
 
2989
        ...
 
2990
        settings.endGroup();
 
2991
        settings.endGroup();
 
2992
    \endcode
 
2993
*/
 
2994
 
 
2995
/*! \fn QStringList QSettings::entryList(const QString &key) const
 
2996
 
 
2997
    Returns a list of all sub-keys of \a key.
 
2998
 
 
2999
    Use childKeys() instead.
 
3000
 
 
3001
    \oldcode
 
3002
        QSettings settings;
 
3003
        QStringList keys = settings.entryList("cities");
 
3004
        ...
 
3005
    \newcode
 
3006
        QSettings settings;
 
3007
        settings.beginGroup("cities");
 
3008
        QStringList keys = settings.childKeys();
 
3009
        ...
 
3010
        settings.endGroup();
 
3011
    \endcode
 
3012
*/
 
3013
 
 
3014
/*! \fn QStringList QSettings::subkeyList(const QString &key) const
 
3015
 
 
3016
    Returns a list of all sub-keys of \a key.
 
3017
 
 
3018
    Use childGroups() instead.
 
3019
 
 
3020
    \oldcode
 
3021
        QSettings settings;
 
3022
        QStringList groups = settings.entryList("cities");
 
3023
        ...
 
3024
    \newcode
 
3025
        QSettings settings;
 
3026
        settings.beginGroup("cities");
 
3027
        QStringList groups = settings.childKeys();
 
3028
        ...
 
3029
        settings.endGroup();
 
3030
    \endcode
 
3031
*/
 
3032
#endif
 
3033
 
 
3034
#endif // QT_NO_SETTINGS