summaryrefslogtreecommitdiff
path: root/qmake/tools/qsettings.cpp
Unidiff
Diffstat (limited to 'qmake/tools/qsettings.cpp') (more/less context) (show whitespace changes)
-rw-r--r--qmake/tools/qsettings.cpp321
1 files changed, 213 insertions, 108 deletions
diff --git a/qmake/tools/qsettings.cpp b/qmake/tools/qsettings.cpp
index 5de105c..35fc039 100644
--- a/qmake/tools/qsettings.cpp
+++ b/qmake/tools/qsettings.cpp
@@ -1,30 +1,30 @@
1/**************************************************************************** 1/****************************************************************************
2** $Id$ 2** $Id$
3** 3**
4** Implementation of QSettings class 4** Implementation of QSettings class
5** 5**
6** Created: 2000.06.26 6** Created : 000626
7** 7**
8** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 8** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
9** 9**
10** This file is part of the tools module of the Qt GUI Toolkit. 10** This file is part of the tools module of the Qt GUI Toolkit.
11** 11**
12** This file may be distributed under the terms of the Q Public License 12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file 13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file. 14** LICENSE.QPL included in the packaging of this file.
15** 15**
16** This file may be distributed and/or modified under the terms of the 16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software 17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the 18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file. 19** packaging of this file.
20** 20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition 21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License 22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software. 23** Agreement provided with the Software.
24** 24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27** 27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for 28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements. 29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information. 30** See http://www.trolltech.com/qpl/ for QPL licensing information.
@@ -50,130 +50,159 @@ static inline int qt_open( const char *pathname, int flags, mode_t mode )
50#endif 50#endif
51 51
52#include "qsettings.h" 52#include "qsettings.h"
53 53
54#ifndef QT_NO_SETTINGS 54#ifndef QT_NO_SETTINGS
55 55
56#include "qdir.h" 56#include "qdir.h"
57#include "qfile.h" 57#include "qfile.h"
58#include "qfileinfo.h" 58#include "qfileinfo.h"
59#include "qmap.h" 59#include "qmap.h"
60#include "qtextstream.h" 60#include "qtextstream.h"
61#include "qregexp.h" 61#include "qregexp.h"
62#include <private/qsettings_p.h> 62#include <private/qsettings_p.h>
63#include <errno.h> 63#include <errno.h>
64 64
65/*! 65/*!
66 \class QSettings 66 \class QSettings
67 \brief The QSettings class provides persistent platform-independent application settings. 67 \brief The QSettings class provides persistent platform-independent application settings.
68 68
69 \ingroup io 69 \ingroup io
70 \ingroup misc 70 \ingroup misc
71 \mainclass 71 \mainclass
72 72
73 On Unix systems, QSettings uses text files to store settings. On Windows 73 On Unix systems, QSettings uses text files to store settings. On Windows
74 systems, QSettings uses the system registry. On Mac OS X, QSettings will 74 systems, QSettings uses the system registry. On Mac OS X, QSettings uses
75 behave as on Unix, and store to text files. 75 the Carbon preferences API.
76 76
77 Each setting comprises an identifying key and the data associated with 77 Each setting comprises an identifying key and the data associated with
78 the key. A key is a unicode string which consists of \e two or more 78 the key. A key is a unicode string which consists of \e two or more
79 subkeys. A subkey is a slash, '/', followed by one or more unicode 79 subkeys. A subkey is a slash, '/', followed by one or more unicode
80 characters (excluding slashes, newlines, carriage returns and equals, 80 characters (excluding slashes, newlines, carriage returns and equals,
81 '=', signs). The associated data, called the entry or value, may be a 81 '=', signs). The associated data, called the entry or value, may be a
82 boolean, an integer, a double, a string or a list of strings. Entry 82 boolean, an integer, a double, a string or a list of strings. Entry
83 strings may contain any unicode characters. 83 strings may contain any unicode characters.
84 84
85 If you want to save and restore the entire desktop's settings, i.e. 85 If you want to save and restore the entire desktop's settings, i.e.
86 which applications are running, use QSettings to save the settings 86 which applications are running, use QSettings to save the settings
87 for each individual application and QSessionManager to save the 87 for each individual application and QSessionManager to save the
88 desktop's session. 88 desktop's session.
89 89
90 Example settings: 90 Example settings:
91 \code 91 \code
92 /MyCompany/MyApplication/background color 92 /MyCompany/MyApplication/background color
93 /MyCompany/MyApplication/foreground color 93 /MyCompany/MyApplication/foreground color
94 /MyCompany/MyApplication/geometry/x 94 /MyCompany/MyApplication/geometry/x
95 /MyCompany/MyApplication/geometry/y 95 /MyCompany/MyApplication/geometry/y
96 /MyCompany/MyApplication/geometry/width 96 /MyCompany/MyApplication/geometry/width
97 /MyCompany/MyApplication/geometry/height 97 /MyCompany/MyApplication/geometry/height
98 /MyCompany/MyApplication/recent files/1 98 /MyCompany/MyApplication/recent files/1
99 /MyCompany/MyApplication/recent files/2 99 /MyCompany/MyApplication/recent files/2
100 /MyCompany/MyApplication/recent files/3 100 /MyCompany/MyApplication/recent files/3
101 \endcode 101 \endcode
102 Each line above is a complete key, made up of subkeys. 102 Each line above is a complete key, made up of subkeys.
103 103
104 A typical usage pattern for application startup: 104 A typical usage pattern for reading application startup:
105 \code 105 \code
106 QSettings settings; 106 QSettings settings;
107 settings.insertSearchPath( QSettings::Windows, "/MyCompany" ); 107 settings.setPath( "MyCompany.com", "MyApplication" );
108 // No search path needed for Unix; see notes further on. 108
109 // Use default values if the keys don't exist 109 QString bgColor = settings.readEntry( "/colors/background", "white" );
110 QString bgColor = settings.readEntry( "/MyApplication/background color", "white" ); 110 int width = settings.readNumEntry( "/geometry/width", 640 );
111 int width = settings.readNumEntry( "/MyApplication/geometry/width", 640 );
112 // ... 111 // ...
113 \endcode 112 \endcode
114 113
115 A typical usage pattern for application exit or 'save preferences': 114 A typical usage pattern for application exit or 'save preferences':
116 \code 115 \code
117 QSettings settings; 116 QSettings settings;
118 settings.insertSearchPath( QSettings::Windows, "/MyCompany" ); 117 settings.setPath( "MyCompany.com", "MyApplication" );
119 // No search path needed for Unix; see notes further on. 118
120 settings.writeEntry( "/MyApplication/background color", bgColor ); 119 settings.writeEntry( "/colors/background", bgColor );
121 settings.writeEntry( "/MyApplication/geometry/width", width ); 120 settings.writeEntry( "/geometry/width", width );
121 // ...
122 \endcode
123
124 QSettings can build a key prefix that is prepended to all keys. To
125 build the key prefix, use beginGroup() and endGroup().
126 \code
127 QSettings settings;
128
129 settings.beginGroup( "/MainWindow" );
130 settings.beginGroup( "/Geometry" );
131 int x = settings.readEntry( "/x" );
132 // ...
133 settings.endGroup();
134 settings.beginGroup( "/Toolbars" );
122 // ... 135 // ...
136 settings.endGroup();
137 settings.endGroup();
123 \endcode 138 \endcode
124 139
125 You can get a list of entry-holding keys by calling entryList(), and 140 You can get a list of entry-holding keys by calling entryList(), and
126 a list of key-holding keys using subkeyList(). 141 a list of key-holding keys using subkeyList().
127 142
128 \code 143 \code
129 QStringList keys = entryList( "/MyApplication" ); 144 QStringList keys = entryList( "/MyApplication" );
130 // keys contains 'background color' and 'foreground color'. 145 // keys contains 'background color' and 'foreground color'.
131 146
132 QStringList keys = entryList( "/MyApplication/recent files" ); 147 QStringList keys = entryList( "/MyApplication/recent files" );
133 // keys contains '1', '2' and '3'. 148 // keys contains '1', '2' and '3'.
134 149
135 QStringList subkeys = subkeyList( "/MyApplication" ); 150 QStringList subkeys = subkeyList( "/MyApplication" );
136 // subkeys contains 'geometry' and 'recent files' 151 // subkeys contains 'geometry' and 'recent files'
137 152
138 QStringList subkeys = subkeyList( "/MyApplication/recent files" ); 153 QStringList subkeys = subkeyList( "/MyApplication/recent files" );
139 // subkeys is empty. 154 // subkeys is empty.
140 \endcode 155 \endcode
141 156
142 If you wish to use a different search path call insertSearchPath()
143 as often as necessary to add your preferred paths. Call
144 removeSearchPath() to remove any unwanted paths.
145
146 Since settings for Windows are stored in the registry there are size 157 Since settings for Windows are stored in the registry there are size
147 limits as follows: 158 limits as follows:
148 \list 159 \list
149 \i A subkey may not exceed 255 characters. 160 \i A subkey may not exceed 255 characters.
150 \i An entry's value may not exceed 16,300 characters. 161 \i An entry's value may not exceed 16,300 characters.
151 \i All the values of a key (for example, all the 'recent files' 162 \i All the values of a key (for example, all the 'recent files'
152 subkeys values), may not exceed 65,535 characters. 163 subkeys values), may not exceed 65,535 characters.
153 \endlist 164 \endlist
154 165
155 These limitations are not enforced on Unix. 166 These limitations are not enforced on Unix or Mac OS X.
167
168 If you wish to use a different search path call insertSearchPath()
169 as often as necessary to add your preferred paths. Call
170 removeSearchPath() to remove any unwanted paths.
171
172 \section1 Notes for Mac OS X Applications
173
174 Internal to the CFPreferences API it is not defined (for Mac OS 9
175 support) where the settings will ultimitely be stored. However, at the
176 time of this writing the settings will be stored (either on a global or
177 user basis, preferring locally) into a plist file in
178 $ROOT/System/Library/Preferences (in XML format). QSettings will create
179 an appropriate plist file (com.<first group name>.plist) out of the
180 full path to a key.
181
182 For further information on CFPreferences see also
183 \link http://developer.apple.com/techpubs/macosx/CoreFoundation/PreferenceServices/preferenceservices_carbon.html
184 Apple's Specifications\endlink
156 185
157 \section1 Notes for Unix Applications 186 \section1 Notes for Unix Applications
158 187
159 There is no universally accepted place for storing application 188 There is no universally accepted place for storing application
160 settings under Unix. In the examples the settings file will be 189 settings under Unix. In the examples the settings file will be
161 searched for in the following directories: 190 searched for in the following directories:
162 \list 1 191 \list 1
163 \i INSTALL/etc/settings 192 \i INSTALL/etc/settings
164 \i /opt/MyCompany/share/etc 193 \i /opt/MyCompany/share/etc
165 \i /opt/MyCompany/share/MyApplication/etc 194 \i /opt/MyCompany/share/MyApplication/etc
166 \i $HOME/.qt 195 \i $HOME/.qt
167 \endlist 196 \endlist
168 When reading settings the files are searched in the order shown 197 When reading settings the files are searched in the order shown
169 above, with later settings overriding earlier settings. Files for 198 above, with later settings overriding earlier settings. Files for
170 which the user doesn't have read permission are ignored. When saving 199 which the user doesn't have read permission are ignored. When saving
171 settings QSettings works in the order shown above, writing 200 settings QSettings works in the order shown above, writing
172 to the first settings file for which the user has write permission. 201 to the first settings file for which the user has write permission.
173 (\c INSTALL is the directory where Qt was installed. This can be 202 (\c INSTALL is the directory where Qt was installed. This can be
174 modified by using the configure script's -prefix argument ) 203 modified by using the configure script's -prefix argument )
175 204
176 If you want to put the settings in a particular place in the 205 If you want to put the settings in a particular place in the
177 filesystem you could do this: 206 filesystem you could do this:
178 \code 207 \code
179 settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share" ); 208 settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share" );
@@ -279,62 +308,62 @@ static void closelock( HANDLE fd )
279 // ignore the return value, so that the unlock fails silently 308 // ignore the return value, so that the unlock fails silently
280 (void) fcntl( fd, F_SETLKW, &fl ); 309 (void) fcntl( fd, F_SETLKW, &fl );
281 310
282 close( fd ); 311 close( fd );
283} 312}
284#elif defined(Q_WS_WIN) 313#elif defined(Q_WS_WIN)
285#define Q_LOCKREAD 1 314#define Q_LOCKREAD 1
286#define Q_LOCKWRITE 2 315#define Q_LOCKWRITE 2
287 316
288static HANDLE openlock( const QString &name, int /*type*/ ) 317static HANDLE openlock( const QString &name, int /*type*/ )
289{ 318{
290 if ( !QFile::exists( name ) ) 319 if ( !QFile::exists( name ) )
291 return 0; 320 return 0;
292 321
293 return 0; 322 return 0;
294 323
295 HANDLE fd = 0; 324 HANDLE fd = 0;
296 325
297 QT_WA( { 326 QT_WA( {
298 fd = CreateFileW( (TCHAR*)name.ucs2(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); 327 fd = CreateFileW( (TCHAR*)name.ucs2(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
299 } , { 328 } , {
300 fd = CreateFileA( name.local8Bit(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); 329 fd = CreateFileA( name.local8Bit(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
301 } ); 330 } );
302 331
303 if ( !LockFile( fd, 0, 0, -1, -1 ) ) { 332 if ( !LockFile( fd, 0, 0, (DWORD)-1, (DWORD)-1 ) ) { // ### (DWORD)-1 ???
304#ifdef QT_CHECK_STATE 333#ifdef QT_CHECK_STATE
305 qWarning( "QSettings: openlock failed!" ); 334 qWarning( "QSettings: openlock failed!" );
306#endif 335#endif
307 } 336 }
308 return fd; 337 return fd;
309} 338}
310 339
311void closelock( HANDLE fd ) 340static void closelock( HANDLE fd )
312{ 341{
313 if ( !fd ) 342 if ( !fd )
314 return; 343 return;
315 344
316 if ( !UnlockFile( fd, 0, 0, -1, -1 ) ) { 345 if ( !UnlockFile( fd, 0, 0, (DWORD)-1, (DWORD)-1 ) ) { // ### (DWORD)-1 ???
317#ifdef QT_CHECK_STATE 346#ifdef QT_CHECK_STATE
318 qWarning( "QSettings: closelock failed!"); 347 qWarning( "QSettings: closelock failed!");
319#endif 348#endif
320 } 349 }
321 CloseHandle( fd ); 350 CloseHandle( fd );
322} 351}
323#endif 352#endif
324 353
325 354
326QSettingsGroup::QSettingsGroup() 355QSettingsGroup::QSettingsGroup()
327 : modified(FALSE) 356 : modified(FALSE)
328{ 357{
329} 358}
330 359
331 360
332 361
333 362
334void QSettingsHeading::read(const QString &filename) 363void QSettingsHeading::read(const QString &filename)
335{ 364{
336 if (! QFileInfo(filename).exists()) 365 if (! QFileInfo(filename).exists())
337 return; 366 return;
338 367
339 HANDLE lockfd = openlock( filename, Q_LOCKREAD ); 368 HANDLE lockfd = openlock( filename, Q_LOCKREAD );
340 369
@@ -434,157 +463,165 @@ void QSettingsHeading::parseLine(QTextStream &stream)
434 } 463 }
435 } 464 }
436 465
437 (*git).insert(key, value); 466 (*git).insert(key, value);
438 } 467 }
439 } 468 }
440} 469}
441 470
442#ifdef Q_WS_WIN // for homedirpath reading from registry 471#ifdef Q_WS_WIN // for homedirpath reading from registry
443#include "qt_windows.h" 472#include "qt_windows.h"
444#include "qlibrary.h" 473#include "qlibrary.h"
445 474
446#ifndef CSIDL_APPDATA 475#ifndef CSIDL_APPDATA
447#define CSIDL_APPDATA 0x001a // <user name>\Application Data 476#define CSIDL_APPDATA 0x001a // <user name>\Application Data
448#endif 477#endif
449#ifndef CSIDL_COMMON_APPDATA 478#ifndef CSIDL_COMMON_APPDATA
450#define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data 479#define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data
451#endif 480#endif
452 481
453#endif 482#endif
454 483
455QSettingsPrivate::QSettingsPrivate( QSettings::Format format ) 484QSettingsPrivate::QSettingsPrivate( QSettings::Format format )
456 : groupDirty( TRUE ), modified(FALSE), globalScope(TRUE) 485 : groupDirty( TRUE ), modified(FALSE), globalScope(TRUE)
457{ 486{
458#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 487#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
459 if ( format != QSettings::Ini ) 488 if ( format != QSettings::Ini )
460 return; 489 return;
490#else
491 Q_UNUSED( format );
461#endif 492#endif
462 493
463 QString appSettings(QDir::homeDirPath() + "/.qt/"); 494 QString appSettings(QDir::homeDirPath() + "/.qt/");
464 QString defPath; 495 QString defPath;
465#ifdef Q_WS_WIN 496#ifdef Q_WS_WIN
466#ifdef Q_OS_TEMP 497#ifdef Q_OS_TEMP
467 TCHAR path[MAX_PATH]; 498 TCHAR path[MAX_PATH];
468 SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); 499 SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE );
469 appSettings = QString::fromUcs2( path ); 500 appSettings = QString::fromUcs2( path );
470 SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); 501 SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE );
471 defPath = QString::fromUcs2( path ); 502 defPath = QString::fromUcs2( path );
472#else 503#else
473 QLibrary library( "shell32" ); 504 QLibrary library( "shell32" );
474 library.setAutoUnload( FALSE ); 505 library.setAutoUnload( FALSE );
475 QT_WA( { 506 QT_WA( {
476 typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL); 507 typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL);
477 GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathW" ); 508 GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathW" );
478 if ( SHGetSpecialFolderPath ) { 509 if ( SHGetSpecialFolderPath ) {
479 TCHAR path[MAX_PATH]; 510 TCHAR path[MAX_PATH];
480 SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); 511 SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE );
481 appSettings = QString::fromUcs2( (ushort*)path ); 512 appSettings = QString::fromUcs2( (ushort*)path );
482 SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); 513 SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE );
483 defPath = QString::fromUcs2( (ushort*)path ); 514 defPath = QString::fromUcs2( (ushort*)path );
484 } 515 }
485 } , { 516 } , {
486 typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL); 517 typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL);
487 GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathA" ); 518 GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathA" );
488 if ( SHGetSpecialFolderPath ) { 519 if ( SHGetSpecialFolderPath ) {
489 char path[MAX_PATH]; 520 char path[MAX_PATH];
490 SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); 521 SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE );
491 appSettings = QString::fromLocal8Bit( path ); 522 appSettings = QString::fromLocal8Bit( path );
492 SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); 523 SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE );
493 defPath = QString::fromLocal8Bit( path ); 524 defPath = QString::fromLocal8Bit( path );
494 } 525 }
495 } ); 526 } );
496#endif // Q_OS_TEMP 527#endif // Q_OS_TEMP
497#else 528#else
498// for now 529// for now
499#define QSETTINGS_DEFAULT_PATH_SUFFIX "/etc/settings" 530#define QSETTINGS_DEFAULT_PATH_SUFFIX "/etc/settings"
500 531
501 defPath = qInstallPath(); 532 defPath = qInstallPath();
502 defPath += QSETTINGS_DEFAULT_PATH_SUFFIX; 533 defPath += QSETTINGS_DEFAULT_PATH_SUFFIX;
503#endif 534#endif
504 QDir dir(appSettings); 535 QDir dir(appSettings);
505 if (! dir.exists()) { 536 if (! dir.exists()) {
506 if (! dir.mkdir(dir.path())) 537 if (! dir.mkdir(dir.path()))
507#if defined(QT_CHECK_STATE) 538#if defined(QT_CHECK_STATE)
508 qWarning("QSettings: error creating %s", dir.path().latin1()); 539 qWarning("QSettings: error creating %s", dir.path().latin1());
540#else
541 ;
509#endif 542#endif
510 } 543 }
511 544
512 if ( !!defPath ) 545 if ( !!defPath )
513 searchPaths.append(defPath); 546 searchPaths.append(defPath);
514 searchPaths.append(dir.path()); 547 searchPaths.append(dir.path());
515} 548}
516 549
517QSettingsPrivate::~QSettingsPrivate() 550QSettingsPrivate::~QSettingsPrivate()
518{ 551{
519} 552}
520 553
521QSettingsGroup QSettingsPrivate::readGroup() 554QSettingsGroup QSettingsPrivate::readGroup()
522{ 555{
523 QSettingsHeading hd; 556 QSettingsHeading hd;
524 QSettingsGroup grp; 557 QSettingsGroup grp;
525 558
526 QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); 559 QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading);
527 if (headingsit != headings.end()) 560 if (headingsit != headings.end())
528 hd = *headingsit; 561 hd = *headingsit;
529 562
530 QSettingsHeading::Iterator grpit = hd.find(group); 563 QSettingsHeading::Iterator grpit = hd.find(group);
531 if (grpit == hd.end()) { 564 if (grpit == hd.end()) {
532 QStringList::Iterator it = searchPaths.begin(); 565 QStringList::Iterator it = searchPaths.begin();
566 if ( !globalScope )
567 ++it;
533 while (it != searchPaths.end()) { 568 while (it != searchPaths.end()) {
534 QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); 569 QString filebase = heading.lower().replace(QRegExp("\\s+"), "_");
535 QString fn((*it++) + "/" + filebase + "rc"); 570 QString fn((*it++) + "/" + filebase + "rc");
536 if (! hd.contains(fn + "cached")) { 571 if (! hd.contains(fn + "cached")) {
537 hd.read(fn); 572 hd.read(fn);
538 hd.insert(fn + "cached", QSettingsGroup()); 573 hd.insert(fn + "cached", QSettingsGroup());
539 } 574 }
540 } 575 }
541 576
542 headings.replace(heading, hd); 577 headings.replace(heading, hd);
543 578
544 grpit = hd.find(group); 579 grpit = hd.find(group);
545 if (grpit != hd.end()) 580 if (grpit != hd.end())
546 grp = *grpit; 581 grp = *grpit;
547 } else if (hd.count() != 0) 582 } else if (hd.count() != 0)
548 grp = *grpit; 583 grp = *grpit;
549 584
550 return grp; 585 return grp;
551} 586}
552 587
553 588
554void QSettingsPrivate::removeGroup(const QString &key) 589void QSettingsPrivate::removeGroup(const QString &key)
555{ 590{
556 QSettingsHeading hd; 591 QSettingsHeading hd;
557 QSettingsGroup grp; 592 QSettingsGroup grp;
558 bool found = FALSE; 593 bool found = FALSE;
559 594
560 QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); 595 QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading);
561 if (headingsit != headings.end()) 596 if (headingsit != headings.end())
562 hd = *headingsit; 597 hd = *headingsit;
563 598
564 QSettingsHeading::Iterator grpit = hd.find(group); 599 QSettingsHeading::Iterator grpit = hd.find(group);
565 if (grpit == hd.end()) { 600 if (grpit == hd.end()) {
566 QStringList::Iterator it = searchPaths.begin(); 601 QStringList::Iterator it = searchPaths.begin();
602 if ( !globalScope )
603 ++it;
567 while (it != searchPaths.end()) { 604 while (it != searchPaths.end()) {
568 QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); 605 QString filebase = heading.lower().replace(QRegExp("\\s+"), "_");
569 QString fn((*it++) + "/" + filebase + "rc"); 606 QString fn((*it++) + "/" + filebase + "rc");
570 if (! hd.contains(fn + "cached")) { 607 if (! hd.contains(fn + "cached")) {
571 hd.read(fn); 608 hd.read(fn);
572 hd.insert(fn + "cached", QSettingsGroup()); 609 hd.insert(fn + "cached", QSettingsGroup());
573 } 610 }
574 } 611 }
575 612
576 headings.replace(heading, hd); 613 headings.replace(heading, hd);
577 614
578 grpit = hd.find(group); 615 grpit = hd.find(group);
579 if (grpit != hd.end()) { 616 if (grpit != hd.end()) {
580 found = TRUE; 617 found = TRUE;
581 grp = *grpit; 618 grp = *grpit;
582 } 619 }
583 } else if (hd.count() != 0) { 620 } else if (hd.count() != 0) {
584 found = TRUE; 621 found = TRUE;
585 grp = *grpit; 622 grp = *grpit;
586 } 623 }
587 624
588 if (found) { 625 if (found) {
589 grp.remove(key); 626 grp.remove(key);
590 627
@@ -594,102 +631,112 @@ void QSettingsPrivate::removeGroup(const QString &key)
594 hd.remove(group); 631 hd.remove(group);
595 632
596 if (hd.count() > 0) 633 if (hd.count() > 0)
597 headings.replace(heading, hd); 634 headings.replace(heading, hd);
598 else 635 else
599 headings.remove(heading); 636 headings.remove(heading);
600 637
601 modified = TRUE; 638 modified = TRUE;
602 } 639 }
603} 640}
604 641
605 642
606void QSettingsPrivate::writeGroup(const QString &key, const QString &value) 643void QSettingsPrivate::writeGroup(const QString &key, const QString &value)
607{ 644{
608 QSettingsHeading hd; 645 QSettingsHeading hd;
609 QSettingsGroup grp; 646 QSettingsGroup grp;
610 647
611 QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); 648 QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading);
612 if (headingsit != headings.end()) 649 if (headingsit != headings.end())
613 hd = *headingsit; 650 hd = *headingsit;
614 651
615 QSettingsHeading::Iterator grpit = hd.find(group); 652 QSettingsHeading::Iterator grpit = hd.find(group);
616 if (grpit == hd.end()) { 653 if (grpit == hd.end()) {
617 QStringList::Iterator it = searchPaths.begin(); 654 QStringList::Iterator it = searchPaths.begin();
655 if ( !globalScope )
656 ++it;
618 while (it != searchPaths.end()) { 657 while (it != searchPaths.end()) {
619 QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); 658 QString filebase = heading.lower().replace(QRegExp("\\s+"), "_");
620 QString fn((*it++) + "/" + filebase + "rc"); 659 QString fn((*it++) + "/" + filebase + "rc");
621 if (! hd.contains(fn + "cached")) { 660 if (! hd.contains(fn + "cached")) {
622 hd.read(fn); 661 hd.read(fn);
623 hd.insert(fn + "cached", QSettingsGroup()); 662 hd.insert(fn + "cached", QSettingsGroup());
624 } 663 }
625 } 664 }
626 665
627 headings.replace(heading, hd); 666 headings.replace(heading, hd);
628 667
629 grpit = hd.find(group); 668 grpit = hd.find(group);
630 if (grpit != hd.end()) 669 if (grpit != hd.end())
631 grp = *grpit; 670 grp = *grpit;
632 } else if (hd.count() != 0) 671 } else if (hd.count() != 0)
633 grp = *grpit; 672 grp = *grpit;
634 673
635 grp.modified = TRUE; 674 grp.modified = TRUE;
636 grp.replace(key, value); 675 grp.replace(key, value);
637 hd.replace(group, grp); 676 hd.replace(group, grp);
638 headings.replace(heading, hd); 677 headings.replace(heading, hd);
639 678
640 modified = TRUE; 679 modified = TRUE;
641} 680}
642 681
643 682
644QDateTime QSettingsPrivate::modificationTime() 683QDateTime QSettingsPrivate::modificationTime()
645{ 684{
646 QSettingsHeading hd = headings[heading]; 685 QSettingsHeading hd = headings[heading];
647 QSettingsGroup grp = hd[group]; 686 QSettingsGroup grp = hd[group];
648 687
649 QDateTime datetime; 688 QDateTime datetime;
650 689
651 QStringList::Iterator it = searchPaths.begin(); 690 QStringList::Iterator it = searchPaths.begin();
691 if ( !globalScope )
692 ++it;
652 while (it != searchPaths.end()) { 693 while (it != searchPaths.end()) {
653 QFileInfo fi((*it++) + "/" + heading + "rc"); 694 QFileInfo fi((*it++) + "/" + heading + "rc");
654 if (fi.exists() && fi.lastModified() > datetime) 695 if (fi.exists() && fi.lastModified() > datetime)
655 datetime = fi.lastModified(); 696 datetime = fi.lastModified();
656 } 697 }
657 698
658 return datetime; 699 return datetime;
659} 700}
660 701
661static bool verifyKey( const QString &key ) 702bool qt_verify_key( const QString &key )
662{ 703{
663 if ( key.isEmpty() || key[0] != '/' || key.contains( QRegExp("[=\\\\r\\\\n" ) ) ) 704 if ( key.isEmpty() || key[0] != '/' || key.contains( QRegExp("[=\\\\r\\\\n" ) ) )
664 return FALSE; 705 return FALSE;
665 return TRUE; 706 return TRUE;
666} 707}
667 708
668static inline QString groupKey( const QString &group, const QString &key ) 709static inline QString groupKey( const QString &group, const QString &key )
669{ 710{
670 if ( group.endsWith( "/" ) || key.startsWith( "/" ) ) 711 if ( group.isEmpty() || ( group.length() == 1 && group[0] == '/' ) ) {
712 // group is empty, or it contains a single '/', so we just return the key
713 if ( key.startsWith( "/" ) )
714 return key;
715 return "/" + key;
716 } else if ( group.endsWith( "/" ) || key.startsWith( "/" ) ) {
671 return group + key; 717 return group + key;
718 }
672 return group + "/" + key; 719 return group + "/" + key;
673} 720}
674 721
675/*! 722/*!
676 Inserts \a path into the settings search path. The semantics of \a 723 Inserts \a path into the settings search path. The semantics of \a
677 path depends on the system \a s. 724 path depends on the system \a s.
678 725
679 When \a s is \e Windows and the execution environment is \e not 726 When \a s is \e Windows and the execution environment is \e not
680 Windows the function does nothing. Similarly when \a s is \e Unix and 727 Windows the function does nothing. Similarly when \a s is \e Unix and
681 the execution environment is \e not Unix the function does nothing. 728 the execution environment is \e not Unix the function does nothing.
682 729
683 When \a s is \e Windows, and the execution environment is Windows, the 730 When \a s is \e Windows, and the execution environment is Windows, the
684 search path list will be used as the first subfolder of the "Software" 731 search path list will be used as the first subfolder of the "Software"
685 folder in the registry. 732 folder in the registry.
686 733
687 When reading settings the folders are searched forwards from the 734 When reading settings the folders are searched forwards from the
688 first folder (listed below) to the last, returning the first 735 first folder (listed below) to the last, returning the first
689 settings found, and ignoring any folders for which the user doesn't 736 settings found, and ignoring any folders for which the user doesn't
690 have read permission. 737 have read permission.
691 \list 1 738 \list 1
692 \i HKEY_CURRENT_USER/Software/MyCompany/MyApplication 739 \i HKEY_CURRENT_USER/Software/MyCompany/MyApplication
693 \i HKEY_LOCAL_MACHINE/Software/MyCompany/MyApplication 740 \i HKEY_LOCAL_MACHINE/Software/MyCompany/MyApplication
694 \i HKEY_CURRENT_USER/Software/MyApplication 741 \i HKEY_CURRENT_USER/Software/MyApplication
695 \i HKEY_LOCAL_MACHINE/Software/MyApplication 742 \i HKEY_LOCAL_MACHINE/Software/MyApplication
@@ -736,655 +783,662 @@ static inline QString groupKey( const QString &group, const QString &key )
736 \i INSTALL/etc 783 \i INSTALL/etc
737 \i /opt/MyCompany/share/etc 784 \i /opt/MyCompany/share/etc
738 \i /opt/MyCompany/share/MyApplication/etc 785 \i /opt/MyCompany/share/MyApplication/etc
739 \i $HOME/.qt 786 \i $HOME/.qt
740 \endlist 787 \endlist
741 When reading settings the files are searched in the order shown 788 When reading settings the files are searched in the order shown
742 above, with later settings overriding earlier settings. Files for 789 above, with later settings overriding earlier settings. Files for
743 which the user doesn't have read permission are ignored. When saving 790 which the user doesn't have read permission are ignored. When saving
744 settings QSettings works in the order shown above, writing 791 settings QSettings works in the order shown above, writing
745 to the first settings file for which the user has write permission. 792 to the first settings file for which the user has write permission.
746 793
747 Settings under Unix are stored in files whose names are based on the 794 Settings under Unix are stored in files whose names are based on the
748 first subkey of the key (not including the search path). The algorithm 795 first subkey of the key (not including the search path). The algorithm
749 for creating names is essentially: lowercase the first subkey, replace 796 for creating names is essentially: lowercase the first subkey, replace
750 spaces with underscores and add 'rc', e.g. 797 spaces with underscores and add 'rc', e.g.
751 <tt>/MyCompany/MyApplication/background color</tt> will be stored in 798 <tt>/MyCompany/MyApplication/background color</tt> will be stored in
752 <tt>myapplicationrc</tt> (assuming that <tt>/MyCompany</tt> is part of 799 <tt>myapplicationrc</tt> (assuming that <tt>/MyCompany</tt> is part of
753 the search path). 800 the search path).
754 801
755 \sa removeSearchPath() 802 \sa removeSearchPath()
756 803
757*/ 804*/
758void QSettings::insertSearchPath( System s, const QString &path) 805void QSettings::insertSearchPath( System s, const QString &path)
759{ 806{
760#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 807#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
761 if ( d->sysd ) { 808 if ( d->sysd ) {
762 d->sysInsertSearchPath( s, path ); 809 d->sysInsertSearchPath( s, path );
763 return; 810 return;
764 } 811 }
765#endif 812#endif
766 813
767 if ( !verifyKey( path ) ) { 814#if !defined(Q_WS_WIN)
815 if ( s == Windows )
816 return;
817#endif
818#if !defined(Q_WS_WIN)
819 if ( s == Mac )
820 return;
821#endif
822
823 if ( !qt_verify_key( path ) ) {
768#if defined(QT_CHECK_STATE) 824#if defined(QT_CHECK_STATE)
769 qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() ); 825 qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() );
770#endif 826#endif
771 return; 827 return;
772 } 828 }
773 829
774#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 830#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
775 if ( d->sysd && s != Unix ) { 831 if ( d->sysd && s != Unix ) {
776#else 832#else
777 if ( s != Unix ) { 833 if ( s != Unix ) {
778#endif 834#endif
779#ifdef Q_OS_MAC 835#if !defined(QWS) && defined(Q_OS_MAC)
780 if(s != Mac) //mac is respected on the mac as well 836 if(s != Mac) //mac is respected on the mac as well
781#endif 837#endif
782 return; 838 return;
783 } 839 }
784 840
841 QString realPath = path;
842#if defined(Q_WS_WIN)
843 QString defPath = d->globalScope ? d->searchPaths.first() : d->searchPaths.last();
844 realPath = defPath + path;
845#endif
846
785 QStringList::Iterator it = d->searchPaths.find(d->searchPaths.last()); 847 QStringList::Iterator it = d->searchPaths.find(d->searchPaths.last());
786 if (it != d->searchPaths.end()) { 848 if (it != d->searchPaths.end()) {
787 d->searchPaths.insert(it, path); 849 d->searchPaths.insert(it, realPath);
788 } 850 }
789} 851}
790 852
791 853
792/*! 854/*!
793 Removes all occurrences of \a path (using exact matching) from the 855 Removes all occurrences of \a path (using exact matching) from the
794 settings search path for system \a s. Note that the default search 856 settings search path for system \a s. Note that the default search
795 paths cannot be removed. 857 paths cannot be removed.
796 858
797 \sa insertSearchPath() 859 \sa insertSearchPath()
798*/ 860*/
799void QSettings::removeSearchPath( System s, const QString &path) 861void QSettings::removeSearchPath( System s, const QString &path)
800{ 862{
801 if ( !verifyKey( path ) ) { 863 if ( !qt_verify_key( path ) ) {
802#if defined(QT_CHECK_STATE) 864#if defined(QT_CHECK_STATE)
803 qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() ); 865 qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() );
804#endif 866#endif
805 return; 867 return;
806 } 868 }
807 869
808#ifdef Q_WS_WIN 870#ifdef Q_WS_WIN
809 if ( d->sysd ) { 871 if ( d->sysd ) {
810 d->sysRemoveSearchPath( s, path ); 872 d->sysRemoveSearchPath( s, path );
811 return; 873 return;
812 } 874 }
813#endif 875#endif
814#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 876#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
815 if ( d->sysd && s != Unix ) { 877 if ( d->sysd && s != Unix ) {
816#else 878#else
817 if ( s != Unix ) { 879 if ( s != Unix ) {
818#endif 880#endif
819#ifdef Q_OS_MAC 881#if !defined(QWS) && defined(Q_OS_MAC)
820 if(s != Mac) //mac is respected on the mac as well 882 if(s != Mac) //mac is respected on the mac as well
821#endif 883#endif
822 return; 884 return;
823 } 885 }
824 886
825 if (path == d->searchPaths.first() || path == d->searchPaths.last()) 887 if (path == d->searchPaths.first() || path == d->searchPaths.last())
826 return; 888 return;
827 889
828 d->searchPaths.remove(path); 890 d->searchPaths.remove(path);
829} 891}
830 892
831 893
832/*! 894/*!
833 Creates a settings object. 895 Creates a settings object.
834*/ 896*/
835QSettings::QSettings() 897QSettings::QSettings()
836{ 898{
837 d = new QSettingsPrivate( Native ); 899 d = new QSettingsPrivate( Native );
838 Q_CHECK_PTR(d); 900 Q_CHECK_PTR(d);
839 901
840#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 902#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
841 d->sysd = 0; 903 d->sysd = 0;
842 d->sysInit(); 904 d->sysInit();
843#endif 905#endif
844} 906}
845 907
846/*! 908/*!
847 Creates a settings object. If \a format is 'Ini' the settings will 909 Creates a settings object. If \a format is 'Ini' the settings will
848 be stored in a text file, using the Unix strategy (see above). If \a format 910 be stored in a text file, using the Unix strategy (see above). If \a format
849 is 'Native', the settings will be stored in a platform specific way 911 is 'Native', the settings will be stored in a platform specific way
850 (ie. the Windows registry). 912 (ie. the Windows registry).
851*/ 913*/
852QSettings::QSettings( Format format ) 914QSettings::QSettings( Format format )
853{ 915{
854 d = new QSettingsPrivate( format ); 916 d = new QSettingsPrivate( format );
855 Q_CHECK_PTR(d); 917 Q_CHECK_PTR(d);
856 918
857#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 919#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
858 d->sysd = 0; 920 d->sysd = 0;
859 if ( format == Native ) 921 if ( format == Native )
860 d->sysInit(); 922 d->sysInit();
861#else 923#else
862 Q_UNUSED(format); 924 Q_UNUSED(format);
863#endif 925#endif
864} 926}
865 927
866/*! 928/*!
867 Destroys the settings object. All modifications made to the settings 929 Destroys the settings object. All modifications made to the settings
868 will automatically be saved. 930 will automatically be saved.
869 931
870*/ 932*/
871QSettings::~QSettings() 933QSettings::~QSettings()
872{ 934{
873 sync(); 935 sync();
874 936
875#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 937#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
876 if ( d->sysd ) 938 if ( d->sysd )
877 d->sysClear(); 939 d->sysClear();
878#endif 940#endif
879 941
880 delete d; 942 delete d;
881} 943}
882 944
883 945
884/*! \internal 946/*! \internal
885 Writes all modifications to the settings to disk. If any errors are 947 Writes all modifications to the settings to disk. If any errors are
886 encountered, this function returns FALSE, otherwise it will return TRUE. 948 encountered, this function returns FALSE, otherwise it will return TRUE.
887*/ 949*/
888bool QSettings::sync() 950bool QSettings::sync()
889{ 951{
890#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 952#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
891 if ( d->sysd ) 953 if ( d->sysd )
892 return d->sysSync(); 954 return d->sysSync();
893#endif 955#endif
894 if (! d->modified) 956 if (! d->modified)
895 // fake success 957 // fake success
896 return TRUE; 958 return TRUE;
897 959
898 bool success = TRUE; 960 bool success = TRUE;
899 QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin(); 961 QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin();
900 962
901 while (it != d->headings.end()) { 963 while (it != d->headings.end()) {
902 // determine filename 964 // determine filename
903 QSettingsHeading hd(*it); 965 QSettingsHeading hd(*it);
904 QSettingsHeading::Iterator hdit = hd.begin(); 966 QSettingsHeading::Iterator hdit = hd.begin();
905 QFile file; 967 QFile file;
906 968
907 QStringList::Iterator pit = d->searchPaths.begin(); 969 QStringList::Iterator pit = d->searchPaths.begin();
970 if ( !d->globalScope )
971 ++pit;
908 while (pit != d->searchPaths.end()) { 972 while (pit != d->searchPaths.end()) {
909 QString filebase = it.key().lower().replace(QRegExp("\\s+"), "_"); 973 QString filebase = it.key().lower().replace(QRegExp("\\s+"), "_");
910 QFileInfo di(*pit); 974 QFileInfo di(*pit);
911 QFileInfo fi((*pit++) + "/" + filebase + "rc"); 975 QFileInfo fi((*pit++) + "/" + filebase + "rc");
912 976
913 if ((fi.exists() && fi.isFile() && fi.isWritable()) || 977 if ((fi.exists() && fi.isFile() && fi.isWritable()) ||
914 (! fi.exists() && di.isDir() && di.isWritable())) { 978 (! fi.exists() && di.isDir() && di.isWritable())) {
915 file.setName(fi.filePath()); 979 file.setName(fi.filePath());
916 break; 980 break;
917 } 981 }
918 } 982 }
919 983
920 it++; 984 ++it;
921 985
922 if (file.name().isNull() || file.name().isEmpty()) { 986 if ( file.name().isEmpty() ) {
923 987
924#ifdef QT_CHECK_STATE 988#ifdef QT_CHECK_STATE
925 qWarning("QSettings::sync: filename is null/empty"); 989 qWarning("QSettings::sync: filename is null/empty");
926#endif // QT_CHECK_STATE 990#endif // QT_CHECK_STATE
927 991
928 success = FALSE; 992 success = FALSE;
929 continue; 993 continue;
930 } 994 }
931 995
932 HANDLE lockfd = openlock( file.name(), Q_LOCKWRITE ); 996 HANDLE lockfd = openlock( file.name(), Q_LOCKWRITE );
933 997
934 if (! file.open(IO_WriteOnly)) { 998 if (! file.open(IO_WriteOnly)) {
935 999
936#ifdef QT_CHECK_STATE 1000#ifdef QT_CHECK_STATE
937 qWarning("QSettings::sync: failed to open '%s' for writing", 1001 qWarning("QSettings::sync: failed to open '%s' for writing",
938 file.name().latin1()); 1002 file.name().latin1());
939#endif // QT_CHECK_STATE 1003#endif // QT_CHECK_STATE
940 1004
941 success = FALSE; 1005 success = FALSE;
942 continue; 1006 continue;
943 } 1007 }
944 1008
945 // spew to file 1009 // spew to file
946 QTextStream stream(&file); 1010 QTextStream stream(&file);
947 stream.setEncoding(QTextStream::UnicodeUTF8); 1011 stream.setEncoding(QTextStream::UnicodeUTF8);
948 1012
949 while (hdit != hd.end()) { 1013 while (hdit != hd.end()) {
950 if ((*hdit).count() > 0) { 1014 if ((*hdit).count() > 0) {
951 stream << "[" << hdit.key() << "]" << endl; 1015 stream << "[" << hdit.key() << "]" << endl;
952 1016
953 QSettingsGroup grp(*hdit); 1017 QSettingsGroup grp(*hdit);
954 QSettingsGroup::Iterator grpit = grp.begin(); 1018 QSettingsGroup::Iterator grpit = grp.begin();
955 1019
956 while (grpit != grp.end()) { 1020 while (grpit != grp.end()) {
957 QString v = grpit.data(); 1021 QString v = grpit.data();
958 if ( v.isNull() ) { 1022 if ( v.isNull() ) {
959 v = "\\0"; // escape null string 1023 v = "\\0"; // escape null string
960 } else { 1024 } else {
961 v.replace("\\", "\\\\"); // escape backslash 1025 v.replace("\\", "\\\\"); // escape backslash
962 v.replace("\n", "\\n"); // escape newlines 1026 v.replace("\n", "\\n"); // escape newlines
963 } 1027 }
964 1028
965 stream << grpit.key() << "=" << v << endl; 1029 stream << grpit.key() << "=" << v << endl;
966 grpit++; 1030 ++grpit;
967 } 1031 }
968 1032
969 stream << endl; 1033 stream << endl;
970 } 1034 }
971 1035
972 hdit++; 1036 ++hdit;
973 } 1037 }
974 1038
975 if (file.status() != IO_Ok) { 1039 if (file.status() != IO_Ok) {
976 1040
977#ifdef QT_CHECK_STATE 1041#ifdef QT_CHECK_STATE
978 qWarning("QSettings::sync: error at end of write"); 1042 qWarning("QSettings::sync: error at end of write");
979#endif // QT_CHECK_STATE 1043#endif // QT_CHECK_STATE
980 1044
981 success = FALSE; 1045 success = FALSE;
982 } 1046 }
983 1047
984 file.close(); 1048 file.close();
985 1049
986 closelock( lockfd ); 1050 closelock( lockfd );
987 } 1051 }
988 1052
989 d->modified = FALSE; 1053 d->modified = FALSE;
990 1054
991 return success; 1055 return success;
992} 1056}
993 1057
994 1058
995/*! 1059/*!
996 \fn bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) const 1060 \fn bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) const
997 1061
998 Reads the entry specified by \a key, and returns a bool, or the 1062 Reads the entry specified by \a key, and returns a bool, or the
999 default value, \a def, if the entry couldn't be read. 1063 default value, \a def, if the entry couldn't be read.
1000 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE 1064 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE
1001 otherwise. 1065 otherwise.
1002 1066
1003 \sa readEntry(), readNumEntry(), readDoubleEntry(), writeEntry(), removeEntry() 1067 \sa readEntry(), readNumEntry(), readDoubleEntry(), writeEntry(), removeEntry()
1004*/ 1068*/
1005 1069
1006/*! 1070/*!
1007 \internal 1071 \internal
1008*/ 1072*/
1009bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) 1073bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok )
1010{ 1074{
1011 if ( !verifyKey( key ) ) { 1075 if ( !qt_verify_key( key ) ) {
1012#if defined(QT_CHECK_STATE) 1076#if defined(QT_CHECK_STATE)
1013 qWarning( "QSettings::readBoolEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1077 qWarning( "QSettings::readBoolEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1014#endif 1078#endif
1015 if ( ok ) 1079 if ( ok )
1016 *ok = FALSE; 1080 *ok = FALSE;
1017 1081
1018 return def; 1082 return def;
1019 } 1083 }
1020 1084
1021 QString theKey = groupKey( group(), key ); 1085#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1022#if defined(Q_WS_WIN) || defined(Q_OS_MAC)
1023 if ( d->sysd ) 1086 if ( d->sysd )
1024 return d->sysReadBoolEntry( theKey, def, ok ); 1087 return d->sysReadBoolEntry( groupKey( group(), key ), def, ok );
1025#endif 1088#endif
1026 1089
1027 QString value = readEntry( theKey, ( def ? "true" : "false" ), ok ); 1090 QString value = readEntry( key, ( def ? "true" : "false" ), ok );
1028 1091
1029 if (value.lower() == "true") 1092 if (value.lower() == "true")
1030 return TRUE; 1093 return TRUE;
1031 else if (value.lower() == "false") 1094 else if (value.lower() == "false")
1032 return FALSE; 1095 return FALSE;
1033 else if (value == "1") 1096 else if (value == "1")
1034 return TRUE; 1097 return TRUE;
1035 else if (value == "0") 1098 else if (value == "0")
1036 return FALSE; 1099 return FALSE;
1037 1100
1038 if (! value.isEmpty()) 1101 if (! value.isEmpty())
1039 qWarning("QSettings::readBoolEntry: '%s' is not 'true' or 'false'", 1102 qWarning("QSettings::readBoolEntry: '%s' is not 'true' or 'false'",
1040 value.latin1()); 1103 value.latin1());
1041 if ( ok ) 1104 if ( ok )
1042 *ok = FALSE; 1105 *ok = FALSE;
1043 return def; 1106 return def;
1044} 1107}
1045 1108
1046 1109
1047/*! 1110/*!
1048 \fn double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) const 1111 \fn double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) const
1049 1112
1050 Reads the entry specified by \a key, and returns a double, or the 1113 Reads the entry specified by \a key, and returns a double, or the
1051 default value, \a def, if the entry couldn't be read. 1114 default value, \a def, if the entry couldn't be read.
1052 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE 1115 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE
1053 otherwise. 1116 otherwise.
1054 1117
1055 \sa readEntry(), readNumEntry(), readBoolEntry(), writeEntry(), removeEntry() 1118 \sa readEntry(), readNumEntry(), readBoolEntry(), writeEntry(), removeEntry()
1056*/ 1119*/
1057 1120
1058/*! 1121/*!
1059 \internal 1122 \internal
1060*/ 1123*/
1061double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) 1124double QSettings::readDoubleEntry(const QString &key, double def, bool *ok )
1062{ 1125{
1063 if ( !verifyKey( key ) ) { 1126 if ( !qt_verify_key( key ) ) {
1064#if defined(QT_CHECK_STATE) 1127#if defined(QT_CHECK_STATE)
1065 qWarning( "QSettings::readDoubleEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1128 qWarning( "QSettings::readDoubleEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1066#endif 1129#endif
1067 if ( ok ) 1130 if ( ok )
1068 *ok = FALSE; 1131 *ok = FALSE;
1069 1132
1070 return def; 1133 return def;
1071 } 1134 }
1072 1135
1073 QString theKey = groupKey( group(), key ); 1136#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1074#if defined(Q_WS_WIN) || defined(Q_OS_MAC)
1075 if ( d->sysd ) 1137 if ( d->sysd )
1076 return d->sysReadDoubleEntry( theKey, def, ok ); 1138 return d->sysReadDoubleEntry( groupKey( group(), key ), def, ok );
1077#endif 1139#endif
1078 1140
1079 QString value = readEntry( theKey, QString::number(def), ok ); 1141 QString value = readEntry( key, QString::number(def), ok );
1080 bool conv_ok; 1142 bool conv_ok;
1081 double retval = value.toDouble( &conv_ok ); 1143 double retval = value.toDouble( &conv_ok );
1082 if ( conv_ok ) 1144 if ( conv_ok )
1083 return retval; 1145 return retval;
1084 if ( ! value.isEmpty() ) 1146 if ( ! value.isEmpty() )
1085 qWarning( "QSettings::readDoubleEntry: '%s' is not a number", 1147 qWarning( "QSettings::readDoubleEntry: '%s' is not a number",
1086 value.latin1() ); 1148 value.latin1() );
1087 if ( ok ) 1149 if ( ok )
1088 *ok = FALSE; 1150 *ok = FALSE;
1089 return def; 1151 return def;
1090} 1152}
1091 1153
1092 1154
1093/*! 1155/*!
1094 \fn int QSettings::readNumEntry(const QString &key, int def, bool *ok ) const 1156 \fn int QSettings::readNumEntry(const QString &key, int def, bool *ok ) const
1095 1157
1096 Reads the entry specified by \a key, and returns an integer, or the 1158 Reads the entry specified by \a key, and returns an integer, or the
1097 default value, \a def, if the entry couldn't be read. 1159 default value, \a def, if the entry couldn't be read.
1098 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE 1160 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE
1099 otherwise. 1161 otherwise.
1100 1162
1101 \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry() 1163 \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry()
1102*/ 1164*/
1103 1165
1104/*! 1166/*!
1105 \internal 1167 \internal
1106*/ 1168*/
1107int QSettings::readNumEntry(const QString &key, int def, bool *ok ) 1169int QSettings::readNumEntry(const QString &key, int def, bool *ok )
1108{ 1170{
1109 if ( !verifyKey( key ) ) { 1171 if ( !qt_verify_key( key ) ) {
1110#if defined(QT_CHECK_STATE) 1172#if defined(QT_CHECK_STATE)
1111 qWarning( "QSettings::readNumEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1173 qWarning( "QSettings::readNumEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1112#endif 1174#endif
1113 if ( ok ) 1175 if ( ok )
1114 *ok = FALSE; 1176 *ok = FALSE;
1115 return def; 1177 return def;
1116 } 1178 }
1117 1179
1118 QString theKey = groupKey( group(), key ); 1180#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1119
1120#if defined(Q_WS_WIN) || defined(Q_OS_MAC)
1121 if ( d->sysd ) 1181 if ( d->sysd )
1122 return d->sysReadNumEntry( theKey, def, ok ); 1182 return d->sysReadNumEntry( groupKey( group(), key ), def, ok );
1123#endif 1183#endif
1124 1184
1125 QString value = readEntry( theKey, QString::number( def ), ok ); 1185 QString value = readEntry( key, QString::number( def ), ok );
1126 bool conv_ok; 1186 bool conv_ok;
1127 int retval = value.toInt( &conv_ok ); 1187 int retval = value.toInt( &conv_ok );
1128 if ( conv_ok ) 1188 if ( conv_ok )
1129 return retval; 1189 return retval;
1130 if ( ! value.isEmpty() ) 1190 if ( ! value.isEmpty() )
1131 qWarning( "QSettings::readNumEntry: '%s' is not a number", 1191 qWarning( "QSettings::readNumEntry: '%s' is not a number",
1132 value.latin1() ); 1192 value.latin1() );
1133 if ( ok ) 1193 if ( ok )
1134 *ok = FALSE; 1194 *ok = FALSE;
1135 return def; 1195 return def;
1136} 1196}
1137 1197
1138 1198
1139/*! 1199/*!
1140 \fn QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) const 1200 \fn QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) const
1141 1201
1142 Reads the entry specified by \a key, and returns a QString, or the 1202 Reads the entry specified by \a key, and returns a QString, or the
1143 default value, \a def, if the entry couldn't be read. 1203 default value, \a def, if the entry couldn't be read.
1144 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE 1204 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE
1145 otherwise. 1205 otherwise.
1146 1206
1147 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry() 1207 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry()
1148*/ 1208*/
1149 1209
1150/*! 1210/*!
1151 \internal 1211 \internal
1152*/ 1212*/
1153QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) 1213QString QSettings::readEntry(const QString &key, const QString &def, bool *ok )
1154{ 1214{
1155 if ( !verifyKey( key ) ) { 1215 if ( !qt_verify_key( key ) ) {
1156#if defined(QT_CHECK_STATE) 1216#if defined(QT_CHECK_STATE)
1157 qWarning( "QSettings::readEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1217 qWarning( "QSettings::readEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1158#endif 1218#endif
1159 if ( ok ) 1219 if ( ok )
1160 *ok = FALSE; 1220 *ok = FALSE;
1161 1221
1162 return def; 1222 return def;
1163 } 1223 }
1164 1224
1165 QString theKey = groupKey( group(), key ); 1225 QString theKey = groupKey( group(), key );
1166 1226
1167#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 1227#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1168 if ( d->sysd ) 1228 if ( d->sysd )
1169 return d->sysReadEntry( theKey, def, ok ); 1229 return d->sysReadEntry( theKey, def, ok );
1170#endif 1230#endif
1171 1231
1172 if ( ok ) // no, everything is not ok 1232 if ( ok ) // no, everything is not ok
1173 *ok = FALSE; 1233 *ok = FALSE;
1174 1234
1175 QString realkey; 1235 QString realkey;
1176 1236
1177 if (theKey[0] == '/') { 1237 if (theKey[0] == '/') {
1178 // parse our key 1238 // parse our key
1179 QStringList list(QStringList::split('/', theKey)); 1239 QStringList list(QStringList::split('/', theKey));
1180 1240
1181 if (list.count() < 2) { 1241 if (list.count() < 2) {
1182#ifdef QT_CHECK_STATE 1242#ifdef QT_CHECK_STATE
1183 qWarning("QSettings::readEntry: invalid key '%s'", theKey.latin1()); 1243 qWarning("QSettings::readEntry: invalid key '%s'", theKey.latin1());
1184#endif // QT_CHECK_STATE 1244#endif // QT_CHECK_STATE
1185 if ( ok ) 1245 if ( ok )
1186 *ok = FALSE; 1246 *ok = FALSE;
1187 return def; 1247 return def;
1188 } 1248 }
1189 1249
1190 if (list.count() == 2) { 1250 if (list.count() == 2) {
1191 d->heading = list[0]; 1251 d->heading = list[0];
1192 d->group = "General"; 1252 d->group = "General";
1193 realkey = list[1]; 1253 realkey = list[1];
1194 } else { 1254 } else {
1195 d->heading = list[0]; 1255 d->heading = list[0];
1196 d->group = list[1]; 1256 d->group = list[1];
1197 1257
1198 // remove the group from the list 1258 // remove the group from the list
1199 list.remove(list.at(1)); 1259 list.remove(list.at(1));
1200 // remove the heading from the list 1260 // remove the heading from the list
1201 list.remove(list.at(0)); 1261 list.remove(list.at(0));
1202 1262
1203 realkey = list.join("/"); 1263 realkey = list.join("/");
1204 } 1264 }
1205 } else 1265 } else
1206 realkey = theKey; 1266 realkey = theKey;
1207 1267
1208 QSettingsGroup grp = d->readGroup(); 1268 QSettingsGroup grp = d->readGroup();
1209 QString retval = grp[realkey]; 1269 QSettingsGroup::const_iterator it = grp.find( realkey ), end = grp.end();
1210 if ( retval.isNull() ) 1270 QString retval = def;
1211 retval = def; 1271 if ( it != end ) {
1212 else if ( ok ) // everything is ok 1272 // found the value we needed
1213 *ok = TRUE; 1273 retval = *it;
1274 if ( ok ) *ok = TRUE;
1275 }
1214 return retval; 1276 return retval;
1215} 1277}
1216 1278
1217 1279
1218#if !defined(Q_NO_BOOL_TYPE) 1280#if !defined(Q_NO_BOOL_TYPE)
1219/*! 1281/*!
1220 Writes the boolean entry \a value into key \a key. The \a key is 1282 Writes the boolean entry \a value into key \a key. The \a key is
1221 created if it doesn't exist. Any previous value is overwritten by \a 1283 created if it doesn't exist. Any previous value is overwritten by \a
1222 value. 1284 value.
1223 1285
1224 If an error occurs the settings are left unchanged and FALSE is 1286 If an error occurs the settings are left unchanged and FALSE is
1225 returned; otherwise TRUE is returned. 1287 returned; otherwise TRUE is returned.
1226 1288
1227 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1289 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
1228*/ 1290*/
1229bool QSettings::writeEntry(const QString &key, bool value) 1291bool QSettings::writeEntry(const QString &key, bool value)
1230{ 1292{
1231 if ( !verifyKey( key ) ) { 1293 if ( !qt_verify_key( key ) ) {
1232#if defined(QT_CHECK_STATE) 1294#if defined(QT_CHECK_STATE)
1233 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1295 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1234#endif 1296#endif
1235 return FALSE; 1297 return FALSE;
1236 } 1298 }
1237 1299
1238 QString theKey = groupKey( group(), key ); 1300#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1239
1240#if defined(Q_WS_WIN) || defined(Q_OS_MAC)
1241 if ( d->sysd ) 1301 if ( d->sysd )
1242 return d->sysWriteEntry( theKey, value ); 1302 return d->sysWriteEntry( groupKey( group(), key ), value );
1243#endif 1303#endif
1244 QString s(value ? "true" : "false"); 1304 QString s(value ? "true" : "false");
1245 return writeEntry(theKey, s); 1305 return writeEntry(key, s);
1246} 1306}
1247#endif 1307#endif
1248 1308
1249 1309
1250/*! 1310/*!
1251 \overload 1311 \overload
1252 Writes the double entry \a value into key \a key. The \a key is 1312 Writes the double entry \a value into key \a key. The \a key is
1253 created if it doesn't exist. Any previous value is overwritten by \a 1313 created if it doesn't exist. Any previous value is overwritten by \a
1254 value. 1314 value.
1255 1315
1256 If an error occurs the settings are left unchanged and FALSE is 1316 If an error occurs the settings are left unchanged and FALSE is
1257 returned; otherwise TRUE is returned. 1317 returned; otherwise TRUE is returned.
1258 1318
1259 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1319 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
1260*/ 1320*/
1261bool QSettings::writeEntry(const QString &key, double value) 1321bool QSettings::writeEntry(const QString &key, double value)
1262{ 1322{
1263 if ( !verifyKey( key ) ) { 1323 if ( !qt_verify_key( key ) ) {
1264#if defined(QT_CHECK_STATE) 1324#if defined(QT_CHECK_STATE)
1265 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1325 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1266#endif 1326#endif
1267 return FALSE; 1327 return FALSE;
1268 } 1328 }
1269 1329
1270 QString theKey = groupKey( group(), key ); 1330#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1271
1272#if defined(Q_WS_WIN) || defined(Q_OS_MAC)
1273 if ( d->sysd ) 1331 if ( d->sysd )
1274 return d->sysWriteEntry( theKey, value ); 1332 return d->sysWriteEntry( groupKey( group(), key ), value );
1275#endif 1333#endif
1276 QString s(QString::number(value)); 1334 QString s(QString::number(value));
1277 return writeEntry(theKey, s); 1335 return writeEntry(key, s);
1278} 1336}
1279 1337
1280 1338
1281/*! 1339/*!
1282 \overload 1340 \overload
1283 Writes the integer entry \a value into key \a key. The \a key is 1341 Writes the integer entry \a value into key \a key. The \a key is
1284 created if it doesn't exist. Any previous value is overwritten by \a 1342 created if it doesn't exist. Any previous value is overwritten by \a
1285 value. 1343 value.
1286 1344
1287 If an error occurs the settings are left unchanged and FALSE is 1345 If an error occurs the settings are left unchanged and FALSE is
1288 returned; otherwise TRUE is returned. 1346 returned; otherwise TRUE is returned.
1289 1347
1290 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1348 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
1291*/ 1349*/
1292bool QSettings::writeEntry(const QString &key, int value) 1350bool QSettings::writeEntry(const QString &key, int value)
1293{ 1351{
1294 if ( !verifyKey( key ) ) { 1352 if ( !qt_verify_key( key ) ) {
1295#if defined(QT_CHECK_STATE) 1353#if defined(QT_CHECK_STATE)
1296 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1354 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1297#endif 1355#endif
1298 return FALSE; 1356 return FALSE;
1299 } 1357 }
1300 1358
1301 QString theKey = groupKey( group(), key ); 1359#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1302
1303#if defined(Q_WS_WIN) || defined(Q_OS_MAC)
1304 if ( d->sysd ) 1360 if ( d->sysd )
1305 return d->sysWriteEntry( theKey, value ); 1361 return d->sysWriteEntry( groupKey( group(), key ), value );
1306#endif 1362#endif
1307 QString s(QString::number(value)); 1363 QString s(QString::number(value));
1308 return writeEntry(theKey, s); 1364 return writeEntry(key, s);
1309} 1365}
1310 1366
1311 1367
1312/*! 1368/*!
1313 \internal 1369 \internal
1314 1370
1315 Writes the entry specified by \a key with the string-literal \a value, 1371 Writes the entry specified by \a key with the string-literal \a value,
1316 replacing any previous setting. If \a value is zero-length or null, the 1372 replacing any previous setting. If \a value is zero-length or null, the
1317 entry is replaced by an empty setting. 1373 entry is replaced by an empty setting.
1318 1374
1319 \e NOTE: This function is provided because some compilers use the 1375 \e NOTE: This function is provided because some compilers use the
1320 writeEntry (const QString &, bool) overload for this code: 1376 writeEntry (const QString &, bool) overload for this code:
1321 writeEntry ("/foo/bar", "baz") 1377 writeEntry ("/foo/bar", "baz")
1322 1378
1323 If an error occurs, this functions returns FALSE and the object is left 1379 If an error occurs, this functions returns FALSE and the object is left
1324 unchanged. 1380 unchanged.
1325 1381
1326 \sa readEntry(), removeEntry() 1382 \sa readEntry(), removeEntry()
1327*/ 1383*/
1328bool QSettings::writeEntry(const QString &key, const char *value) 1384bool QSettings::writeEntry(const QString &key, const char *value)
1329{ 1385{
1330 if ( !verifyKey( key ) ) { 1386 if ( !qt_verify_key( key ) ) {
1331#if defined(QT_CHECK_STATE) 1387#if defined(QT_CHECK_STATE)
1332 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1388 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1333#endif 1389#endif
1334 return FALSE; 1390 return FALSE;
1335 } 1391 }
1336 1392
1337 QString theKey = groupKey( group(), key ); 1393 return writeEntry(key, QString(value));
1338
1339 return writeEntry(theKey, QString(value));
1340} 1394}
1341 1395
1342 1396
1343/*! 1397/*!
1344 \overload 1398 \overload
1345 Writes the string entry \a value into key \a key. The \a key is 1399 Writes the string entry \a value into key \a key. The \a key is
1346 created if it doesn't exist. Any previous value is overwritten by \a 1400 created if it doesn't exist. Any previous value is overwritten by \a
1347 value. If \a value is an empty string or a null string the key's 1401 value. If \a value is an empty string or a null string the key's
1348 value will be an empty string. 1402 value will be an empty string.
1349 1403
1350 If an error occurs the settings are left unchanged and FALSE is 1404 If an error occurs the settings are left unchanged and FALSE is
1351 returned; otherwise TRUE is returned. 1405 returned; otherwise TRUE is returned.
1352 1406
1353 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1407 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
1354*/ 1408*/
1355bool QSettings::writeEntry(const QString &key, const QString &value) 1409bool QSettings::writeEntry(const QString &key, const QString &value)
1356{ 1410{
1357 if ( !verifyKey( key ) ) { 1411 if ( !qt_verify_key( key ) ) {
1358#if defined(QT_CHECK_STATE) 1412#if defined(QT_CHECK_STATE)
1359 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1413 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1360#endif 1414#endif
1361 return FALSE; 1415 return FALSE;
1362 } 1416 }
1363 1417
1364 QString theKey = groupKey( group(), key ); 1418 QString theKey = groupKey( group(), key );
1365 1419
1366#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 1420#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1367 if ( d->sysd ) 1421 if ( d->sysd )
1368 return d->sysWriteEntry( theKey, value ); 1422 return d->sysWriteEntry( theKey, value );
1369#endif 1423#endif
1370 // NOTE: we *do* allow value to be a null/empty string 1424 // NOTE: we *do* allow value to be a null/empty string
1371 1425
1372 QString realkey; 1426 QString realkey;
1373 1427
1374 if (theKey[0] == '/') { 1428 if (theKey[0] == '/') {
1375 // parse our key 1429 // parse our key
1376 QStringList list(QStringList::split('/', theKey)); 1430 QStringList list(QStringList::split('/', theKey));
1377 1431
1378 if (list.count() < 2) { 1432 if (list.count() < 2) {
1379#ifdef QT_CHECK_STATE 1433#ifdef QT_CHECK_STATE
1380 qWarning("QSettings::writeEntry: invalid key '%s'", theKey.latin1()); 1434 qWarning("QSettings::writeEntry: invalid key '%s'", theKey.latin1());
1381#endif // QT_CHECK_STATE 1435#endif // QT_CHECK_STATE
1382 1436
1383 return FALSE; 1437 return FALSE;
1384 } 1438 }
1385 1439
1386 if (list.count() == 2) { 1440 if (list.count() == 2) {
1387 d->heading = list[0]; 1441 d->heading = list[0];
1388 d->group = "General"; 1442 d->group = "General";
1389 realkey = list[1]; 1443 realkey = list[1];
1390 } else { 1444 } else {
@@ -1394,58 +1448,58 @@ bool QSettings::writeEntry(const QString &key, const QString &value)
1394 // remove the group from the list 1448 // remove the group from the list
1395 list.remove(list.at(1)); 1449 list.remove(list.at(1));
1396 // remove the heading from the list 1450 // remove the heading from the list
1397 list.remove(list.at(0)); 1451 list.remove(list.at(0));
1398 1452
1399 realkey = list.join("/"); 1453 realkey = list.join("/");
1400 } 1454 }
1401 } else 1455 } else
1402 realkey = theKey; 1456 realkey = theKey;
1403 1457
1404 d->writeGroup(realkey, value); 1458 d->writeGroup(realkey, value);
1405 return TRUE; 1459 return TRUE;
1406} 1460}
1407 1461
1408 1462
1409/*! 1463/*!
1410 Removes the entry specified by \a key. 1464 Removes the entry specified by \a key.
1411 1465
1412 Returns TRUE if the entry existed and was removed; otherwise returns FALSE. 1466 Returns TRUE if the entry existed and was removed; otherwise returns FALSE.
1413 1467
1414 \sa readEntry(), writeEntry() 1468 \sa readEntry(), writeEntry()
1415*/ 1469*/
1416bool QSettings::removeEntry(const QString &key) 1470bool QSettings::removeEntry(const QString &key)
1417{ 1471{
1418 if ( !verifyKey( key ) ) { 1472 if ( !qt_verify_key( key ) ) {
1419#if defined(QT_CHECK_STATE) 1473#if defined(QT_CHECK_STATE)
1420 qWarning( "QSettings::removeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1474 qWarning( "QSettings::removeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1421#endif 1475#endif
1422 return FALSE; 1476 return FALSE;
1423 } 1477 }
1424 1478
1425 QString theKey = groupKey( group(), key ); 1479 QString theKey = groupKey( group(), key );
1426 1480
1427#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 1481#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1428 if ( d->sysd ) 1482 if ( d->sysd )
1429 return d->sysRemoveEntry( theKey ); 1483 return d->sysRemoveEntry( theKey );
1430#endif 1484#endif
1431 1485
1432 QString realkey; 1486 QString realkey;
1433 1487
1434 if (theKey[0] == '/') { 1488 if (theKey[0] == '/') {
1435 // parse our key 1489 // parse our key
1436 QStringList list(QStringList::split('/', theKey)); 1490 QStringList list(QStringList::split('/', theKey));
1437 1491
1438 if (list.count() < 2) { 1492 if (list.count() < 2) {
1439#ifdef QT_CHECK_STATE 1493#ifdef QT_CHECK_STATE
1440 qWarning("QSettings::removeEntry: invalid key '%s'", theKey.latin1()); 1494 qWarning("QSettings::removeEntry: invalid key '%s'", theKey.latin1());
1441#endif // QT_CHECK_STATE 1495#endif // QT_CHECK_STATE
1442 1496
1443 return FALSE; 1497 return FALSE;
1444 } 1498 }
1445 1499
1446 if (list.count() == 2) { 1500 if (list.count() == 2) {
1447 d->heading = list[0]; 1501 d->heading = list[0];
1448 d->group = "General"; 1502 d->group = "General";
1449 realkey = list[1]; 1503 realkey = list[1];
1450 } else { 1504 } else {
1451 d->heading = list[0]; 1505 d->heading = list[0];
@@ -1473,272 +1527,295 @@ bool QSettings::removeEntry(const QString &key)
1473 Example settings: 1527 Example settings:
1474 \code 1528 \code
1475 /MyCompany/MyApplication/background color 1529 /MyCompany/MyApplication/background color
1476 /MyCompany/MyApplication/foreground color 1530 /MyCompany/MyApplication/foreground color
1477 /MyCompany/MyApplication/geometry/x 1531 /MyCompany/MyApplication/geometry/x
1478 /MyCompany/MyApplication/geometry/y 1532 /MyCompany/MyApplication/geometry/y
1479 /MyCompany/MyApplication/geometry/width 1533 /MyCompany/MyApplication/geometry/width
1480 /MyCompany/MyApplication/geometry/height 1534 /MyCompany/MyApplication/geometry/height
1481 \endcode 1535 \endcode
1482 \code 1536 \code
1483 QStringList keys = entryList( "/MyCompany/MyApplication" ); 1537 QStringList keys = entryList( "/MyCompany/MyApplication" );
1484 \endcode 1538 \endcode
1485 \c keys contains 'background color' and 'foreground color'. It does 1539 \c keys contains 'background color' and 'foreground color'. It does
1486 not contain 'geometry' because this key contains keys not entries. 1540 not contain 'geometry' because this key contains keys not entries.
1487 1541
1488 To access the geometry values could either use subkeyList() to read 1542 To access the geometry values could either use subkeyList() to read
1489 the keys and then read each entry, or simply read each entry 1543 the keys and then read each entry, or simply read each entry
1490 directly by specifying its full key, e.g. 1544 directly by specifying its full key, e.g.
1491 "/MyCompany/MyApplication/geometry/y". 1545 "/MyCompany/MyApplication/geometry/y".
1492 1546
1493 \sa subkeyList() 1547 \sa subkeyList()
1494*/ 1548*/
1495QStringList QSettings::entryList(const QString &key) const 1549QStringList QSettings::entryList(const QString &key) const
1496{ 1550{
1497 if ( !verifyKey( key ) ) { 1551 if ( !qt_verify_key( key ) ) {
1498#if defined(QT_CHECK_STATE) 1552#if defined(QT_CHECK_STATE)
1499 qWarning( "QSettings::entryList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() ); 1553 qWarning( "QSettings::entryList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() );
1500#endif 1554#endif
1501 return QStringList(); 1555 return QStringList();
1502 } 1556 }
1503 1557
1504 QString theKey = groupKey( group(), key ); 1558 QString theKey = groupKey( group(), key );
1505 1559
1506#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 1560#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1507 if ( d->sysd ) 1561 if ( d->sysd )
1508 return d->sysEntryList( theKey ); 1562 return d->sysEntryList( theKey );
1509#endif 1563#endif
1510 1564
1511 QString realkey; 1565 QString realkey;
1512 if (theKey[0] == '/') { 1566 if (theKey[0] == '/') {
1513 // parse our key 1567 // parse our key
1514 QStringList list(QStringList::split('/', theKey)); 1568 QStringList list(QStringList::split('/', theKey));
1515 1569
1516 if (list.count() < 1) { 1570 if (list.count() < 1) {
1517#ifdef QT_CHECK_STATE 1571#ifdef QT_CHECK_STATE
1518 qWarning("QSettings::listEntries: invalid key '%s'", theKey.latin1()); 1572 qWarning("QSettings::listEntries: invalid key '%s'", theKey.latin1());
1519#endif // QT_CHECK_STATE 1573#endif // QT_CHECK_STATE
1520 1574
1521 return QStringList(); 1575 return QStringList();
1522 } 1576 }
1523 1577
1524 if (list.count() == 1) { 1578 if (list.count() == 1) {
1525 d->heading = list[0]; 1579 d->heading = list[0];
1526 d->group = "General"; 1580 d->group = "General";
1527 } else { 1581 } else {
1528 d->heading = list[0]; 1582 d->heading = list[0];
1529 d->group = list[1]; 1583 d->group = list[1];
1530 1584
1531 // remove the group from the list 1585 // remove the group from the list
1532 list.remove(list.at(1)); 1586 list.remove(list.at(1));
1533 // remove the heading from the list 1587 // remove the heading from the list
1534 list.remove(list.at(0)); 1588 list.remove(list.at(0));
1535 1589
1536 realkey = list.join("/"); 1590 realkey = list.join("/");
1537 } 1591 }
1538 } else 1592 } else
1539 realkey = theKey; 1593 realkey = theKey;
1540 1594
1541 QSettingsGroup grp = d->readGroup(); 1595 QSettingsGroup grp = d->readGroup();
1542 QSettingsGroup::Iterator it = grp.begin(); 1596 QSettingsGroup::Iterator it = grp.begin();
1543 QStringList ret; 1597 QStringList ret;
1544 QString itkey; 1598 QString itkey;
1545 while (it != grp.end()) { 1599 while (it != grp.end()) {
1546 itkey = it.key(); 1600 itkey = it.key();
1547 it++; 1601 ++it;
1548 1602
1549 if ( realkey.length() > 0 ) { 1603 if ( realkey.length() > 0 ) {
1550 if ( itkey.left( realkey.length() ) != realkey ) 1604 if ( itkey.left( realkey.length() ) != realkey )
1551 continue; 1605 continue;
1552 else 1606 else
1553 itkey.remove( 0, realkey.length() + 1 ); 1607 itkey.remove( 0, realkey.length() + 1 );
1554 } 1608 }
1555 1609
1556 if ( itkey.find( '/' ) != -1 ) 1610 if ( itkey.find( '/' ) != -1 )
1557 continue; 1611 continue;
1558 1612
1559 ret << itkey; 1613 ret << itkey;
1560 } 1614 }
1561 1615
1562 return ret; 1616 return ret;
1563} 1617}
1564 1618
1565 1619
1566/*! 1620/*!
1567 Returns a list of the keys which contain keys under \a key. Does \e 1621 Returns a list of the keys which contain keys under \a key. Does \e
1568 not return any keys that contain entries. 1622 not return any keys that contain entries.
1569 1623
1570 Example settings: 1624 Example settings:
1571 \code 1625 \code
1572 /MyCompany/MyApplication/background color 1626 /MyCompany/MyApplication/background color
1573 /MyCompany/MyApplication/foreground color 1627 /MyCompany/MyApplication/foreground color
1574 /MyCompany/MyApplication/geometry/x 1628 /MyCompany/MyApplication/geometry/x
1575 /MyCompany/MyApplication/geometry/y 1629 /MyCompany/MyApplication/geometry/y
1576 /MyCompany/MyApplication/geometry/width 1630 /MyCompany/MyApplication/geometry/width
1577 /MyCompany/MyApplication/geometry/height 1631 /MyCompany/MyApplication/geometry/height
1578 /MyCompany/MyApplication/recent files/1 1632 /MyCompany/MyApplication/recent files/1
1579 /MyCompany/MyApplication/recent files/2 1633 /MyCompany/MyApplication/recent files/2
1580 /MyCompany/MyApplication/recent files/3 1634 /MyCompany/MyApplication/recent files/3
1581 \endcode 1635 \endcode
1582 \code 1636 \code
1583 QStringList keys = subkeyList( "/MyCompany/MyApplication" ); 1637 QStringList keys = subkeyList( "/MyCompany/MyApplication" );
1584 \endcode 1638 \endcode
1585 \c keys contains 'geometry' and 'recent files'. It does not contain 1639 \c keys contains 'geometry' and 'recent files'. It does not contain
1586 'background color' or 'foreground color' because they are keys which 1640 'background color' or 'foreground color' because they are keys which
1587 contain entries not keys. To get a list of keys that have values 1641 contain entries not keys. To get a list of keys that have values
1588 rather than subkeys use entryList(). 1642 rather than subkeys use entryList().
1589 1643
1590 \sa entryList() 1644 \sa entryList()
1591*/ 1645*/
1592QStringList QSettings::subkeyList(const QString &key) const 1646QStringList QSettings::subkeyList(const QString &key) const
1593{ 1647{
1594 if ( !verifyKey( key ) ) { 1648 if ( !qt_verify_key( key ) ) {
1595#if defined(QT_CHECK_STATE) 1649#if defined(QT_CHECK_STATE)
1596 qWarning( "QSettings::subkeyList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() ); 1650 qWarning( "QSettings::subkeyList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() );
1597#endif 1651#endif
1598 return QStringList(); 1652 return QStringList();
1599 } 1653 }
1600 1654
1601 QString theKey = groupKey( group(), key ); 1655 QString theKey = groupKey( group(), key );
1602 1656
1603#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 1657#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1604 if ( d->sysd ) 1658 if ( d->sysd )
1605 return d->sysSubkeyList( theKey ); 1659 return d->sysSubkeyList( theKey );
1606#endif 1660#endif
1607 1661
1608 QString realkey; 1662 QString realkey;
1663 int subkeycount = 2;
1609 if (theKey[0] == '/') { 1664 if (theKey[0] == '/') {
1610 // parse our key 1665 // parse our key
1611 QStringList list(QStringList::split('/', theKey)); 1666 QStringList list(QStringList::split('/', theKey));
1612 1667
1613 if (list.count() < 1) { 1668 if (list.count() < 1) {
1614#ifdef QT_CHECK_STATE 1669#ifdef QT_CHECK_STATE
1615 qWarning("QSettings::subkeyList: invalid key '%s'", theKey.latin1()); 1670 qWarning("QSettings::subkeyList: invalid key '%s'", theKey.latin1());
1616#endif // QT_CHECK_STATE 1671#endif // QT_CHECK_STATE
1617 1672
1618 return QStringList(); 1673 return QStringList();
1619 } 1674 }
1620 1675
1676 subkeycount = list.count();
1677
1621 if (list.count() == 1) { 1678 if (list.count() == 1) {
1622 d->heading = list[0]; 1679 d->heading = list[0];
1623 d->group = "General"; 1680 d->group = "General";
1624 } else { 1681 } else {
1625 d->heading = list[0]; 1682 d->heading = list[0];
1626 d->group = list[1]; 1683 d->group = list[1];
1627 1684
1628 // remove the group from the list 1685 // remove the group from the list
1629 list.remove(list.at(1)); 1686 list.remove(list.at(1));
1630 // remove the heading from the list 1687 // remove the heading from the list
1631 list.remove(list.at(0)); 1688 list.remove(list.at(0));
1632 1689
1633 realkey = list.join("/"); 1690 realkey = list.join("/");
1634 } 1691 }
1692
1635 } else 1693 } else
1636 realkey = theKey; 1694 realkey = theKey;
1637 1695
1696 QStringList ret;
1697 if ( subkeycount == 1 ) {
1698 QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin();
1699 while ( it != d->headings.end() ) {
1700 if ( it.key() != "General" && ! ret.contains( it.key() ) )
1701 ret << it.key();
1702 ++it;
1703 }
1704
1705 return ret;
1706 }
1707
1638 QSettingsGroup grp = d->readGroup(); 1708 QSettingsGroup grp = d->readGroup();
1639 QSettingsGroup::Iterator it = grp.begin(); 1709 QSettingsGroup::Iterator it = grp.begin();
1640 QStringList ret;
1641 QString itkey; 1710 QString itkey;
1642 while (it != grp.end()) { 1711 while (it != grp.end()) {
1643 itkey = it.key(); 1712 itkey = it.key();
1644 it++; 1713 ++it;
1645 1714
1646 if ( realkey.length() > 0 ) { 1715 if ( realkey.length() > 0 ) {
1647 if ( itkey.left( realkey.length() ) != realkey ) 1716 if ( itkey.left( realkey.length() ) != realkey )
1648 continue; 1717 continue;
1649 else 1718 else
1650 itkey.remove( 0, realkey.length() + 1 ); 1719 itkey.remove( 0, realkey.length() + 1 );
1651 } 1720 }
1652 1721
1653 int slash = itkey.find( '/' ); 1722 int slash = itkey.find( '/' );
1654 if ( slash == -1 ) 1723 if ( slash == -1 )
1655 continue; 1724 continue;
1656 itkey.truncate( slash ); 1725 itkey.truncate( slash );
1657 1726
1658 if ( ! ret.contains( itkey ) ) 1727 if ( ! ret.contains( itkey ) )
1659 ret << itkey; 1728 ret << itkey;
1660 } 1729 }
1661 1730
1662 return ret; 1731 return ret;
1663} 1732}
1664 1733
1665 1734
1666/*! 1735/*!
1667 \internal 1736 \internal
1668 1737
1669 This function returns the time of last modification for \a key. 1738 This function returns the time of last modification for \a key.
1670*/ 1739*/
1671QDateTime QSettings::lastModficationTime(const QString &key) 1740QDateTime QSettings::lastModficationTime(const QString &key)
1672{ 1741{
1673 if ( !verifyKey( key ) ) { 1742 if ( !qt_verify_key( key ) ) {
1674#if defined(QT_CHECK_STATE) 1743#if defined(QT_CHECK_STATE)
1675 qWarning( "QSettings::lastModficationTime: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1744 qWarning( "QSettings::lastModficationTime: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1676#endif 1745#endif
1677 return QDateTime(); 1746 return QDateTime();
1678 } 1747 }
1679 1748
1680 QString theKey = groupKey( group(), key ); 1749 QString theKey = groupKey( group(), key );
1681 1750
1682#if defined(Q_WS_WIN) || defined(Q_OS_MAC) 1751#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1683 if ( d->sysd ) 1752 if ( d->sysd )
1684 return QDateTime(); 1753 return QDateTime();
1685#endif 1754#endif
1686 1755
1687 if (theKey[0] == '/') { 1756 if (theKey[0] == '/') {
1688 // parse our key 1757 // parse our key
1689 QStringList list(QStringList::split('/', theKey)); 1758 QStringList list(QStringList::split('/', theKey));
1690 1759
1691 if (list.count() < 2) { 1760 if (list.count() < 2) {
1692#ifdef QT_CHECK_STATE 1761#ifdef QT_CHECK_STATE
1693 qWarning("QSettings::lastModficationTime: invalid key '%s'", theKey.latin1()); 1762 qWarning("QSettings::lastModficationTime: invalid key '%s'", theKey.latin1());
1694#endif // QT_CHECK_STATE 1763#endif // QT_CHECK_STATE
1695 1764
1696 return QDateTime(); 1765 return QDateTime();
1697 } 1766 }
1698 1767
1699 if (list.count() == 2) { 1768 if (list.count() == 2) {
1700 d->heading = list[0]; 1769 d->heading = list[0];
1701 d->group = "General"; 1770 d->group = "General";
1702 } else { 1771 } else {
1703 d->heading = list[0]; 1772 d->heading = list[0];
1704 d->group = list[1]; 1773 d->group = list[1];
1705 } 1774 }
1706 } 1775 }
1707 1776
1708 return d->modificationTime(); 1777 return d->modificationTime();
1709} 1778}
1710 1779
1711 1780
1712/*! 1781/*!
1713 \overload 1782 \overload
1714 1783
1715 Writes the string list entry \a value into key \a key. The \a key 1784 Writes the string list entry \a value into key \a key. The \a key
1716 is created if it doesn't exist. Any previous value is overwritten 1785 is created if it doesn't exist. Any previous value is overwritten
1717 by \a value. The list is stored as a sequence of strings separated 1786 by \a value. The list is stored as a sequence of strings separated
1718 by \a separator, so none of the strings in the list should contain 1787 by \a separator (using QStringList::join()), so none of the
1719 the separator. If the list is empty or null the key's value will 1788 strings in the list should contain the separator. If the list is
1720 be an empty string. 1789 empty or null the key's value will be an empty string.
1790
1791 \warning The list should not contain empty or null strings, as
1792 readListEntry() will use QStringList::split() to recreate the
1793 list. As the documentation states, QStringList::split() will omit
1794 empty strings from the list. Because of this, it is impossible to
1795 retrieve identical list data that is stored with this function.
1796 We recommend using the writeEntry() and readListEntry() overloads
1797 that do not take a \a separator argument.
1721 1798
1722 If an error occurs the settings are left unchanged and FALSE is 1799 If an error occurs the settings are left unchanged and FALSE is
1723 returned; otherwise returns TRUE. 1800 returned; otherwise returns TRUE.
1724 1801
1725 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1802 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
1726*/ 1803*/
1727bool QSettings::writeEntry(const QString &key, const QStringList &value, 1804bool QSettings::writeEntry(const QString &key, const QStringList &value,
1728 const QChar &separator) 1805 const QChar &separator)
1729{ 1806{
1730 QString s(value.join(separator)); 1807 QString s(value.join(separator));
1731 return writeEntry(key, s); 1808 return writeEntry(key, s);
1732} 1809}
1733 1810
1734/*! 1811/*!
1735 \overload 1812 \overload
1736 1813
1737 Writes the string list entry \a value into key \a key. The \a key 1814 Writes the string list entry \a value into key \a key. The \a key
1738 is created if it doesn't exist. Any previous value is overwritten 1815 is created if it doesn't exist. Any previous value is overwritten
1739 by \a value. 1816 by \a value.
1740 1817
1741 If an error occurs the settings are left unchanged and FALSE is 1818 If an error occurs the settings are left unchanged and FALSE is
1742 returned; otherwise returns TRUE. 1819 returned; otherwise returns TRUE.
1743 1820
1744 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1821 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
@@ -1747,48 +1824,55 @@ bool QSettings::writeEntry(const QString &key, const QStringList &value)
1747{ 1824{
1748 QString s; 1825 QString s;
1749 for (QStringList::ConstIterator it=value.begin(); it!=value.end(); ++it) { 1826 for (QStringList::ConstIterator it=value.begin(); it!=value.end(); ++it) {
1750 QString el = *it; 1827 QString el = *it;
1751 if ( el.isNull() ) { 1828 if ( el.isNull() ) {
1752 el = "^0"; 1829 el = "^0";
1753 } else { 1830 } else {
1754 el.replace("^", "^^"); 1831 el.replace("^", "^^");
1755 } 1832 }
1756 s+=el; 1833 s+=el;
1757 s+="^e"; // end of element 1834 s+="^e"; // end of element
1758 } 1835 }
1759 return writeEntry(key, s); 1836 return writeEntry(key, s);
1760} 1837}
1761 1838
1762 1839
1763/*! 1840/*!
1764 \overload QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) const 1841 \overload QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) const
1765 1842
1766 Reads the entry specified by \a key as a string. The \a separator 1843 Reads the entry specified by \a key as a string. The \a separator
1767 is used to create a QStringList by calling QStringList::split(\a 1844 is used to create a QStringList by calling QStringList::split(\a
1768 separator, entry). If \a ok is not 0: \a *ok is set to TRUE if the 1845 separator, entry). If \a ok is not 0: \a *ok is set to TRUE if the
1769 key was read, otherwise \a *ok is set to FALSE. 1846 key was read, otherwise \a *ok is set to FALSE.
1770 1847
1848 \warning As the documentation states, QStringList::split() will
1849 omit empty strings from the list. Because of this, it is
1850 impossible to retrieve identical list data with this function. We
1851 recommend using the readListEntry() and writeEntry() overloads
1852 that do not take a \a separator argument.
1853
1854
1771 Note that if you want to iterate over the list, you should iterate 1855 Note that if you want to iterate over the list, you should iterate
1772 over a copy, e.g. 1856 over a copy, e.g.
1773 \code 1857 \code
1774 QStringList list = mySettings.readListEntry( "size", " " ); 1858 QStringList list = mySettings.readListEntry( "size", " " );
1775 QStringList::Iterator it = list.begin(); 1859 QStringList::Iterator it = list.begin();
1776 while( it != list.end() ) { 1860 while( it != list.end() ) {
1777 myProcessing( *it ); 1861 myProcessing( *it );
1778 ++it; 1862 ++it;
1779 } 1863 }
1780 \endcode 1864 \endcode
1781 1865
1782 \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split() 1866 \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split()
1783*/ 1867*/
1784 1868
1785/*! 1869/*!
1786 \internal 1870 \internal
1787*/ 1871*/
1788QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) 1872QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok )
1789{ 1873{
1790 QString value = readEntry( key, QString::null, ok ); 1874 QString value = readEntry( key, QString::null, ok );
1791 if ( ok && !*ok ) 1875 if ( ok && !*ok )
1792 return QStringList(); 1876 return QStringList();
1793 1877
1794 return QStringList::split(separator, value); 1878 return QStringList::split(separator, value);
@@ -1826,130 +1910,151 @@ QStringList QSettings::readListEntry(const QString &key, bool *ok )
1826 QString s; 1910 QString s;
1827 bool esc=FALSE; 1911 bool esc=FALSE;
1828 for (int i=0; i<(int)value.length(); i++) { 1912 for (int i=0; i<(int)value.length(); i++) {
1829 if ( esc ) { 1913 if ( esc ) {
1830 if ( value[i] == 'e' ) { // end-of-string 1914 if ( value[i] == 'e' ) { // end-of-string
1831 l.append(s); 1915 l.append(s);
1832 s=""; 1916 s="";
1833 } else if ( value[i] == '0' ) { // null string 1917 } else if ( value[i] == '0' ) { // null string
1834 s=QString::null; 1918 s=QString::null;
1835 } else { 1919 } else {
1836 s.append(value[i]); 1920 s.append(value[i]);
1837 } 1921 }
1838 esc=FALSE; 1922 esc=FALSE;
1839 } else if ( value[i] == '^' ) { 1923 } else if ( value[i] == '^' ) {
1840 esc = TRUE; 1924 esc = TRUE;
1841 } else { 1925 } else {
1842 s.append(value[i]); 1926 s.append(value[i]);
1843 if ( i == (int)value.length()-1 ) 1927 if ( i == (int)value.length()-1 )
1844 l.append(s); 1928 l.append(s);
1845 } 1929 }
1846 } 1930 }
1847 return l; 1931 return l;
1848} 1932}
1849 1933
1934#ifdef Q_OS_MAC
1935void qt_setSettingsBasePath(const QString &); //qsettings_mac.cpp
1936#endif
1937
1850/*! 1938/*!
1851 Insert platform-dependent paths from platform-independent information. 1939 Insert platform-dependent paths from platform-independent information.
1852 1940
1853 The \a domain should be an Internet domain name 1941 The \a domain should be an Internet domain name
1854 controlled by the producer of the software, eg. Trolltech products 1942 controlled by the producer of the software, eg. Trolltech products
1855 use "trolltech.com". 1943 use "trolltech.com".
1856 1944
1857 The \a product should be the official name of the product. 1945 The \a product should be the official name of the product.
1858 1946
1859 The \a scope should be 1947 The \a scope should be
1860 QSettings::User for user-specific settings, or 1948 QSettings::User for user-specific settings, or
1861 QSettings::Global for system-wide settings (generally 1949 QSettings::Global for system-wide settings (generally
1862 these will be read-only to many users). 1950 these will be read-only to many users).
1951
1952 Not all information is relevant on all systems (e.g. scoping is
1953 currently used only if QSettings accesses the Windows registry).
1863*/ 1954*/
1864 1955
1865void QSettings::setPath( const QString &domain, const QString &product, Scope scope ) 1956void QSettings::setPath( const QString &domain, const QString &product, Scope scope )
1866{ 1957{
1867// On Windows, any trailing ".com(\..*)" is stripped from the domain. The 1958// On Windows, any trailing ".com(\..*)" is stripped from the domain. The
1868// Global scope corresponds to HKEY_LOCAL_MACHINE, and User corresponds to 1959// Global scope corresponds to HKEY_LOCAL_MACHINE, and User corresponds to
1869// HKEY_CURRENT_USER. Note that on some installations, not all users can 1960// HKEY_CURRENT_USER. Note that on some installations, not all users can
1870// write to the Global scope. On UNIX, any trailing ".com(\..*)" is stripped 1961// write to the Global scope. On UNIX, any trailing ".com(\..*)" is stripped
1871// from the domain. The Global scope corresponds to "/opt" (this would be 1962// from the domain. The Global scope corresponds to "/opt" (this would be
1872// configurable at library build time - eg. to "/usr/local" or "/usr"), 1963// configurable at library build time - eg. to "/usr/local" or "/usr"),
1873// while the User scope corresponds to $HOME/.*rc. 1964// while the User scope corresponds to $HOME/.*rc.
1874// Note that on most installations, not all users can write to the System 1965// Note that on most installations, not all users can write to the System
1875// scope. 1966// scope.
1876// 1967//
1877// On MacOS X, if there is no "." in domain, append ".com", then reverse the 1968// On MacOS X, if there is no "." in domain, append ".com", then reverse the
1878// order of the elements (Mac OS uses "com.apple.finder" as domain+product). 1969// order of the elements (Mac OS uses "com.apple.finder" as domain+product).
1879// The Global scope corresponds to /Library/Preferences/*.plist, while the 1970// The Global scope corresponds to /Library/Preferences/*.plist, while the
1880// User scope corresponds to ~/Library/Preferences/*.plist. 1971// User scope corresponds to ~/Library/Preferences/*.plist.
1881// Note that on most installations, not all users can write to the System 1972// Note that on most installations, not all users can write to the System
1882// scope. 1973// scope.
1974 d->globalScope = scope == Global;
1975
1883 QString actualSearchPath; 1976 QString actualSearchPath;
1884 int lastDot = domain.findRev( '.' ); 1977 int lastDot = domain.findRev( '.' );
1885 1978
1886#if defined(Q_WS_WIN) 1979#if defined(Q_WS_WIN)
1887 actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product; 1980 actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product;
1888 insertSearchPath( Windows, actualSearchPath ); 1981 insertSearchPath( Windows, actualSearchPath );
1889#elif defined(Q_WS_MAC) 1982#elif !defined(QWS) && defined(Q_OS_MAC)
1890 QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + "."; 1983 QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + ".";
1891 if ( topLevelDomain.isEmpty() ) 1984 if ( !topLevelDomain.isEmpty() )
1892 topLevelDomain = "com."; 1985 qt_setSettingsBasePath( topLevelDomain );
1893 actualSearchPath = "/" + topLevelDomain + domain.left( lastDot ) + product; 1986 actualSearchPath = "/" + domain.left( lastDot ) + product;
1894 insertSearchPath( Mac, actualSearchPath ); 1987 insertSearchPath( Mac, actualSearchPath );
1895#else 1988#else
1896 actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product; 1989 actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product;
1897 insertSearchPath( Unix, actualSearchPath ); 1990 insertSearchPath( Unix, actualSearchPath );
1898#endif 1991#endif
1899
1900 d->globalScope = scope == Global;
1901} 1992}
1902 1993
1903/*! 1994/*!
1904 Appends \a group to the current key prefix. 1995 Appends \a group to the current key prefix.
1996
1997 \code
1998 QSettings settings;
1999 settings.beginGroup( "/MainWindow" );
2000 // read values
2001 settings.endGroup();
2002 \endcode
1905*/ 2003*/
1906void QSettings::beginGroup( const QString &group ) 2004void QSettings::beginGroup( const QString &group )
1907{ 2005{
1908 d->groupStack.push( group ); 2006 d->groupStack.push( group );
1909 d->groupDirty = TRUE; 2007 d->groupDirty = TRUE;
1910} 2008}
1911 2009
1912/*! 2010/*!
1913 Undo previous calls to beginGroup(). Note that a single beginGroup("a/b/c") is undone 2011 Undo previous calls to beginGroup(). Note that a single beginGroup("a/b/c") is undone
1914 by a single call to endGroup(). 2012 by a single call to endGroup().
2013
2014 \code
2015 QSettings settings;
2016 settings.beginGroup( "/MainWindow/Geometry" );
2017 // read values
2018 settings.endGroup();
2019 \endcode
1915*/ 2020*/
1916void QSettings::endGroup() 2021void QSettings::endGroup()
1917{ 2022{
1918 d->groupStack.pop(); 2023 d->groupStack.pop();
1919 d->groupDirty = TRUE; 2024 d->groupDirty = TRUE;
1920} 2025}
1921 2026
1922/*! 2027/*!
1923 Set the current key prefix to the empty string. 2028 Set the current key prefix to the empty string.
1924*/ 2029*/
1925void QSettings::resetGroup() 2030void QSettings::resetGroup()
1926{ 2031{
1927 d->groupStack.clear(); 2032 d->groupStack.clear();
1928 d->groupDirty = FALSE; 2033 d->groupDirty = FALSE;
1929 d->groupPrefix = QString::null; 2034 d->groupPrefix = QString::null;
1930} 2035}
1931 2036
1932/*! 2037/*!
1933 Returns the current key prefix, or a null string if there is no key prefix set. 2038 Returns the current key prefix, or a null string if there is no key prefix set.
1934 2039
1935 \sa beginGroup(); 2040 \sa beginGroup();
1936*/ 2041*/
1937QString QSettings::group() const 2042QString QSettings::group() const
1938{ 2043{
1939 if ( d->groupDirty ) { 2044 if ( d->groupDirty ) {
1940 d->groupDirty = FALSE; 2045 d->groupDirty = FALSE;
1941 d->groupPrefix = QString::null; 2046 d->groupPrefix = QString::null;
1942 2047
1943 QValueStack<QString>::Iterator it = d->groupStack.begin(); 2048 QValueStack<QString>::Iterator it = d->groupStack.begin();
1944 while ( it != d->groupStack.end() ) { 2049 while ( it != d->groupStack.end() ) {
1945 QString group = *it; 2050 QString group = *it;
1946 ++it; 2051 ++it;
1947 if ( group[0] != '/' ) 2052 if ( group[0] != '/' )
1948 group = "/" + group; 2053 group.prepend( "/" );
1949 d->groupPrefix += group; 2054 d->groupPrefix += group;
1950 } 2055 }
1951 } 2056 }
1952 return d->groupPrefix; 2057 return d->groupPrefix;
1953} 2058}
1954 2059
1955#endif 2060#endif