qsettings.cpp

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

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9