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.cpp365
1 files changed, 188 insertions, 177 deletions
diff --git a/qmake/tools/qsettings.cpp b/qmake/tools/qsettings.cpp
index 35fc039..598e94b 100644
--- a/qmake/tools/qsettings.cpp
+++ b/qmake/tools/qsettings.cpp
@@ -1,32 +1,32 @@
1/**************************************************************************** 1/****************************************************************************
2** $Id$ 2**
3** 3**
4** Implementation of QSettings class 4** Implementation of QSettings class
5** 5**
6** Created : 000626 6** Created : 000626
7** 7**
8** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 8** Copyright (C) 2000-2003 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.
31** See http://www.trolltech.com/gpl/ for GPL licensing information. 31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32** 32**
@@ -39,207 +39,213 @@
39 39
40// POSIX Large File Support redefines open -> open64 40// POSIX Large File Support redefines open -> open64
41static inline int qt_open( const char *pathname, int flags, mode_t mode ) 41static inline int qt_open( const char *pathname, int flags, mode_t mode )
42{ return ::open( pathname, flags, mode ); } 42{ return ::open( pathname, flags, mode ); }
43#if defined(open) 43#if defined(open)
44# undef open 44# undef open
45#endif 45#endif
46 46
47// POSIX Large File Support redefines truncate -> truncate64 47// POSIX Large File Support redefines truncate -> truncate64
48#if defined(truncate) 48#if defined(truncate)
49# undef truncate 49# undef truncate
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#ifndef NO_ERRNO_H
63#include <errno.h> 64#include <errno.h>
65#endif
64 66
65/*! 67/*!
66 \class QSettings 68 \class QSettings
67 \brief The QSettings class provides persistent platform-independent application settings. 69 \brief The QSettings class provides persistent platform-independent application settings.
68 70
69 \ingroup io 71 \ingroup io
70 \ingroup misc 72 \ingroup misc
71 \mainclass 73 \mainclass
72 74
73 On Unix systems, QSettings uses text files to store settings. On Windows 75 On Unix systems, QSettings uses text files to store settings. On Windows
74 systems, QSettings uses the system registry. On Mac OS X, QSettings uses 76 systems, QSettings uses the system registry. On Mac OS X, QSettings uses
75 the Carbon preferences API. 77 the Carbon preferences API.
76 78
77 Each setting comprises an identifying key and the data associated with 79 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 80 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 81 subkeys. A subkey is a slash, '/', followed by one or more unicode
80 characters (excluding slashes, newlines, carriage returns and equals, 82 characters (excluding slashes, newlines, carriage returns and equals,
81 '=', signs). The associated data, called the entry or value, may be a 83 '=', 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 84 boolean, an integer, a double, a string or a list of strings. Entry
83 strings may contain any unicode characters. 85 strings may contain any unicode characters.
84 86
85 If you want to save and restore the entire desktop's settings, i.e. 87 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 88 which applications are running, use QSettings to save the settings
87 for each individual application and QSessionManager to save the 89 for each individual application and QSessionManager to save the
88 desktop's session. 90 desktop's session.
89 91
90 Example settings: 92 Example settings:
91 \code 93 \code
92 /MyCompany/MyApplication/background color 94 /MyCompany/MyApplication/background color
93 /MyCompany/MyApplication/foreground color 95 /MyCompany/MyApplication/foreground color
94 /MyCompany/MyApplication/geometry/x 96 /MyCompany/MyApplication/geometry/x
95 /MyCompany/MyApplication/geometry/y 97 /MyCompany/MyApplication/geometry/y
96 /MyCompany/MyApplication/geometry/width 98 /MyCompany/MyApplication/geometry/width
97 /MyCompany/MyApplication/geometry/height 99 /MyCompany/MyApplication/geometry/height
98 /MyCompany/MyApplication/recent files/1 100 /MyCompany/MyApplication/recent files/1
99 /MyCompany/MyApplication/recent files/2 101 /MyCompany/MyApplication/recent files/2
100 /MyCompany/MyApplication/recent files/3 102 /MyCompany/MyApplication/recent files/3
101 \endcode 103 \endcode
102 Each line above is a complete key, made up of subkeys. 104 Each line above is a complete key, made up of subkeys.
103 105
104 A typical usage pattern for reading application startup: 106 A typical usage pattern for reading settings at application
107 startup:
105 \code 108 \code
106 QSettings settings; 109 QSettings settings;
107 settings.setPath( "MyCompany.com", "MyApplication" ); 110 settings.setPath( "MyCompany.com", "MyApplication" );
108 111
109 QString bgColor = settings.readEntry( "/colors/background", "white" ); 112 QString bgColor = settings.readEntry( "/colors/background", "white" );
110 int width = settings.readNumEntry( "/geometry/width", 640 ); 113 int width = settings.readNumEntry( "/geometry/width", 640 );
111 // ... 114 // ...
112 \endcode 115 \endcode
113 116
114 A typical usage pattern for application exit or 'save preferences': 117 A typical usage pattern for saving settings at application exit or
118 'save preferences':
115 \code 119 \code
116 QSettings settings; 120 QSettings settings;
117 settings.setPath( "MyCompany.com", "MyApplication" ); 121 settings.setPath( "MyCompany.com", "MyApplication" );
118 122
119 settings.writeEntry( "/colors/background", bgColor ); 123 settings.writeEntry( "/colors/background", bgColor );
120 settings.writeEntry( "/geometry/width", width ); 124 settings.writeEntry( "/geometry/width", width );
121 // ... 125 // ...
122 \endcode 126 \endcode
123 127
124 QSettings can build a key prefix that is prepended to all keys. To 128 A key prefix can be prepended to all keys using beginGroup(). The
125 build the key prefix, use beginGroup() and endGroup(). 129 application of the prefix is stopped using endGroup(). For
130 example:
126 \code 131 \code
127 QSettings settings; 132 QSettings settings;
128 133
129 settings.beginGroup( "/MainWindow" ); 134 settings.beginGroup( "/MainWindow" );
130 settings.beginGroup( "/Geometry" ); 135 settings.beginGroup( "/Geometry" );
131 int x = settings.readEntry( "/x" ); 136 int x = settings.readEntry( "/x" );
132 // ... 137 // ...
133 settings.endGroup(); 138 settings.endGroup();
134 settings.beginGroup( "/Toolbars" ); 139 settings.beginGroup( "/Toolbars" );
135 // ... 140 // ...
136 settings.endGroup(); 141 settings.endGroup();
137 settings.endGroup(); 142 settings.endGroup();
138 \endcode 143 \endcode
139 144
140 You can get a list of entry-holding keys by calling entryList(), and 145 You can get a list of entry-holding keys by calling entryList(), and
141 a list of key-holding keys using subkeyList(). 146 a list of key-holding keys using subkeyList().
142 147
143 \code 148 \code
144 QStringList keys = entryList( "/MyApplication" ); 149 QStringList keys = entryList( "/MyApplication" );
145 // keys contains 'background color' and 'foreground color'. 150 // keys contains 'background color' and 'foreground color'.
146 151
147 QStringList keys = entryList( "/MyApplication/recent files" ); 152 QStringList keys = entryList( "/MyApplication/recent files" );
148 // keys contains '1', '2' and '3'. 153 // keys contains '1', '2' and '3'.
149 154
150 QStringList subkeys = subkeyList( "/MyApplication" ); 155 QStringList subkeys = subkeyList( "/MyApplication" );
151 // subkeys contains 'geometry' and 'recent files' 156 // subkeys contains 'geometry' and 'recent files'
152 157
153 QStringList subkeys = subkeyList( "/MyApplication/recent files" ); 158 QStringList subkeys = subkeyList( "/MyApplication/recent files" );
154 // subkeys is empty. 159 // subkeys is empty.
155 \endcode 160 \endcode
156 161
157 Since settings for Windows are stored in the registry there are size 162 Since settings for Windows are stored in the registry there are
158 limits as follows: 163 some size limitations as follows:
159 \list 164 \list
160 \i A subkey may not exceed 255 characters. 165 \i A subkey may not exceed 255 characters.
161 \i An entry's value may not exceed 16,300 characters. 166 \i An entry's value may not exceed 16,300 characters.
162 \i All the values of a key (for example, all the 'recent files' 167 \i All the values of a key (for example, all the 'recent files'
163 subkeys values), may not exceed 65,535 characters. 168 subkeys values), may not exceed 65,535 characters.
164 \endlist 169 \endlist
165 170
166 These limitations are not enforced on Unix or Mac OS X. 171 These limitations are not enforced on Unix or Mac OS X.
167 172
168 If you wish to use a different search path call insertSearchPath() 173 \warning Creating multiple, simultaneous instances of QSettings writing
169 as often as necessary to add your preferred paths. Call 174 to a text file may lead to data loss! This is a known issue which will
170 removeSearchPath() to remove any unwanted paths. 175 be fixed in a future release of Qt.
171 176
172 \section1 Notes for Mac OS X Applications 177 \section1 Notes for Mac OS X Applications
173 178
174 Internal to the CFPreferences API it is not defined (for Mac OS 9 179 The location where settings are stored is not formally defined by
175 support) where the settings will ultimitely be stored. However, at the 180 the CFPreferences API.
176 time of this writing the settings will be stored (either on a global or 181
177 user basis, preferring locally) into a plist file in 182 At the time of writing settings are stored (either on a global or
178 $ROOT/System/Library/Preferences (in XML format). QSettings will create 183 user basis, preferring locally) into a plist file in \c
179 an appropriate plist file (com.<first group name>.plist) out of the 184 $ROOT/System/Library/Preferences (in XML format). QSettings will
180 full path to a key. 185 create an appropriate plist file (\c{com.<first group name>.plist})
186 out of the full path to a key.
181 187
182 For further information on CFPreferences see also 188 For further information on CFPreferences see
183 \link http://developer.apple.com/techpubs/macosx/CoreFoundation/PreferenceServices/preferenceservices_carbon.html 189 \link http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFPreferences/index.html
184 Apple's Specifications\endlink 190 Apple's Specifications\endlink
185 191
186 \section1 Notes for Unix Applications 192 \section1 Notes for Unix Applications
187 193
188 There is no universally accepted place for storing application 194 There is no universally accepted place for storing application
189 settings under Unix. In the examples the settings file will be 195 settings under Unix. In the examples the settings file will be
190 searched for in the following directories: 196 searched for in the following directories:
191 \list 1 197 \list 1
192 \i INSTALL/etc/settings 198 \i \c SYSCONF - the default value is \c INSTALL/etc/settings
193 \i /opt/MyCompany/share/etc 199 \i \c /opt/MyCompany/share/etc
194 \i /opt/MyCompany/share/MyApplication/etc 200 \i \c /opt/MyCompany/share/MyApplication/etc
195 \i $HOME/.qt 201 \i \c $HOME/.qt
196 \endlist 202 \endlist
197 When reading settings the files are searched in the order shown 203 When reading settings the files are searched in the order shown
198 above, with later settings overriding earlier settings. Files for 204 above, with later settings overriding earlier settings. Files for
199 which the user doesn't have read permission are ignored. When saving 205 which the user doesn't have read permission are ignored. When saving
200 settings QSettings works in the order shown above, writing 206 settings QSettings works in the order shown above, writing
201 to the first settings file for which the user has write permission. 207 to the first settings file for which the user has write permission.
202 (\c INSTALL is the directory where Qt was installed. This can be 208 (\c INSTALL is the directory where Qt was installed. This can be
203 modified by using the configure script's -prefix argument ) 209 modified by using the configure script's -prefix argument )
204 210
205 If you want to put the settings in a particular place in the 211 If you want to put the settings in a particular place in the
206 filesystem you could do this: 212 filesystem you could do this:
207 \code 213 \code
208 settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share" ); 214 settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share" );
209 \endcode 215 \endcode
210 216
211 But in practice you may prefer not to use a search path for Unix. 217 But in practice you may prefer not to use a search path for Unix.
212 For example the following code: 218 For example the following code:
213 \code 219 \code
214 settings.writeEntry( "/MyApplication/geometry/width", width ); 220 settings.writeEntry( "/MyApplication/geometry/width", width );
215 \endcode 221 \endcode
216 will end up writing the "geometry/width" setting to the file 222 will end up writing the "geometry/width" setting to the file
217 \c{$HOME/.qt/myapplicationrc} (assuming that the application is 223 \c{$HOME/.qt/myapplicationrc} (assuming that the application is
218 being run by an ordinary user, i.e. not by root). 224 being run by an ordinary user, i.e. not by root).
219 225
220 For cross-platform applications you should ensure that the Windows 226 For cross-platform applications you should ensure that the
221 size limitations are not exceeded. 227 \link #sizelimit Windows size limitations \endlink are not exceeded.
222*/ 228*/
223 229
224/*! 230/*!
225 \enum QSettings::System 231 \enum QSettings::System
226 232
227 \value Mac Macintosh execution environments 233 \value Mac Macintosh execution environments
228 \value Unix Mac OS X, Unix, Linux and Unix-like execution environments 234 \value Unix Mac OS X, Unix, Linux and Unix-like execution environments
229 \value Windows Windows execution environments 235 \value Windows Windows execution environments
230*/ 236*/
231 237
232/*! 238/*!
233 \enum QSettings::Format 239 \enum QSettings::Format
234 240
235 \value Native Store the settings in a platform dependent location 241 \value Native Store the settings in a platform dependent location
236 \value Ini Store the settings in a text file 242 \value Ini Store the settings in a text file
237*/ 243*/
238 244
239/*! 245/*!
240 \enum QSettings::Scope 246 \enum QSettings::Scope
241 247
242 \value Global Save settings as global as possible 248 \value Global Save settings as global as possible
243 \value User Save settings in user space 249 \value User Save settings in user space
244*/ 250*/
245 251
@@ -289,143 +295,108 @@ static HANDLE openlock( const QString &name, int type )
289 return fd; 295 return fd;
290} 296}
291 297
292/* 298/*
293 Closes the lock file specified by fd. fd is the file descriptor 299 Closes the lock file specified by fd. fd is the file descriptor
294 returned by the openlock() function. 300 returned by the openlock() function.
295*/ 301*/
296static void closelock( HANDLE fd ) 302static void closelock( HANDLE fd )
297{ 303{
298 if ( fd < 0 ) { 304 if ( fd < 0 ) {
299 // the lock file is not open 305 // the lock file is not open
300 return; 306 return;
301 } 307 }
302 308
303 struct flock fl; 309 struct flock fl;
304 fl.l_type = F_UNLCK; 310 fl.l_type = F_UNLCK;
305 fl.l_whence = SEEK_SET; 311 fl.l_whence = SEEK_SET;
306 fl.l_start = 0; 312 fl.l_start = 0;
307 fl.l_len = 0; 313 fl.l_len = 0;
308 // ignore the return value, so that the unlock fails silently 314 // ignore the return value, so that the unlock fails silently
309 (void) fcntl( fd, F_SETLKW, &fl ); 315 (void) fcntl( fd, F_SETLKW, &fl );
310 316
311 close( fd ); 317 close( fd );
312} 318}
313#elif defined(Q_WS_WIN)
314#define Q_LOCKREAD 1
315#define Q_LOCKWRITE 2
316
317static HANDLE openlock( const QString &name, int /*type*/ )
318{
319 if ( !QFile::exists( name ) )
320 return 0;
321
322 return 0;
323
324 HANDLE fd = 0;
325
326 QT_WA( {
327 fd = CreateFileW( (TCHAR*)name.ucs2(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
328 } , {
329 fd = CreateFileA( name.local8Bit(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
330 } );
331
332 if ( !LockFile( fd, 0, 0, (DWORD)-1, (DWORD)-1 ) ) { // ### (DWORD)-1 ???
333#ifdef QT_CHECK_STATE
334 qWarning( "QSettings: openlock failed!" );
335#endif
336 }
337 return fd;
338}
339
340static void closelock( HANDLE fd )
341{
342 if ( !fd )
343 return;
344
345 if ( !UnlockFile( fd, 0, 0, (DWORD)-1, (DWORD)-1 ) ) { // ### (DWORD)-1 ???
346#ifdef QT_CHECK_STATE
347 qWarning( "QSettings: closelock failed!");
348#endif
349 }
350 CloseHandle( fd );
351}
352#endif 319#endif
353 320
354 321
355QSettingsGroup::QSettingsGroup() 322QSettingsGroup::QSettingsGroup()
356 : modified(FALSE) 323 : modified(FALSE)
357{ 324{
358} 325}
359 326
360 327
361 328
362 329
363void QSettingsHeading::read(const QString &filename) 330void QSettingsHeading::read(const QString &filename)
364{ 331{
365 if (! QFileInfo(filename).exists()) 332 if (! QFileInfo(filename).exists())
366 return; 333 return;
367 334
335#ifndef Q_WS_WIN
368 HANDLE lockfd = openlock( filename, Q_LOCKREAD ); 336 HANDLE lockfd = openlock( filename, Q_LOCKREAD );
337#endif
369 338
370 QFile file(filename); 339 QFile file(filename);
371 if (! file.open(IO_ReadOnly)) { 340 if (! file.open(IO_ReadOnly)) {
372#if defined(QT_CHECK_STATE) 341#if defined(QT_CHECK_STATE)
373 qWarning("QSettings: failed to open file '%s'", filename.latin1()); 342 qWarning("QSettings: failed to open file '%s'", filename.latin1());
374#endif 343#endif
375 return; 344 return;
376 } 345 }
377 346
378 git = end(); 347 git = end();
379 348
380 QTextStream stream(&file); 349 QTextStream stream(&file);
381 stream.setEncoding(QTextStream::UnicodeUTF8); 350 stream.setEncoding(QTextStream::UnicodeUTF8);
382 while (! stream.atEnd()) 351 while (! stream.atEnd())
383 parseLine(stream); 352 parseLine(stream);
384 353
385 git = end(); 354 git = end();
386 355
387 file.close(); 356 file.close();
388 357
358#ifndef Q_WS_WIN
389 closelock( lockfd ); 359 closelock( lockfd );
360#endif
390} 361}
391 362
392 363
393void QSettingsHeading::parseLine(QTextStream &stream) 364void QSettingsHeading::parseLine(QTextStream &stream)
394{ 365{
395 QString line = stream.readLine(); 366 QString line = stream.readLine();
396 if (line.isEmpty()) 367 if (line.isEmpty())
397 // empty line... we'll allow it 368 // empty line... we'll allow it
398 return; 369 return;
399 370
400 if (line[0] == QChar('#')) 371 if (line[0] == QChar('#'))
401 // commented line 372 // commented line
402 return; 373 return;
403 374
404 if (line[0] == QChar('[')) { 375 if (line[0] == QChar('[')) {
405 QString gname = line; 376 QString gname = line;
406 377
407 gname = gname.remove(0, 1); 378 gname = gname.remove((uint)0, 1);
408 if (gname[(int)gname.length() - 1] == QChar(']')) 379 if (gname[(int)gname.length() - 1] == QChar(']'))
409 gname = gname.remove(gname.length() - 1, 1); 380 gname = gname.remove(gname.length() - 1, 1);
410 381
411 git = find(gname); 382 git = find(gname);
412 if (git == end()) 383 if (git == end())
413 git = replace(gname, QSettingsGroup()); 384 git = replace(gname, QSettingsGroup());
414 } else { 385 } else {
415 if (git == end()) { 386 if (git == end()) {
416#if defined(QT_CHECK_STATE) 387#if defined(QT_CHECK_STATE)
417 qWarning("QSettings: line '%s' out of group", line.latin1()); 388 qWarning("QSettings: line '%s' out of group", line.latin1());
418#endif 389#endif
419 return; 390 return;
420 } 391 }
421 392
422 int i = line.find('='); 393 int i = line.find('=');
423 if (i == -1) { 394 if (i == -1) {
424#if defined(QT_CHECK_STATE) 395#if defined(QT_CHECK_STATE)
425 qWarning("QSettings: malformed line '%s' in group '%s'", 396 qWarning("QSettings: malformed line '%s' in group '%s'",
426 line.latin1(), git.key().latin1()); 397 line.latin1(), git.key().latin1());
427#endif 398#endif
428 return; 399 return;
429 } else { 400 } else {
430 QString key, value; 401 QString key, value;
431 key = line.left(i); 402 key = line.left(i);
@@ -505,53 +476,49 @@ QSettingsPrivate::QSettingsPrivate( QSettings::Format format )
505 library.setAutoUnload( FALSE ); 476 library.setAutoUnload( FALSE );
506 QT_WA( { 477 QT_WA( {
507 typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL); 478 typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL);
508 GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathW" ); 479 GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathW" );
509 if ( SHGetSpecialFolderPath ) { 480 if ( SHGetSpecialFolderPath ) {
510 TCHAR path[MAX_PATH]; 481 TCHAR path[MAX_PATH];
511 SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); 482 SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE );
512 appSettings = QString::fromUcs2( (ushort*)path ); 483 appSettings = QString::fromUcs2( (ushort*)path );
513 SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); 484 SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE );
514 defPath = QString::fromUcs2( (ushort*)path ); 485 defPath = QString::fromUcs2( (ushort*)path );
515 } 486 }
516 } , { 487 } , {
517 typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL); 488 typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL);
518 GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathA" ); 489 GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathA" );
519 if ( SHGetSpecialFolderPath ) { 490 if ( SHGetSpecialFolderPath ) {
520 char path[MAX_PATH]; 491 char path[MAX_PATH];
521 SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); 492 SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE );
522 appSettings = QString::fromLocal8Bit( path ); 493 appSettings = QString::fromLocal8Bit( path );
523 SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); 494 SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE );
524 defPath = QString::fromLocal8Bit( path ); 495 defPath = QString::fromLocal8Bit( path );
525 } 496 }
526 } ); 497 } );
527#endif // Q_OS_TEMP 498#endif // Q_OS_TEMP
528#else 499#else
529// for now 500 defPath = qInstallPathSysconf();
530#define QSETTINGS_DEFAULT_PATH_SUFFIX "/etc/settings"
531
532 defPath = qInstallPath();
533 defPath += QSETTINGS_DEFAULT_PATH_SUFFIX;
534#endif 501#endif
535 QDir dir(appSettings); 502 QDir dir(appSettings);
536 if (! dir.exists()) { 503 if (! dir.exists()) {
537 if (! dir.mkdir(dir.path())) 504 if (! dir.mkdir(dir.path()))
538#if defined(QT_CHECK_STATE) 505#if defined(QT_CHECK_STATE)
539 qWarning("QSettings: error creating %s", dir.path().latin1()); 506 qWarning("QSettings: error creating %s", dir.path().latin1());
540#else 507#else
541 ; 508 ;
542#endif 509#endif
543 } 510 }
544 511
545 if ( !!defPath ) 512 if ( !!defPath )
546 searchPaths.append(defPath); 513 searchPaths.append(defPath);
547 searchPaths.append(dir.path()); 514 searchPaths.append(dir.path());
548} 515}
549 516
550QSettingsPrivate::~QSettingsPrivate() 517QSettingsPrivate::~QSettingsPrivate()
551{ 518{
552} 519}
553 520
554QSettingsGroup QSettingsPrivate::readGroup() 521QSettingsGroup QSettingsPrivate::readGroup()
555{ 522{
556 QSettingsHeading hd; 523 QSettingsHeading hd;
557 QSettingsGroup grp; 524 QSettingsGroup grp;
@@ -680,163 +647,172 @@ void QSettingsPrivate::writeGroup(const QString &key, const QString &value)
680} 647}
681 648
682 649
683QDateTime QSettingsPrivate::modificationTime() 650QDateTime QSettingsPrivate::modificationTime()
684{ 651{
685 QSettingsHeading hd = headings[heading]; 652 QSettingsHeading hd = headings[heading];
686 QSettingsGroup grp = hd[group]; 653 QSettingsGroup grp = hd[group];
687 654
688 QDateTime datetime; 655 QDateTime datetime;
689 656
690 QStringList::Iterator it = searchPaths.begin(); 657 QStringList::Iterator it = searchPaths.begin();
691 if ( !globalScope ) 658 if ( !globalScope )
692 ++it; 659 ++it;
693 while (it != searchPaths.end()) { 660 while (it != searchPaths.end()) {
694 QFileInfo fi((*it++) + "/" + heading + "rc"); 661 QFileInfo fi((*it++) + "/" + heading + "rc");
695 if (fi.exists() && fi.lastModified() > datetime) 662 if (fi.exists() && fi.lastModified() > datetime)
696 datetime = fi.lastModified(); 663 datetime = fi.lastModified();
697 } 664 }
698 665
699 return datetime; 666 return datetime;
700} 667}
701 668
702bool qt_verify_key( const QString &key ) 669bool qt_verify_key( const QString &key )
703{ 670{
704 if ( key.isEmpty() || key[0] != '/' || key.contains( QRegExp("[=\\\\r\\\\n" ) ) ) 671 if ( key.isEmpty() || key[0] != '/' || key.contains( QRegExp("[=\\r\\n]" ) ) )
705 return FALSE; 672 return FALSE;
706 return TRUE; 673 return TRUE;
707} 674}
708 675
709static inline QString groupKey( const QString &group, const QString &key ) 676static QString groupKey( const QString &group, const QString &key )
710{ 677{
678 QString grp_key;
711 if ( group.isEmpty() || ( group.length() == 1 && group[0] == '/' ) ) { 679 if ( group.isEmpty() || ( group.length() == 1 && group[0] == '/' ) ) {
712 // group is empty, or it contains a single '/', so we just return the key 680 // group is empty, or it contains a single '/', so we just return the key
713 if ( key.startsWith( "/" ) ) 681 if ( key.startsWith( "/" ) )
714 return key; 682 grp_key = key;
715 return "/" + key; 683 else
684 grp_key = "/" + key;
716 } else if ( group.endsWith( "/" ) || key.startsWith( "/" ) ) { 685 } else if ( group.endsWith( "/" ) || key.startsWith( "/" ) ) {
717 return group + key; 686 grp_key = group + key;
687 } else {
688 grp_key = group + "/" + key;
718 } 689 }
719 return group + "/" + key; 690 return grp_key;
720} 691}
721 692
722/*! 693/*!
723 Inserts \a path into the settings search path. The semantics of \a 694 Inserts \a path into the settings search path. The semantics of \a
724 path depends on the system \a s. 695 path depends on the system \a s. It is usually easier and better to
696 use setPath() instead of this function.
725 697
726 When \a s is \e Windows and the execution environment is \e not 698 When \a s is \e Windows and the execution environment is \e not
727 Windows the function does nothing. Similarly when \a s is \e Unix and 699 Windows the function does nothing. Similarly when \a s is \e Unix and
728 the execution environment is \e not Unix the function does nothing. 700 the execution environment is \e not Unix the function does nothing.
729 701
730 When \a s is \e Windows, and the execution environment is Windows, the 702 When \a s is \e Windows, and the execution environment is Windows, the
731 search path list will be used as the first subfolder of the "Software" 703 search path list will be used as the first subfolder of the "Software"
732 folder in the registry. 704 folder in the registry.
733 705
734 When reading settings the folders are searched forwards from the 706 When reading settings the folders are searched forwards from the
735 first folder (listed below) to the last, returning the first 707 first folder (listed below) to the last, returning the first
736 settings found, and ignoring any folders for which the user doesn't 708 settings found, and ignoring any folders for which the user doesn't
737 have read permission. 709 have read permission.
738 \list 1 710 \list 1
739 \i HKEY_CURRENT_USER/Software/MyCompany/MyApplication 711 \i HKEY_CURRENT_USER/Software/MyCompany/MyApplication
740 \i HKEY_LOCAL_MACHINE/Software/MyCompany/MyApplication 712 \i HKEY_LOCAL_MACHINE/Software/MyCompany/MyApplication
741 \i HKEY_CURRENT_USER/Software/MyApplication 713 \i HKEY_CURRENT_USER/Software/MyApplication
742 \i HKEY_LOCAL_MACHINE/Software/MyApplication 714 \i HKEY_LOCAL_MACHINE/Software/MyApplication
743 \endlist 715 \endlist
744 716
745 \code 717 \code
746 QSettings settings; 718 QSettings settings;
747 settings.insertSearchPath( QSettings::Windows, "/MyCompany" ); 719 settings.insertSearchPath( QSettings::Windows, "/MyCompany" );
748 settings.writeEntry( "/MyApplication/Tip of the day", TRUE ); 720 settings.writeEntry( "/MyApplication/Tip of the day", TRUE );
749 \endcode 721 \endcode
750 The code above will write the subkey "Tip of the day" into the \e 722 The code above will write the subkey "Tip of the day" into the \e
751 first of the registry folders listed below that is found and for 723 first of the registry folders listed below that is found and for
752 which the user has write permission. 724 which the user has write permission.
753 \list 1 725 \list 1
754 \i HKEY_LOCAL_MACHINE/Software/MyCompany/MyApplication 726 \i HKEY_LOCAL_MACHINE/Software/MyCompany/MyApplication
755 \i HKEY_CURRENT_USER/Software/MyCompany/MyApplication 727 \i HKEY_CURRENT_USER/Software/MyCompany/MyApplication
756 \i HKEY_LOCAL_MACHINE/Software/MyApplication 728 \i HKEY_LOCAL_MACHINE/Software/MyApplication
757 \i HKEY_CURRENT_USER/Software/MyApplication 729 \i HKEY_CURRENT_USER/Software/MyApplication
758 \endlist 730 \endlist
759 If a setting is found in the HKEY_CURRENT_USER space, this setting 731 If a setting is found in the HKEY_CURRENT_USER space, this setting
760 is overwritten independently of write permissions in the 732 is overwritten independently of write permissions in the
761 HKEY_LOCAL_MACHINE space. 733 HKEY_LOCAL_MACHINE space.
762 734
763 When \a s is \e Unix, and the execution environment is Unix, the 735 When \a s is \e Unix, and the execution environment is Unix, the
764 search path list will be used when trying to determine a suitable 736 search path list will be used when trying to determine a suitable
765 filename for reading and writing settings files. By default, there are 737 filename for reading and writing settings files. By default, there are
766 two entries in the search path: 738 two entries in the search path:
767 739
768 \list 1 740 \list 1
769 \i INSTALL/etc - where \c INSTALL is the directory where Qt was installed. 741 \i \c SYSCONF - where \c SYSCONF is a directory specified when
770 \i $HOME/.qt/ - where \c $HOME is the user's home directory. 742 configuring Qt; by default it is INSTALL/etc/settings.
743 \i \c $HOME/.qt/ - where \c $HOME is the user's home directory.
771 \endlist 744 \endlist
772 745
773 All insertions into the search path will go before $HOME/.qt/. 746 All insertions into the search path will go before $HOME/.qt/.
774 For example: 747 For example:
775 \code 748 \code
776 QSettings settings; 749 QSettings settings;
777 settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share/etc" ); 750 settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share/etc" );
778 settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share/MyApplication/etc" ); 751 settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share/MyApplication/etc" );
779 // ... 752 // ...
780 \endcode 753 \endcode
781 Will result in a search path of: 754 Will result in a search path of:
782 \list 1 755 \list 1
783 \i INSTALL/etc 756 \i SYSCONF
784 \i /opt/MyCompany/share/etc 757 \i /opt/MyCompany/share/etc
785 \i /opt/MyCompany/share/MyApplication/etc 758 \i /opt/MyCompany/share/MyApplication/etc
786 \i $HOME/.qt 759 \i $HOME/.qt
787 \endlist 760 \endlist
788 When reading settings the files are searched in the order shown 761 When reading settings the files are searched in the order shown
789 above, with later settings overriding earlier settings. Files for 762 above, with later settings overriding earlier settings. Files for
790 which the user doesn't have read permission are ignored. When saving 763 which the user doesn't have read permission are ignored. When saving
791 settings QSettings works in the order shown above, writing 764 settings QSettings works in the order shown above, writing
792 to the first settings file for which the user has write permission. 765 to the first settings file for which the user has write permission.
793 766
767 Note that paths in the file system are not created by this
768 function, so they must already exist to be useful.
769
794 Settings under Unix are stored in files whose names are based on the 770 Settings under Unix are stored in files whose names are based on the
795 first subkey of the key (not including the search path). The algorithm 771 first subkey of the key (not including the search path). The algorithm
796 for creating names is essentially: lowercase the first subkey, replace 772 for creating names is essentially: lowercase the first subkey, replace
797 spaces with underscores and add 'rc', e.g. 773 spaces with underscores and add 'rc', e.g.
798 <tt>/MyCompany/MyApplication/background color</tt> will be stored in 774 <tt>/MyCompany/MyApplication/background color</tt> will be stored in
799 <tt>myapplicationrc</tt> (assuming that <tt>/MyCompany</tt> is part of 775 <tt>myapplicationrc</tt> (assuming that <tt>/MyCompany</tt> is part of
800 the search path). 776 the search path).
801 777
802 \sa removeSearchPath() 778 \sa removeSearchPath()
803 779
804*/ 780*/
805void QSettings::insertSearchPath( System s, const QString &path) 781void QSettings::insertSearchPath( System s, const QString &path)
806{ 782{
807#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 783#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
808 if ( d->sysd ) { 784 if ( d->sysd ) {
809 d->sysInsertSearchPath( s, path ); 785 d->sysInsertSearchPath( s, path );
810 return; 786 return;
811 } 787 }
812#endif 788#endif
813 789
814#if !defined(Q_WS_WIN) 790#if !defined(Q_WS_WIN)
815 if ( s == Windows ) 791 if ( s == Windows )
816 return; 792 return;
817#endif 793#endif
818#if !defined(Q_WS_WIN) 794#if !defined(Q_OS_MAC)
819 if ( s == Mac ) 795 if ( s == Mac )
820 return; 796 return;
821#endif 797#endif
822 798
823 if ( !qt_verify_key( path ) ) { 799 if ( !qt_verify_key( path ) ) {
824#if defined(QT_CHECK_STATE) 800#if defined(QT_CHECK_STATE)
825 qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() ); 801 qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() );
826#endif 802#endif
827 return; 803 return;
828 } 804 }
829 805
830#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 806#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
831 if ( d->sysd && s != Unix ) { 807 if ( d->sysd && s != Unix ) {
832#else 808#else
833 if ( s != Unix ) { 809 if ( s != Unix ) {
834#endif 810#endif
835#if !defined(QWS) && defined(Q_OS_MAC) 811#if !defined(QWS) && defined(Q_OS_MAC)
836 if(s != Mac) //mac is respected on the mac as well 812 if(s != Mac) //mac is respected on the mac as well
837#endif 813#endif
838 return; 814 return;
839 } 815 }
840 816
841 QString realPath = path; 817 QString realPath = path;
842#if defined(Q_WS_WIN) 818#if defined(Q_WS_WIN)
@@ -943,79 +919,93 @@ QSettings::~QSettings()
943} 919}
944 920
945 921
946/*! \internal 922/*! \internal
947 Writes all modifications to the settings to disk. If any errors are 923 Writes all modifications to the settings to disk. If any errors are
948 encountered, this function returns FALSE, otherwise it will return TRUE. 924 encountered, this function returns FALSE, otherwise it will return TRUE.
949*/ 925*/
950bool QSettings::sync() 926bool QSettings::sync()
951{ 927{
952#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 928#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
953 if ( d->sysd ) 929 if ( d->sysd )
954 return d->sysSync(); 930 return d->sysSync();
955#endif 931#endif
956 if (! d->modified) 932 if (! d->modified)
957 // fake success 933 // fake success
958 return TRUE; 934 return TRUE;
959 935
960 bool success = TRUE; 936 bool success = TRUE;
961 QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin(); 937 QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin();
962 938
963 while (it != d->headings.end()) { 939 while (it != d->headings.end()) {
964 // determine filename 940 // determine filename
965 QSettingsHeading hd(*it); 941 QSettingsHeading hd(*it);
966 QSettingsHeading::Iterator hdit = hd.begin(); 942 QSettingsHeading::Iterator hdit = hd.begin();
967 QFile file; 943 QString filename;
968 944
969 QStringList::Iterator pit = d->searchPaths.begin(); 945 QStringList::Iterator pit = d->searchPaths.begin();
970 if ( !d->globalScope ) 946 if ( !d->globalScope )
971 ++pit; 947 ++pit;
972 while (pit != d->searchPaths.end()) { 948 while (pit != d->searchPaths.end()) {
973 QString filebase = it.key().lower().replace(QRegExp("\\s+"), "_"); 949 QString filebase = it.key().lower().replace(QRegExp("\\s+"), "_");
974 QFileInfo di(*pit); 950 QFileInfo di(*pit);
951 if ( !di.exists() ) {
952 QDir dir;
953 dir.mkdir( *pit );
954 }
955
975 QFileInfo fi((*pit++) + "/" + filebase + "rc"); 956 QFileInfo fi((*pit++) + "/" + filebase + "rc");
976 957
977 if ((fi.exists() && fi.isFile() && fi.isWritable()) || 958 if ((fi.exists() && fi.isFile() && fi.isWritable()) ||
978 (! fi.exists() && di.isDir() && di.isWritable())) { 959 (! fi.exists() && di.isDir()
979 file.setName(fi.filePath()); 960#ifndef Q_WS_WIN
961 && di.isWritable()
962#else
963 && ((qWinVersion()&Qt::WV_NT_based) > Qt::WV_2000 || di.isWritable())
964#endif
965 )) {
966 filename = fi.filePath();
980 break; 967 break;
981 } 968 }
982 } 969 }
983 970
984 ++it; 971 ++it;
985 972
986 if ( file.name().isEmpty() ) { 973 if ( filename.isEmpty() ) {
987 974
988#ifdef QT_CHECK_STATE 975#ifdef QT_CHECK_STATE
989 qWarning("QSettings::sync: filename is null/empty"); 976 qWarning("QSettings::sync: filename is null/empty");
990#endif // QT_CHECK_STATE 977#endif // QT_CHECK_STATE
991 978
992 success = FALSE; 979 success = FALSE;
993 continue; 980 continue;
994 } 981 }
995 982
996 HANDLE lockfd = openlock( file.name(), Q_LOCKWRITE ); 983#ifndef Q_WS_WIN
984 HANDLE lockfd = openlock( filename, Q_LOCKWRITE );
985#endif
997 986
987 QFile file( filename + ".tmp" );
998 if (! file.open(IO_WriteOnly)) { 988 if (! file.open(IO_WriteOnly)) {
999 989
1000#ifdef QT_CHECK_STATE 990#ifdef QT_CHECK_STATE
1001 qWarning("QSettings::sync: failed to open '%s' for writing", 991 qWarning("QSettings::sync: failed to open '%s' for writing",
1002 file.name().latin1()); 992 file.name().latin1());
1003#endif // QT_CHECK_STATE 993#endif // QT_CHECK_STATE
1004 994
1005 success = FALSE; 995 success = FALSE;
1006 continue; 996 continue;
1007 } 997 }
1008 998
1009 // spew to file 999 // spew to file
1010 QTextStream stream(&file); 1000 QTextStream stream(&file);
1011 stream.setEncoding(QTextStream::UnicodeUTF8); 1001 stream.setEncoding(QTextStream::UnicodeUTF8);
1012 1002
1013 while (hdit != hd.end()) { 1003 while (hdit != hd.end()) {
1014 if ((*hdit).count() > 0) { 1004 if ((*hdit).count() > 0) {
1015 stream << "[" << hdit.key() << "]" << endl; 1005 stream << "[" << hdit.key() << "]" << endl;
1016 1006
1017 QSettingsGroup grp(*hdit); 1007 QSettingsGroup grp(*hdit);
1018 QSettingsGroup::Iterator grpit = grp.begin(); 1008 QSettingsGroup::Iterator grpit = grp.begin();
1019 1009
1020 while (grpit != grp.end()) { 1010 while (grpit != grp.end()) {
1021 QString v = grpit.data(); 1011 QString v = grpit.data();
@@ -1026,592 +1016,608 @@ bool QSettings::sync()
1026 v.replace("\n", "\\n"); // escape newlines 1016 v.replace("\n", "\\n"); // escape newlines
1027 } 1017 }
1028 1018
1029 stream << grpit.key() << "=" << v << endl; 1019 stream << grpit.key() << "=" << v << endl;
1030 ++grpit; 1020 ++grpit;
1031 } 1021 }
1032 1022
1033 stream << endl; 1023 stream << endl;
1034 } 1024 }
1035 1025
1036 ++hdit; 1026 ++hdit;
1037 } 1027 }
1038 1028
1039 if (file.status() != IO_Ok) { 1029 if (file.status() != IO_Ok) {
1040 1030
1041#ifdef QT_CHECK_STATE 1031#ifdef QT_CHECK_STATE
1042 qWarning("QSettings::sync: error at end of write"); 1032 qWarning("QSettings::sync: error at end of write");
1043#endif // QT_CHECK_STATE 1033#endif // QT_CHECK_STATE
1044 1034
1045 success = FALSE; 1035 success = FALSE;
1046 } 1036 }
1047 1037
1048 file.close(); 1038 file.close();
1049 1039
1040 if ( success ) {
1041 QDir dir( QFileInfo( file ).dir( TRUE ) );
1042 if ( dir.exists( filename ) && !dir.remove( filename ) ||
1043 !dir.rename( file.name(), filename, TRUE ) ) {
1044
1045#ifdef QT_CHECK_STATE
1046 qWarning( "QSettings::sync: error writing file '%s'",
1047 QFile::encodeName( filename ).data() );
1048#endif // QT_CHECK_STATE
1049
1050 success = FALSE;
1051 }
1052 }
1053
1054 // remove temporary file
1055 file.remove();
1056
1057#ifndef Q_WS_WIN
1050 closelock( lockfd ); 1058 closelock( lockfd );
1059#endif
1051 } 1060 }
1052 1061
1053 d->modified = FALSE; 1062 d->modified = FALSE;
1054 1063
1055 return success; 1064 return success;
1056} 1065}
1057 1066
1058 1067
1059/*! 1068/*!
1060 \fn bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) const 1069 \fn bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) const
1061 1070
1062 Reads the entry specified by \a key, and returns a bool, or the 1071 Reads the entry specified by \a key, and returns a bool, or the
1063 default value, \a def, if the entry couldn't be read. 1072 default value, \a def, if the entry couldn't be read.
1064 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE 1073 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE
1065 otherwise. 1074 otherwise.
1066 1075
1067 \sa readEntry(), readNumEntry(), readDoubleEntry(), writeEntry(), removeEntry() 1076 \sa readEntry(), readNumEntry(), readDoubleEntry(), writeEntry(), removeEntry()
1068*/ 1077*/
1069 1078
1070/*! 1079/*!
1071 \internal 1080 \internal
1072*/ 1081*/
1073bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) 1082bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok )
1074{ 1083{
1075 if ( !qt_verify_key( key ) ) { 1084 QString grp_key( groupKey( group(), key ) );
1085 if ( !qt_verify_key( grp_key ) ) {
1076#if defined(QT_CHECK_STATE) 1086#if defined(QT_CHECK_STATE)
1077 qWarning( "QSettings::readBoolEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1087 qWarning( "QSettings::readBoolEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1078#endif 1088#endif
1079 if ( ok ) 1089 if ( ok )
1080 *ok = FALSE; 1090 *ok = FALSE;
1081 1091
1082 return def; 1092 return def;
1083 } 1093 }
1084 1094
1085#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1095#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1086 if ( d->sysd ) 1096 if ( d->sysd )
1087 return d->sysReadBoolEntry( groupKey( group(), key ), def, ok ); 1097 return d->sysReadBoolEntry( grp_key, def, ok );
1088#endif 1098#endif
1089 1099
1090 QString value = readEntry( key, ( def ? "true" : "false" ), ok ); 1100 QString value = readEntry( key, ( def ? "true" : "false" ), ok );
1091 1101
1092 if (value.lower() == "true") 1102 if (value.lower() == "true")
1093 return TRUE; 1103 return TRUE;
1094 else if (value.lower() == "false") 1104 else if (value.lower() == "false")
1095 return FALSE; 1105 return FALSE;
1096 else if (value == "1") 1106 else if (value == "1")
1097 return TRUE; 1107 return TRUE;
1098 else if (value == "0") 1108 else if (value == "0")
1099 return FALSE; 1109 return FALSE;
1100 1110
1101 if (! value.isEmpty()) 1111 if (! value.isEmpty())
1102 qWarning("QSettings::readBoolEntry: '%s' is not 'true' or 'false'", 1112 qWarning("QSettings::readBoolEntry: '%s' is not 'true' or 'false'",
1103 value.latin1()); 1113 value.latin1());
1104 if ( ok ) 1114 if ( ok )
1105 *ok = FALSE; 1115 *ok = FALSE;
1106 return def; 1116 return def;
1107} 1117}
1108 1118
1109 1119
1110/*! 1120/*!
1111 \fn double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) const 1121 \fn double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) const
1112 1122
1113 Reads the entry specified by \a key, and returns a double, or the 1123 Reads the entry specified by \a key, and returns a double, or the
1114 default value, \a def, if the entry couldn't be read. 1124 default value, \a def, if the entry couldn't be read.
1115 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE 1125 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE
1116 otherwise. 1126 otherwise.
1117 1127
1118 \sa readEntry(), readNumEntry(), readBoolEntry(), writeEntry(), removeEntry() 1128 \sa readEntry(), readNumEntry(), readBoolEntry(), writeEntry(), removeEntry()
1119*/ 1129*/
1120 1130
1121/*! 1131/*!
1122 \internal 1132 \internal
1123*/ 1133*/
1124double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) 1134double QSettings::readDoubleEntry(const QString &key, double def, bool *ok )
1125{ 1135{
1126 if ( !qt_verify_key( key ) ) { 1136 QString grp_key( groupKey( group(), key ) );
1137 if ( !qt_verify_key( grp_key ) ) {
1127#if defined(QT_CHECK_STATE) 1138#if defined(QT_CHECK_STATE)
1128 qWarning( "QSettings::readDoubleEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1139 qWarning( "QSettings::readDoubleEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1129#endif 1140#endif
1130 if ( ok ) 1141 if ( ok )
1131 *ok = FALSE; 1142 *ok = FALSE;
1132 1143
1133 return def; 1144 return def;
1134 } 1145 }
1135 1146
1136#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1147#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1137 if ( d->sysd ) 1148 if ( d->sysd )
1138 return d->sysReadDoubleEntry( groupKey( group(), key ), def, ok ); 1149 return d->sysReadDoubleEntry( grp_key, def, ok );
1139#endif 1150#endif
1140 1151
1141 QString value = readEntry( key, QString::number(def), ok ); 1152 QString value = readEntry( key, QString::number(def), ok );
1142 bool conv_ok; 1153 bool conv_ok;
1143 double retval = value.toDouble( &conv_ok ); 1154 double retval = value.toDouble( &conv_ok );
1144 if ( conv_ok ) 1155 if ( conv_ok )
1145 return retval; 1156 return retval;
1146 if ( ! value.isEmpty() ) 1157 if ( ! value.isEmpty() )
1147 qWarning( "QSettings::readDoubleEntry: '%s' is not a number", 1158 qWarning( "QSettings::readDoubleEntry: '%s' is not a number",
1148 value.latin1() ); 1159 value.latin1() );
1149 if ( ok ) 1160 if ( ok )
1150 *ok = FALSE; 1161 *ok = FALSE;
1151 return def; 1162 return def;
1152} 1163}
1153 1164
1154 1165
1155/*! 1166/*!
1156 \fn int QSettings::readNumEntry(const QString &key, int def, bool *ok ) const 1167 \fn int QSettings::readNumEntry(const QString &key, int def, bool *ok ) const
1157 1168
1158 Reads the entry specified by \a key, and returns an integer, or the 1169 Reads the entry specified by \a key, and returns an integer, or the
1159 default value, \a def, if the entry couldn't be read. 1170 default value, \a def, if the entry couldn't be read.
1160 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE 1171 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE
1161 otherwise. 1172 otherwise.
1162 1173
1163 \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry() 1174 \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry()
1164*/ 1175*/
1165 1176
1166/*! 1177/*!
1167 \internal 1178 \internal
1168*/ 1179*/
1169int QSettings::readNumEntry(const QString &key, int def, bool *ok ) 1180int QSettings::readNumEntry(const QString &key, int def, bool *ok )
1170{ 1181{
1171 if ( !qt_verify_key( key ) ) { 1182 QString grp_key( groupKey( group(), key ) );
1183 if ( !qt_verify_key( grp_key ) ) {
1172#if defined(QT_CHECK_STATE) 1184#if defined(QT_CHECK_STATE)
1173 qWarning( "QSettings::readNumEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1185 qWarning( "QSettings::readNumEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1174#endif 1186#endif
1175 if ( ok ) 1187 if ( ok )
1176 *ok = FALSE; 1188 *ok = FALSE;
1177 return def; 1189 return def;
1178 } 1190 }
1179 1191
1180#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1192#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1181 if ( d->sysd ) 1193 if ( d->sysd )
1182 return d->sysReadNumEntry( groupKey( group(), key ), def, ok ); 1194 return d->sysReadNumEntry( grp_key, def, ok );
1183#endif 1195#endif
1184 1196
1185 QString value = readEntry( key, QString::number( def ), ok ); 1197 QString value = readEntry( key, QString::number( def ), ok );
1186 bool conv_ok; 1198 bool conv_ok;
1187 int retval = value.toInt( &conv_ok ); 1199 int retval = value.toInt( &conv_ok );
1188 if ( conv_ok ) 1200 if ( conv_ok )
1189 return retval; 1201 return retval;
1190 if ( ! value.isEmpty() ) 1202 if ( ! value.isEmpty() )
1191 qWarning( "QSettings::readNumEntry: '%s' is not a number", 1203 qWarning( "QSettings::readNumEntry: '%s' is not a number",
1192 value.latin1() ); 1204 value.latin1() );
1193 if ( ok ) 1205 if ( ok )
1194 *ok = FALSE; 1206 *ok = FALSE;
1195 return def; 1207 return def;
1196} 1208}
1197 1209
1198 1210
1199/*! 1211/*!
1200 \fn QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) const 1212 \fn QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) const
1201 1213
1202 Reads the entry specified by \a key, and returns a QString, or the 1214 Reads the entry specified by \a key, and returns a QString, or the
1203 default value, \a def, if the entry couldn't be read. 1215 default value, \a def, if the entry couldn't be read.
1204 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE 1216 If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE
1205 otherwise. 1217 otherwise.
1206 1218
1207 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry() 1219 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry()
1208*/ 1220*/
1209 1221
1210/*! 1222/*!
1211 \internal 1223 \internal
1212*/ 1224*/
1213QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) 1225QString QSettings::readEntry(const QString &key, const QString &def, bool *ok )
1214{ 1226{
1215 if ( !qt_verify_key( key ) ) { 1227 QString grp_key( groupKey( group(), key ) );
1228 if ( !qt_verify_key( grp_key ) ) {
1216#if defined(QT_CHECK_STATE) 1229#if defined(QT_CHECK_STATE)
1217 qWarning( "QSettings::readEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1230 qWarning( "QSettings::readEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1218#endif 1231#endif
1219 if ( ok ) 1232 if ( ok )
1220 *ok = FALSE; 1233 *ok = FALSE;
1221 1234
1222 return def; 1235 return def;
1223 } 1236 }
1224 1237
1225 QString theKey = groupKey( group(), key );
1226
1227#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1238#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1228 if ( d->sysd ) 1239 if ( d->sysd )
1229 return d->sysReadEntry( theKey, def, ok ); 1240 return d->sysReadEntry( grp_key, def, ok );
1230#endif 1241#endif
1231 1242
1232 if ( ok ) // no, everything is not ok 1243 if ( ok ) // no, everything is not ok
1233 *ok = FALSE; 1244 *ok = FALSE;
1234 1245
1235 QString realkey; 1246 QString realkey;
1236 1247
1237 if (theKey[0] == '/') { 1248 if (grp_key[0] == '/') {
1238 // parse our key 1249 // parse our key
1239 QStringList list(QStringList::split('/', theKey)); 1250 QStringList list(QStringList::split('/', grp_key));
1240 1251
1241 if (list.count() < 2) { 1252 if (list.count() < 2) {
1242#ifdef QT_CHECK_STATE 1253#ifdef QT_CHECK_STATE
1243 qWarning("QSettings::readEntry: invalid key '%s'", theKey.latin1()); 1254 qWarning("QSettings::readEntry: invalid key '%s'", grp_key.latin1());
1244#endif // QT_CHECK_STATE 1255#endif // QT_CHECK_STATE
1245 if ( ok ) 1256 if ( ok )
1246 *ok = FALSE; 1257 *ok = FALSE;
1247 return def; 1258 return def;
1248 } 1259 }
1249 1260
1250 if (list.count() == 2) { 1261 if (list.count() == 2) {
1251 d->heading = list[0]; 1262 d->heading = list[0];
1252 d->group = "General"; 1263 d->group = "General";
1253 realkey = list[1]; 1264 realkey = list[1];
1254 } else { 1265 } else {
1255 d->heading = list[0]; 1266 d->heading = list[0];
1256 d->group = list[1]; 1267 d->group = list[1];
1257 1268
1258 // remove the group from the list 1269 // remove the group from the list
1259 list.remove(list.at(1)); 1270 list.remove(list.at(1));
1260 // remove the heading from the list 1271 // remove the heading from the list
1261 list.remove(list.at(0)); 1272 list.remove(list.at(0));
1262 1273
1263 realkey = list.join("/"); 1274 realkey = list.join("/");
1264 } 1275 }
1265 } else 1276 } else {
1266 realkey = theKey; 1277 realkey = grp_key;
1278 }
1267 1279
1268 QSettingsGroup grp = d->readGroup(); 1280 QSettingsGroup grp = d->readGroup();
1269 QSettingsGroup::const_iterator it = grp.find( realkey ), end = grp.end(); 1281 QSettingsGroup::const_iterator it = grp.find( realkey ), end = grp.end();
1270 QString retval = def; 1282 QString retval = def;
1271 if ( it != end ) { 1283 if ( it != end ) {
1272 // found the value we needed 1284 // found the value we needed
1273 retval = *it; 1285 retval = *it;
1274 if ( ok ) *ok = TRUE; 1286 if ( ok ) *ok = TRUE;
1275 } 1287 }
1276 return retval; 1288 return retval;
1277} 1289}
1278 1290
1279 1291
1280#if !defined(Q_NO_BOOL_TYPE) 1292#if !defined(Q_NO_BOOL_TYPE)
1281/*! 1293/*!
1282 Writes the boolean entry \a value into key \a key. The \a key is 1294 Writes the boolean entry \a value into key \a key. The \a key is
1283 created if it doesn't exist. Any previous value is overwritten by \a 1295 created if it doesn't exist. Any previous value is overwritten by \a
1284 value. 1296 value.
1285 1297
1286 If an error occurs the settings are left unchanged and FALSE is 1298 If an error occurs the settings are left unchanged and FALSE is
1287 returned; otherwise TRUE is returned. 1299 returned; otherwise TRUE is returned.
1288 1300
1289 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1301 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
1290*/ 1302*/
1291bool QSettings::writeEntry(const QString &key, bool value) 1303bool QSettings::writeEntry(const QString &key, bool value)
1292{ 1304{
1293 if ( !qt_verify_key( key ) ) { 1305 QString grp_key( groupKey( group(), key ) );
1306 if ( !qt_verify_key( grp_key ) ) {
1294#if defined(QT_CHECK_STATE) 1307#if defined(QT_CHECK_STATE)
1295 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1308 qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1296#endif 1309#endif
1297 return FALSE; 1310 return FALSE;
1298 } 1311 }
1299 1312
1300#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1313#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1301 if ( d->sysd ) 1314 if ( d->sysd )
1302 return d->sysWriteEntry( groupKey( group(), key ), value ); 1315 return d->sysWriteEntry( grp_key, value );
1303#endif 1316#endif
1304 QString s(value ? "true" : "false"); 1317 QString s(value ? "true" : "false");
1305 return writeEntry(key, s); 1318 return writeEntry(key, s);
1306} 1319}
1307#endif 1320#endif
1308 1321
1309 1322
1310/*! 1323/*!
1311 \overload 1324 \overload
1312 Writes the double entry \a value into key \a key. The \a key is 1325 Writes the double entry \a value into key \a key. The \a key is
1313 created if it doesn't exist. Any previous value is overwritten by \a 1326 created if it doesn't exist. Any previous value is overwritten by \a
1314 value. 1327 value.
1315 1328
1316 If an error occurs the settings are left unchanged and FALSE is 1329 If an error occurs the settings are left unchanged and FALSE is
1317 returned; otherwise TRUE is returned. 1330 returned; otherwise TRUE is returned.
1318 1331
1319 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1332 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
1320*/ 1333*/
1321bool QSettings::writeEntry(const QString &key, double value) 1334bool QSettings::writeEntry(const QString &key, double value)
1322{ 1335{
1323 if ( !qt_verify_key( key ) ) { 1336 QString grp_key( groupKey( group(), key ) );
1337 if ( !qt_verify_key( grp_key ) ) {
1324#if defined(QT_CHECK_STATE) 1338#if defined(QT_CHECK_STATE)
1325 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1339 qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1326#endif 1340#endif
1327 return FALSE; 1341 return FALSE;
1328 } 1342 }
1329 1343
1330#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1344#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1331 if ( d->sysd ) 1345 if ( d->sysd )
1332 return d->sysWriteEntry( groupKey( group(), key ), value ); 1346 return d->sysWriteEntry( grp_key, value );
1333#endif 1347#endif
1334 QString s(QString::number(value)); 1348 QString s(QString::number(value));
1335 return writeEntry(key, s); 1349 return writeEntry(key, s);
1336} 1350}
1337 1351
1338 1352
1339/*! 1353/*!
1340 \overload 1354 \overload
1341 Writes the integer entry \a value into key \a key. The \a key is 1355 Writes the integer entry \a value into key \a key. The \a key is
1342 created if it doesn't exist. Any previous value is overwritten by \a 1356 created if it doesn't exist. Any previous value is overwritten by \a
1343 value. 1357 value.
1344 1358
1345 If an error occurs the settings are left unchanged and FALSE is 1359 If an error occurs the settings are left unchanged and FALSE is
1346 returned; otherwise TRUE is returned. 1360 returned; otherwise TRUE is returned.
1347 1361
1348 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1362 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
1349*/ 1363*/
1350bool QSettings::writeEntry(const QString &key, int value) 1364bool QSettings::writeEntry(const QString &key, int value)
1351{ 1365{
1352 if ( !qt_verify_key( key ) ) { 1366 QString grp_key( groupKey( group(), key ) );
1367 if ( !qt_verify_key( grp_key ) ) {
1353#if defined(QT_CHECK_STATE) 1368#if defined(QT_CHECK_STATE)
1354 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1369 qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1355#endif 1370#endif
1356 return FALSE; 1371 return FALSE;
1357 } 1372 }
1358 1373
1359#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1374#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1360 if ( d->sysd ) 1375 if ( d->sysd )
1361 return d->sysWriteEntry( groupKey( group(), key ), value ); 1376 return d->sysWriteEntry( grp_key, value );
1362#endif 1377#endif
1363 QString s(QString::number(value)); 1378 QString s(QString::number(value));
1364 return writeEntry(key, s); 1379 return writeEntry(key, s);
1365} 1380}
1366 1381
1367 1382
1368/*! 1383/*!
1369 \internal 1384 \internal
1370 1385
1371 Writes the entry specified by \a key with the string-literal \a value, 1386 Writes the entry specified by \a key with the string-literal \a value,
1372 replacing any previous setting. If \a value is zero-length or null, the 1387 replacing any previous setting. If \a value is zero-length or null, the
1373 entry is replaced by an empty setting. 1388 entry is replaced by an empty setting.
1374 1389
1375 \e NOTE: This function is provided because some compilers use the 1390 \e NOTE: This function is provided because some compilers use the
1376 writeEntry (const QString &, bool) overload for this code: 1391 writeEntry (const QString &, bool) overload for this code:
1377 writeEntry ("/foo/bar", "baz") 1392 writeEntry ("/foo/bar", "baz")
1378 1393
1379 If an error occurs, this functions returns FALSE and the object is left 1394 If an error occurs, this functions returns FALSE and the object is left
1380 unchanged. 1395 unchanged.
1381 1396
1382 \sa readEntry(), removeEntry() 1397 \sa readEntry(), removeEntry()
1383*/ 1398*/
1384bool QSettings::writeEntry(const QString &key, const char *value) 1399bool QSettings::writeEntry(const QString &key, const char *value)
1385{ 1400{
1386 if ( !qt_verify_key( key ) ) {
1387#if defined(QT_CHECK_STATE)
1388 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() );
1389#endif
1390 return FALSE;
1391 }
1392
1393 return writeEntry(key, QString(value)); 1401 return writeEntry(key, QString(value));
1394} 1402}
1395 1403
1396 1404
1397/*! 1405/*!
1398 \overload 1406 \overload
1399 Writes the string entry \a value into key \a key. The \a key is 1407 Writes the string entry \a value into key \a key. The \a key is
1400 created if it doesn't exist. Any previous value is overwritten by \a 1408 created if it doesn't exist. Any previous value is overwritten by \a
1401 value. If \a value is an empty string or a null string the key's 1409 value. If \a value is an empty string or a null string the key's
1402 value will be an empty string. 1410 value will be an empty string.
1403 1411
1404 If an error occurs the settings are left unchanged and FALSE is 1412 If an error occurs the settings are left unchanged and FALSE is
1405 returned; otherwise TRUE is returned. 1413 returned; otherwise TRUE is returned.
1406 1414
1407 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1415 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
1408*/ 1416*/
1409bool QSettings::writeEntry(const QString &key, const QString &value) 1417bool QSettings::writeEntry(const QString &key, const QString &value)
1410{ 1418{
1411 if ( !qt_verify_key( key ) ) { 1419 QString grp_key( groupKey( group(), key ) );
1420 if ( !qt_verify_key( grp_key ) ) {
1412#if defined(QT_CHECK_STATE) 1421#if defined(QT_CHECK_STATE)
1413 qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1422 qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1414#endif 1423#endif
1415 return FALSE; 1424 return FALSE;
1416 } 1425 }
1417 1426
1418 QString theKey = groupKey( group(), key );
1419
1420#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1427#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1421 if ( d->sysd ) 1428 if ( d->sysd )
1422 return d->sysWriteEntry( theKey, value ); 1429 return d->sysWriteEntry( grp_key, value );
1423#endif 1430#endif
1424 // NOTE: we *do* allow value to be a null/empty string 1431 // NOTE: we *do* allow value to be a null/empty string
1425 1432
1426 QString realkey; 1433 QString realkey;
1427 1434
1428 if (theKey[0] == '/') { 1435 if (grp_key[0] == '/') {
1429 // parse our key 1436 // parse our key
1430 QStringList list(QStringList::split('/', theKey)); 1437 QStringList list(QStringList::split('/', grp_key));
1431 1438
1432 if (list.count() < 2) { 1439 if (list.count() < 2) {
1433#ifdef QT_CHECK_STATE 1440#ifdef QT_CHECK_STATE
1434 qWarning("QSettings::writeEntry: invalid key '%s'", theKey.latin1()); 1441 qWarning("QSettings::writeEntry: invalid key '%s'", grp_key.latin1());
1435#endif // QT_CHECK_STATE 1442#endif // QT_CHECK_STATE
1436 1443
1437 return FALSE; 1444 return FALSE;
1438 } 1445 }
1439 1446
1440 if (list.count() == 2) { 1447 if (list.count() == 2) {
1441 d->heading = list[0]; 1448 d->heading = list[0];
1442 d->group = "General"; 1449 d->group = "General";
1443 realkey = list[1]; 1450 realkey = list[1];
1444 } else { 1451 } else {
1445 d->heading = list[0]; 1452 d->heading = list[0];
1446 d->group = list[1]; 1453 d->group = list[1];
1447 1454
1448 // remove the group from the list 1455 // remove the group from the list
1449 list.remove(list.at(1)); 1456 list.remove(list.at(1));
1450 // remove the heading from the list 1457 // remove the heading from the list
1451 list.remove(list.at(0)); 1458 list.remove(list.at(0));
1452 1459
1453 realkey = list.join("/"); 1460 realkey = list.join("/");
1454 } 1461 }
1455 } else 1462 } else {
1456 realkey = theKey; 1463 realkey = grp_key;
1464 }
1457 1465
1458 d->writeGroup(realkey, value); 1466 d->writeGroup(realkey, value);
1459 return TRUE; 1467 return TRUE;
1460} 1468}
1461 1469
1462 1470
1463/*! 1471/*!
1464 Removes the entry specified by \a key. 1472 Removes the entry specified by \a key.
1465 1473
1466 Returns TRUE if the entry existed and was removed; otherwise returns FALSE. 1474 Returns TRUE if the entry existed and was removed; otherwise returns FALSE.
1467 1475
1468 \sa readEntry(), writeEntry() 1476 \sa readEntry(), writeEntry()
1469*/ 1477*/
1470bool QSettings::removeEntry(const QString &key) 1478bool QSettings::removeEntry(const QString &key)
1471{ 1479{
1472 if ( !qt_verify_key( key ) ) { 1480 QString grp_key( groupKey( group(), key ) );
1481 if ( !qt_verify_key( grp_key ) ) {
1473#if defined(QT_CHECK_STATE) 1482#if defined(QT_CHECK_STATE)
1474 qWarning( "QSettings::removeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1483 qWarning( "QSettings::removeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1475#endif 1484#endif
1476 return FALSE; 1485 return FALSE;
1477 } 1486 }
1478 1487
1479 QString theKey = groupKey( group(), key );
1480
1481#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1488#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1482 if ( d->sysd ) 1489 if ( d->sysd )
1483 return d->sysRemoveEntry( theKey ); 1490 return d->sysRemoveEntry( grp_key );
1484#endif 1491#endif
1485 1492
1486 QString realkey; 1493 QString realkey;
1487 1494 if (grp_key[0] == '/') {
1488 if (theKey[0] == '/') {
1489 // parse our key 1495 // parse our key
1490 QStringList list(QStringList::split('/', theKey)); 1496 QStringList list(QStringList::split('/', grp_key));
1491 1497
1492 if (list.count() < 2) { 1498 if (list.count() < 2) {
1493#ifdef QT_CHECK_STATE 1499#ifdef QT_CHECK_STATE
1494 qWarning("QSettings::removeEntry: invalid key '%s'", theKey.latin1()); 1500 qWarning("QSettings::removeEntry: invalid key '%s'", grp_key.latin1());
1495#endif // QT_CHECK_STATE 1501#endif // QT_CHECK_STATE
1496 1502
1497 return FALSE; 1503 return FALSE;
1498 } 1504 }
1499 1505
1500 if (list.count() == 2) { 1506 if (list.count() == 2) {
1501 d->heading = list[0]; 1507 d->heading = list[0];
1502 d->group = "General"; 1508 d->group = "General";
1503 realkey = list[1]; 1509 realkey = list[1];
1504 } else { 1510 } else {
1505 d->heading = list[0]; 1511 d->heading = list[0];
1506 d->group = list[1]; 1512 d->group = list[1];
1507 1513
1508 // remove the group from the list 1514 // remove the group from the list
1509 list.remove(list.at(1)); 1515 list.remove(list.at(1));
1510 // remove the heading from the list 1516 // remove the heading from the list
1511 list.remove(list.at(0)); 1517 list.remove(list.at(0));
1512 1518
1513 realkey = list.join("/"); 1519 realkey = list.join("/");
1514 } 1520 }
1515 } else 1521 } else {
1516 realkey = theKey; 1522 realkey = grp_key;
1523 }
1517 1524
1518 d->removeGroup(realkey); 1525 d->removeGroup(realkey);
1519 return TRUE; 1526 return TRUE;
1520} 1527}
1521 1528
1522 1529
1523/*! 1530/*!
1524 Returns a list of the keys which contain entries under \a key. Does \e 1531 Returns a list of the keys which contain entries under \a key. Does \e
1525 not return any keys that contain keys. 1532 not return any keys that contain keys.
1526 1533
1527 Example settings: 1534 Example settings:
1528 \code 1535 \code
1529 /MyCompany/MyApplication/background color 1536 /MyCompany/MyApplication/background color
1530 /MyCompany/MyApplication/foreground color 1537 /MyCompany/MyApplication/foreground color
1531 /MyCompany/MyApplication/geometry/x 1538 /MyCompany/MyApplication/geometry/x
1532 /MyCompany/MyApplication/geometry/y 1539 /MyCompany/MyApplication/geometry/y
1533 /MyCompany/MyApplication/geometry/width 1540 /MyCompany/MyApplication/geometry/width
1534 /MyCompany/MyApplication/geometry/height 1541 /MyCompany/MyApplication/geometry/height
1535 \endcode 1542 \endcode
1536 \code 1543 \code
1537 QStringList keys = entryList( "/MyCompany/MyApplication" ); 1544 QStringList keys = entryList( "/MyCompany/MyApplication" );
1538 \endcode 1545 \endcode
1539 \c keys contains 'background color' and 'foreground color'. It does 1546 \c keys contains 'background color' and 'foreground color'. It does
1540 not contain 'geometry' because this key contains keys not entries. 1547 not contain 'geometry' because this key contains keys not entries.
1541 1548
1542 To access the geometry values could either use subkeyList() to read 1549 To access the geometry values could either use subkeyList() to read
1543 the keys and then read each entry, or simply read each entry 1550 the keys and then read each entry, or simply read each entry
1544 directly by specifying its full key, e.g. 1551 directly by specifying its full key, e.g.
1545 "/MyCompany/MyApplication/geometry/y". 1552 "/MyCompany/MyApplication/geometry/y".
1546 1553
1547 \sa subkeyList() 1554 \sa subkeyList()
1548*/ 1555*/
1549QStringList QSettings::entryList(const QString &key) const 1556QStringList QSettings::entryList(const QString &key) const
1550{ 1557{
1551 if ( !qt_verify_key( key ) ) { 1558 QString grp_key( groupKey( group(), key ) );
1559 if ( !qt_verify_key( grp_key ) ) {
1552#if defined(QT_CHECK_STATE) 1560#if defined(QT_CHECK_STATE)
1553 qWarning( "QSettings::entryList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() ); 1561 qWarning( "QSettings::entryList: Invalid key: %s", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1554#endif 1562#endif
1555 return QStringList(); 1563 return QStringList();
1556 } 1564 }
1557 1565
1558 QString theKey = groupKey( group(), key );
1559
1560#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1566#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1561 if ( d->sysd ) 1567 if ( d->sysd )
1562 return d->sysEntryList( theKey ); 1568 return d->sysEntryList( grp_key );
1563#endif 1569#endif
1564 1570
1565 QString realkey; 1571 QString realkey;
1566 if (theKey[0] == '/') { 1572 if (grp_key[0] == '/') {
1567 // parse our key 1573 // parse our key
1568 QStringList list(QStringList::split('/', theKey)); 1574 QStringList list(QStringList::split('/', grp_key));
1569 1575
1570 if (list.count() < 1) { 1576 if (list.count() < 1) {
1571#ifdef QT_CHECK_STATE 1577#ifdef QT_CHECK_STATE
1572 qWarning("QSettings::listEntries: invalid key '%s'", theKey.latin1()); 1578 qWarning("QSettings::listEntries: invalid key '%s'", grp_key.latin1());
1573#endif // QT_CHECK_STATE 1579#endif // QT_CHECK_STATE
1574 1580
1575 return QStringList(); 1581 return QStringList();
1576 } 1582 }
1577 1583
1578 if (list.count() == 1) { 1584 if (list.count() == 1) {
1579 d->heading = list[0]; 1585 d->heading = list[0];
1580 d->group = "General"; 1586 d->group = "General";
1581 } else { 1587 } else {
1582 d->heading = list[0]; 1588 d->heading = list[0];
1583 d->group = list[1]; 1589 d->group = list[1];
1584 1590
1585 // remove the group from the list 1591 // remove the group from the list
1586 list.remove(list.at(1)); 1592 list.remove(list.at(1));
1587 // remove the heading from the list 1593 // remove the heading from the list
1588 list.remove(list.at(0)); 1594 list.remove(list.at(0));
1589 1595
1590 realkey = list.join("/"); 1596 realkey = list.join("/");
1591 } 1597 }
1592 } else 1598 } else
1593 realkey = theKey; 1599 realkey = grp_key;
1594 1600
1595 QSettingsGroup grp = d->readGroup(); 1601 QSettingsGroup grp = d->readGroup();
1596 QSettingsGroup::Iterator it = grp.begin(); 1602 QSettingsGroup::Iterator it = grp.begin();
1597 QStringList ret; 1603 QStringList ret;
1598 QString itkey; 1604 QString itkey;
1599 while (it != grp.end()) { 1605 while (it != grp.end()) {
1600 itkey = it.key(); 1606 itkey = it.key();
1601 ++it; 1607 ++it;
1602 1608
1603 if ( realkey.length() > 0 ) { 1609 if ( realkey.length() > 0 ) {
1604 if ( itkey.left( realkey.length() ) != realkey ) 1610 if ( itkey.left( realkey.length() ) != realkey )
1605 continue; 1611 continue;
1606 else 1612 else
1607 itkey.remove( 0, realkey.length() + 1 ); 1613 itkey.remove( 0, realkey.length() + 1 );
1608 } 1614 }
1609 1615
1610 if ( itkey.find( '/' ) != -1 ) 1616 if ( itkey.find( '/' ) != -1 )
1611 continue; 1617 continue;
1612 1618
1613 ret << itkey; 1619 ret << itkey;
1614 } 1620 }
1615 1621
1616 return ret; 1622 return ret;
1617} 1623}
@@ -1624,255 +1630,255 @@ QStringList QSettings::entryList(const QString &key) const
1624 Example settings: 1630 Example settings:
1625 \code 1631 \code
1626 /MyCompany/MyApplication/background color 1632 /MyCompany/MyApplication/background color
1627 /MyCompany/MyApplication/foreground color 1633 /MyCompany/MyApplication/foreground color
1628 /MyCompany/MyApplication/geometry/x 1634 /MyCompany/MyApplication/geometry/x
1629 /MyCompany/MyApplication/geometry/y 1635 /MyCompany/MyApplication/geometry/y
1630 /MyCompany/MyApplication/geometry/width 1636 /MyCompany/MyApplication/geometry/width
1631 /MyCompany/MyApplication/geometry/height 1637 /MyCompany/MyApplication/geometry/height
1632 /MyCompany/MyApplication/recent files/1 1638 /MyCompany/MyApplication/recent files/1
1633 /MyCompany/MyApplication/recent files/2 1639 /MyCompany/MyApplication/recent files/2
1634 /MyCompany/MyApplication/recent files/3 1640 /MyCompany/MyApplication/recent files/3
1635 \endcode 1641 \endcode
1636 \code 1642 \code
1637 QStringList keys = subkeyList( "/MyCompany/MyApplication" ); 1643 QStringList keys = subkeyList( "/MyCompany/MyApplication" );
1638 \endcode 1644 \endcode
1639 \c keys contains 'geometry' and 'recent files'. It does not contain 1645 \c keys contains 'geometry' and 'recent files'. It does not contain
1640 'background color' or 'foreground color' because they are keys which 1646 'background color' or 'foreground color' because they are keys which
1641 contain entries not keys. To get a list of keys that have values 1647 contain entries not keys. To get a list of keys that have values
1642 rather than subkeys use entryList(). 1648 rather than subkeys use entryList().
1643 1649
1644 \sa entryList() 1650 \sa entryList()
1645*/ 1651*/
1646QStringList QSettings::subkeyList(const QString &key) const 1652QStringList QSettings::subkeyList(const QString &key) const
1647{ 1653{
1648 if ( !qt_verify_key( key ) ) { 1654 QString grp_key( groupKey( group(), key ) );
1655 if ( !qt_verify_key( grp_key ) ) {
1649#if defined(QT_CHECK_STATE) 1656#if defined(QT_CHECK_STATE)
1650 qWarning( "QSettings::subkeyList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() ); 1657 qWarning( "QSettings::subkeyList: Invalid key: %s", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1651#endif 1658#endif
1652 return QStringList(); 1659 return QStringList();
1653 } 1660 }
1654 1661
1655 QString theKey = groupKey( group(), key );
1656
1657#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1662#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1658 if ( d->sysd ) 1663 if ( d->sysd )
1659 return d->sysSubkeyList( theKey ); 1664 return d->sysSubkeyList( grp_key );
1660#endif 1665#endif
1661 1666
1662 QString realkey; 1667 QString realkey;
1663 int subkeycount = 2; 1668 int subkeycount = 2;
1664 if (theKey[0] == '/') { 1669 if (grp_key[0] == '/') {
1665 // parse our key 1670 // parse our key
1666 QStringList list(QStringList::split('/', theKey)); 1671 QStringList list(QStringList::split('/', grp_key));
1667 1672
1668 if (list.count() < 1) { 1673 if (list.count() < 1) {
1669#ifdef QT_CHECK_STATE 1674#ifdef QT_CHECK_STATE
1670 qWarning("QSettings::subkeyList: invalid key '%s'", theKey.latin1()); 1675 qWarning("QSettings::subkeyList: invalid key '%s'", grp_key.latin1());
1671#endif // QT_CHECK_STATE 1676#endif // QT_CHECK_STATE
1672 1677
1673 return QStringList(); 1678 return QStringList();
1674 } 1679 }
1675 1680
1676 subkeycount = list.count(); 1681 subkeycount = list.count();
1677 1682
1678 if (list.count() == 1) { 1683 if (list.count() == 1) {
1679 d->heading = list[0]; 1684 d->heading = list[0];
1680 d->group = "General"; 1685 d->group = "General";
1681 } else { 1686 } else {
1682 d->heading = list[0]; 1687 d->heading = list[0];
1683 d->group = list[1]; 1688 d->group = list[1];
1684 1689
1685 // remove the group from the list 1690 // remove the group from the list
1686 list.remove(list.at(1)); 1691 list.remove(list.at(1));
1687 // remove the heading from the list 1692 // remove the heading from the list
1688 list.remove(list.at(0)); 1693 list.remove(list.at(0));
1689 1694
1690 realkey = list.join("/"); 1695 realkey = list.join("/");
1691 } 1696 }
1692 1697
1693 } else 1698 } else
1694 realkey = theKey; 1699 realkey = grp_key;
1695 1700
1696 QStringList ret; 1701 QStringList ret;
1697 if ( subkeycount == 1 ) { 1702 if ( subkeycount == 1 ) {
1698 QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin(); 1703 QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin();
1699 while ( it != d->headings.end() ) { 1704 while ( it != d->headings.end() ) {
1700 if ( it.key() != "General" && ! ret.contains( it.key() ) ) 1705 if ( it.key() != "General" && ! ret.contains( it.key() ) )
1701 ret << it.key(); 1706 ret << it.key();
1702 ++it; 1707 ++it;
1703 } 1708 }
1704 1709
1705 return ret; 1710 return ret;
1706 } 1711 }
1707 1712
1708 QSettingsGroup grp = d->readGroup(); 1713 QSettingsGroup grp = d->readGroup();
1709 QSettingsGroup::Iterator it = grp.begin(); 1714 QSettingsGroup::Iterator it = grp.begin();
1710 QString itkey; 1715 QString itkey;
1711 while (it != grp.end()) { 1716 while (it != grp.end()) {
1712 itkey = it.key(); 1717 itkey = it.key();
1713 ++it; 1718 ++it;
1714 1719
1715 if ( realkey.length() > 0 ) { 1720 if ( realkey.length() > 0 ) {
1716 if ( itkey.left( realkey.length() ) != realkey ) 1721 if ( itkey.left( realkey.length() ) != realkey )
1717 continue; 1722 continue;
1718 else 1723 else
1719 itkey.remove( 0, realkey.length() + 1 ); 1724 itkey.remove( 0, realkey.length() + 1 );
1720 } 1725 }
1721 1726
1722 int slash = itkey.find( '/' ); 1727 int slash = itkey.find( '/' );
1723 if ( slash == -1 ) 1728 if ( slash == -1 )
1724 continue; 1729 continue;
1725 itkey.truncate( slash ); 1730 itkey.truncate( slash );
1726 1731
1727 if ( ! ret.contains( itkey ) ) 1732 if ( ! ret.contains( itkey ) )
1728 ret << itkey; 1733 ret << itkey;
1729 } 1734 }
1730 1735
1731 return ret; 1736 return ret;
1732} 1737}
1733 1738
1734 1739
1735/*! 1740/*!
1736 \internal 1741 \internal
1737 1742
1738 This function returns the time of last modification for \a key. 1743 This function returns the time of last modification for \a key.
1739*/ 1744*/
1740QDateTime QSettings::lastModficationTime(const QString &key) 1745QDateTime QSettings::lastModificationTime( const QString &key )
1741{ 1746{
1742 if ( !qt_verify_key( key ) ) { 1747 QString grp_key( groupKey( group(), key ) );
1748 if ( !qt_verify_key( grp_key ) ) {
1743#if defined(QT_CHECK_STATE) 1749#if defined(QT_CHECK_STATE)
1744 qWarning( "QSettings::lastModficationTime: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); 1750 qWarning( "QSettings::lastModificationTime: Invalid key '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() );
1745#endif 1751#endif
1746 return QDateTime(); 1752 return QDateTime();
1747 } 1753 }
1748 1754
1749 QString theKey = groupKey( group(), key );
1750
1751#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) 1755#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC))
1752 if ( d->sysd ) 1756 if ( d->sysd )
1753 return QDateTime(); 1757 return QDateTime();
1754#endif 1758#endif
1755 1759
1756 if (theKey[0] == '/') { 1760 if (grp_key[0] == '/') {
1757 // parse our key 1761 // parse our key
1758 QStringList list(QStringList::split('/', theKey)); 1762 QStringList list(QStringList::split('/', grp_key));
1759 1763
1760 if (list.count() < 2) { 1764 if (list.count() < 2) {
1761#ifdef QT_CHECK_STATE 1765#ifdef QT_CHECK_STATE
1762 qWarning("QSettings::lastModficationTime: invalid key '%s'", theKey.latin1()); 1766 qWarning("QSettings::lastModificationTime: Invalid key '%s'", grp_key.latin1());
1763#endif // QT_CHECK_STATE 1767#endif // QT_CHECK_STATE
1764 1768
1765 return QDateTime(); 1769 return QDateTime();
1766 } 1770 }
1767 1771
1768 if (list.count() == 2) { 1772 if (list.count() == 2) {
1769 d->heading = list[0]; 1773 d->heading = list[0];
1770 d->group = "General"; 1774 d->group = "General";
1771 } else { 1775 } else {
1772 d->heading = list[0]; 1776 d->heading = list[0];
1773 d->group = list[1]; 1777 d->group = list[1];
1774 } 1778 }
1775 } 1779 }
1776 1780
1777 return d->modificationTime(); 1781 return d->modificationTime();
1778} 1782}
1779 1783
1780 1784
1781/*! 1785/*!
1782 \overload 1786 \overload
1787 \obsolete
1783 1788
1784 Writes the string list entry \a value into key \a key. The \a key 1789 Writes the string list entry \a value into key \a key. The \a key
1785 is created if it doesn't exist. Any previous value is overwritten 1790 is created if it doesn't exist. Any previous value is overwritten
1786 by \a value. The list is stored as a sequence of strings separated 1791 by \a value. The list is stored as a sequence of strings separated
1787 by \a separator (using QStringList::join()), so none of the 1792 by \a separator (using QStringList::join()), so none of the
1788 strings in the list should contain the separator. If the list is 1793 strings in the list should contain the separator. If the list is
1789 empty or null the key's value will be an empty string. 1794 empty or null the key's value will be an empty string.
1790 1795
1791 \warning The list should not contain empty or null strings, as 1796 \warning The list should not contain empty or null strings, as
1792 readListEntry() will use QStringList::split() to recreate the 1797 readListEntry() will use QStringList::split() to recreate the
1793 list. As the documentation states, QStringList::split() will omit 1798 list. As the documentation states, QStringList::split() will omit
1794 empty strings from the list. Because of this, it is impossible to 1799 empty strings from the list. Because of this, it is impossible to
1795 retrieve identical list data that is stored with this function. 1800 retrieve identical list data that is stored with this function.
1796 We recommend using the writeEntry() and readListEntry() overloads 1801 We recommend using the writeEntry() and readListEntry() overloads
1797 that do not take a \a separator argument. 1802 that do not take a \a separator argument.
1798 1803
1804
1799 If an error occurs the settings are left unchanged and FALSE is 1805 If an error occurs the settings are left unchanged and FALSE is
1800 returned; otherwise returns TRUE. 1806 returned; otherwise returns TRUE.
1801 1807
1802 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1808 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry(), QStringList::join()
1803*/ 1809*/
1804bool QSettings::writeEntry(const QString &key, const QStringList &value, 1810bool QSettings::writeEntry(const QString &key, const QStringList &value,
1805 const QChar &separator) 1811 const QChar &separator)
1806{ 1812{
1807 QString s(value.join(separator)); 1813 QString s(value.join(separator));
1808 return writeEntry(key, s); 1814 return writeEntry(key, s);
1809} 1815}
1810 1816
1811/*! 1817/*!
1812 \overload 1818 \overload
1813 1819
1814 Writes the string list entry \a value into key \a key. The \a key 1820 Writes the string list entry \a value into key \a key. The \a key
1815 is created if it doesn't exist. Any previous value is overwritten 1821 is created if it doesn't exist. Any previous value is overwritten
1816 by \a value. 1822 by \a value.
1817 1823
1818 If an error occurs the settings are left unchanged and FALSE is 1824 If an error occurs the settings are left unchanged and FALSE is
1819 returned; otherwise returns TRUE. 1825 returned; otherwise returns TRUE.
1820 1826
1821 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() 1827 \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry()
1822*/ 1828*/
1823bool QSettings::writeEntry(const QString &key, const QStringList &value) 1829bool QSettings::writeEntry(const QString &key, const QStringList &value)
1824{ 1830{
1825 QString s; 1831 QString s;
1826 for (QStringList::ConstIterator it=value.begin(); it!=value.end(); ++it) { 1832 for (QStringList::ConstIterator it=value.begin(); it!=value.end(); ++it) {
1827 QString el = *it; 1833 QString el = *it;
1828 if ( el.isNull() ) { 1834 if ( el.isNull() ) {
1829 el = "^0"; 1835 el = "^0";
1830 } else { 1836 } else {
1831 el.replace("^", "^^"); 1837 el.replace("^", "^^");
1832 } 1838 }
1833 s+=el; 1839 s+=el;
1834 s+="^e"; // end of element 1840 s+="^e"; // end of element
1835 } 1841 }
1836 return writeEntry(key, s); 1842 return writeEntry(key, s);
1837} 1843}
1838 1844
1839 1845
1840/*! 1846/*!
1841 \overload QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) const 1847 \overload QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) const
1848 \obsolete
1842 1849
1843 Reads the entry specified by \a key as a string. The \a separator 1850 Reads the entry specified by \a key as a string. The \a separator
1844 is used to create a QStringList by calling QStringList::split(\a 1851 is used to create a QStringList by calling QStringList::split(\a
1845 separator, entry). If \a ok is not 0: \a *ok is set to TRUE if the 1852 separator, entry). If \a ok is not 0: \a *ok is set to TRUE
1846 key was read, otherwise \a *ok is set to FALSE. 1853 if the key was read, otherwise \a *ok is set to FALSE.
1847 1854
1848 \warning As the documentation states, QStringList::split() will 1855 \warning As the documentation states, QStringList::split() will
1849 omit empty strings from the list. Because of this, it is 1856 omit empty strings from the list. Because of this, it is
1850 impossible to retrieve identical list data with this function. We 1857 impossible to retrieve identical list data with this function. We
1851 recommend using the readListEntry() and writeEntry() overloads 1858 recommend using the readListEntry() and writeEntry() overloads
1852 that do not take a \a separator argument. 1859 that do not take a \a separator argument.
1853 1860
1854
1855 Note that if you want to iterate over the list, you should iterate 1861 Note that if you want to iterate over the list, you should iterate
1856 over a copy, e.g. 1862 over a copy, e.g.
1857 \code 1863 \code
1858 QStringList list = mySettings.readListEntry( "size", " " ); 1864 QStringList list = mySettings.readListEntry( "size", " " );
1859 QStringList::Iterator it = list.begin(); 1865 QStringList::Iterator it = list.begin();
1860 while( it != list.end() ) { 1866 while( it != list.end() ) {
1861 myProcessing( *it ); 1867 myProcessing( *it );
1862 ++it; 1868 ++it;
1863 } 1869 }
1864 \endcode 1870 \endcode
1865 1871
1866 \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split() 1872 \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split()
1867*/ 1873*/
1868 1874
1869/*! 1875/*!
1870 \internal 1876 \internal
1871*/ 1877*/
1872QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) 1878QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok )
1873{ 1879{
1874 QString value = readEntry( key, QString::null, ok ); 1880 QString value = readEntry( key, QString::null, ok );
1875 if ( ok && !*ok ) 1881 if ( ok && !*ok )
1876 return QStringList(); 1882 return QStringList();
1877 1883
1878 return QStringList::split(separator, value); 1884 return QStringList::split(separator, value);
@@ -1928,86 +1934,91 @@ QStringList QSettings::readListEntry(const QString &key, bool *ok )
1928 l.append(s); 1934 l.append(s);
1929 } 1935 }
1930 } 1936 }
1931 return l; 1937 return l;
1932} 1938}
1933 1939
1934#ifdef Q_OS_MAC 1940#ifdef Q_OS_MAC
1935void qt_setSettingsBasePath(const QString &); //qsettings_mac.cpp 1941void qt_setSettingsBasePath(const QString &); //qsettings_mac.cpp
1936#endif 1942#endif
1937 1943
1938/*! 1944/*!
1939 Insert platform-dependent paths from platform-independent information. 1945 Insert platform-dependent paths from platform-independent information.
1940 1946
1941 The \a domain should be an Internet domain name 1947 The \a domain should be an Internet domain name
1942 controlled by the producer of the software, eg. Trolltech products 1948 controlled by the producer of the software, eg. Trolltech products
1943 use "trolltech.com". 1949 use "trolltech.com".
1944 1950
1945 The \a product should be the official name of the product. 1951 The \a product should be the official name of the product.
1946 1952
1947 The \a scope should be 1953 The \a scope should be
1948 QSettings::User for user-specific settings, or 1954 QSettings::User for user-specific settings, or
1949 QSettings::Global for system-wide settings (generally 1955 QSettings::Global for system-wide settings (generally
1950 these will be read-only to many users). 1956 these will be read-only to many users).
1951 1957
1952 Not all information is relevant on all systems (e.g. scoping is 1958 Not all information is relevant on all systems.
1953 currently used only if QSettings accesses the Windows registry).
1954*/ 1959*/
1955 1960
1956void QSettings::setPath( const QString &domain, const QString &product, Scope scope ) 1961void QSettings::setPath( const QString &domain, const QString &product, Scope scope )
1957{ 1962{
1958// On Windows, any trailing ".com(\..*)" is stripped from the domain. The 1963// On Windows, any trailing ".com(\..*)" is stripped from the domain. The
1959// Global scope corresponds to HKEY_LOCAL_MACHINE, and User corresponds to 1964// Global scope corresponds to HKEY_LOCAL_MACHINE, and User corresponds to
1960// HKEY_CURRENT_USER. Note that on some installations, not all users can 1965// HKEY_CURRENT_USER. Note that on some installations, not all users can
1961// write to the Global scope. On UNIX, any trailing ".com(\..*)" is stripped 1966// write to the Global scope. On UNIX, any trailing ".com(\..*)" is stripped
1962// from the domain. The Global scope corresponds to "/opt" (this would be 1967// from the domain. The Global scope corresponds to "/opt" (this would be
1963// configurable at library build time - eg. to "/usr/local" or "/usr"), 1968// configurable at library build time - eg. to "/usr/local" or "/usr"),
1964// while the User scope corresponds to $HOME/.*rc. 1969// while the User scope corresponds to $HOME/.*rc.
1965// Note that on most installations, not all users can write to the System 1970// Note that on most installations, not all users can write to the System
1966// scope. 1971// scope.
1967// 1972//
1968// On MacOS X, if there is no "." in domain, append ".com", then reverse the 1973// On MacOS X, if there is no "." in domain, append ".com", then reverse the
1969// order of the elements (Mac OS uses "com.apple.finder" as domain+product). 1974// order of the elements (Mac OS uses "com.apple.finder" as domain+product).
1970// The Global scope corresponds to /Library/Preferences/*.plist, while the 1975// The Global scope corresponds to /Library/Preferences/*.plist, while the
1971// User scope corresponds to ~/Library/Preferences/*.plist. 1976// User scope corresponds to ~/Library/Preferences/*.plist.
1972// Note that on most installations, not all users can write to the System 1977// Note that on most installations, not all users can write to the System
1973// scope. 1978// scope.
1974 d->globalScope = scope == Global; 1979 d->globalScope = scope == Global;
1975 1980
1976 QString actualSearchPath; 1981 QString actualSearchPath;
1977 int lastDot = domain.findRev( '.' ); 1982 int lastDot = domain.findRev( '.' );
1978 1983
1979#if defined(Q_WS_WIN) 1984#if defined(Q_WS_WIN)
1980 actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product; 1985 actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product;
1981 insertSearchPath( Windows, actualSearchPath ); 1986 insertSearchPath( Windows, actualSearchPath );
1982#elif !defined(QWS) && defined(Q_OS_MAC) 1987#elif !defined(QWS) && defined(Q_OS_MAC)
1988 if(lastDot != -1) {
1983 QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + "."; 1989 QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + ".";
1984 if ( !topLevelDomain.isEmpty() ) 1990 if ( !topLevelDomain.isEmpty() )
1985 qt_setSettingsBasePath( topLevelDomain ); 1991 qt_setSettingsBasePath( topLevelDomain );
1986 actualSearchPath = "/" + domain.left( lastDot ) + product; 1992 }
1993 actualSearchPath = "/" + domain.left( lastDot ) + "." + product;
1987 insertSearchPath( Mac, actualSearchPath ); 1994 insertSearchPath( Mac, actualSearchPath );
1988#else 1995#else
1989 actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product; 1996 if (scope == User)
1997 actualSearchPath = QDir::homeDirPath() + "/.";
1998 else
1999 actualSearchPath = QString(qInstallPathSysconf()) + "/";
2000 actualSearchPath += domain.mid( 0, lastDot ) + "/" + product;
1990 insertSearchPath( Unix, actualSearchPath ); 2001 insertSearchPath( Unix, actualSearchPath );
1991#endif 2002#endif
1992} 2003}
1993 2004
1994/*! 2005/*!
1995 Appends \a group to the current key prefix. 2006 Appends \a group to the current key prefix.
1996 2007
1997 \code 2008 \code
1998 QSettings settings; 2009 QSettings settings;
1999 settings.beginGroup( "/MainWindow" ); 2010 settings.beginGroup( "/MainWindow" );
2000 // read values 2011 // read values
2001 settings.endGroup(); 2012 settings.endGroup();
2002 \endcode 2013 \endcode
2003*/ 2014*/
2004void QSettings::beginGroup( const QString &group ) 2015void QSettings::beginGroup( const QString &group )
2005{ 2016{
2006 d->groupStack.push( group ); 2017 d->groupStack.push( group );
2007 d->groupDirty = TRUE; 2018 d->groupDirty = TRUE;
2008} 2019}
2009 2020
2010/*! 2021/*!
2011 Undo previous calls to beginGroup(). Note that a single beginGroup("a/b/c") is undone 2022 Undo previous calls to beginGroup(). Note that a single beginGroup("a/b/c") is undone
2012 by a single call to endGroup(). 2023 by a single call to endGroup().
2013 2024