-rw-r--r-- | qmake/tools/qsettings.cpp | 371 |
1 files changed, 191 insertions, 180 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,597 +1,564 @@ | |||
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 | ** |
33 | ** Contact info@trolltech.com if any conditions of this licensing are | 33 | ** Contact info@trolltech.com if any conditions of this licensing are |
34 | ** not clear to you. | 34 | ** not clear to you. |
35 | ** | 35 | ** |
36 | **********************************************************************/ | 36 | **********************************************************************/ |
37 | 37 | ||
38 | #include "qplatformdefs.h" | 38 | #include "qplatformdefs.h" |
39 | 39 | ||
40 | // POSIX Large File Support redefines open -> open64 | 40 | // POSIX Large File Support redefines open -> open64 |
41 | static inline int qt_open( const char *pathname, int flags, mode_t mode ) | 41 | static 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 | ||
246 | #if defined(Q_OS_UNIX) | 252 | #if defined(Q_OS_UNIX) |
247 | typedef int HANDLE; | 253 | typedef int HANDLE; |
248 | #define Q_LOCKREAD F_RDLCK | 254 | #define Q_LOCKREAD F_RDLCK |
249 | #define Q_LOCKWRITE F_WRLCK | 255 | #define Q_LOCKWRITE F_WRLCK |
250 | /* | 256 | /* |
251 | Locks the file specified by name. The lockfile is created as a | 257 | Locks the file specified by name. The lockfile is created as a |
252 | hidden file in the same directory as the target file, with .lock | 258 | hidden file in the same directory as the target file, with .lock |
253 | appended to the name. For example, "/etc/settings/onerc" uses a | 259 | appended to the name. For example, "/etc/settings/onerc" uses a |
254 | lockfile named "/etc/settings/.onerc.lock". The type argument | 260 | lockfile named "/etc/settings/.onerc.lock". The type argument |
255 | controls the type of the lock, it can be either F_RDLCK for a read | 261 | controls the type of the lock, it can be either F_RDLCK for a read |
256 | lock, or F_WRLCK for a write lock. | 262 | lock, or F_WRLCK for a write lock. |
257 | 263 | ||
258 | A file descriptor for the lock file is returned, and should be | 264 | A file descriptor for the lock file is returned, and should be |
259 | closed with closelock() when the lock is no longer needed. | 265 | closed with closelock() when the lock is no longer needed. |
260 | */ | 266 | */ |
261 | static HANDLE openlock( const QString &name, int type ) | 267 | static HANDLE openlock( const QString &name, int type ) |
262 | { | 268 | { |
263 | QFileInfo info( name ); | 269 | QFileInfo info( name ); |
264 | // lockfile should be hidden, and never removed | 270 | // lockfile should be hidden, and never removed |
265 | QString lockfile = info.dirPath() + "/." + info.fileName() + ".lock"; | 271 | QString lockfile = info.dirPath() + "/." + info.fileName() + ".lock"; |
266 | 272 | ||
267 | // open the lockfile | 273 | // open the lockfile |
268 | HANDLE fd = qt_open( QFile::encodeName( lockfile ), | 274 | HANDLE fd = qt_open( QFile::encodeName( lockfile ), |
269 | O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ); | 275 | O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ); |
270 | 276 | ||
271 | if ( fd < 0 ) { | 277 | if ( fd < 0 ) { |
272 | // failed to open the lock file, most likely because of permissions | 278 | // failed to open the lock file, most likely because of permissions |
273 | return fd; | 279 | return fd; |
274 | } | 280 | } |
275 | 281 | ||
276 | struct flock fl; | 282 | struct flock fl; |
277 | fl.l_type = type; | 283 | fl.l_type = type; |
278 | fl.l_whence = SEEK_SET; | 284 | fl.l_whence = SEEK_SET; |
279 | fl.l_start = 0; | 285 | fl.l_start = 0; |
280 | fl.l_len = 0; | 286 | fl.l_len = 0; |
281 | if ( fcntl( fd, F_SETLKW, &fl ) == -1 ) { | 287 | if ( fcntl( fd, F_SETLKW, &fl ) == -1 ) { |
282 | // the lock failed, so we should fail silently, so that people | 288 | // the lock failed, so we should fail silently, so that people |
283 | // using filesystems that do not support locking don't see | 289 | // using filesystems that do not support locking don't see |
284 | // numerous warnings about a failed lock | 290 | // numerous warnings about a failed lock |
285 | close( fd ); | 291 | close( fd ); |
286 | fd = -1; | 292 | fd = -1; |
287 | } | 293 | } |
288 | 294 | ||
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 | */ |
296 | static void closelock( HANDLE fd ) | 302 | static 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 | |||
317 | static 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 | |||
340 | static 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 | ||
355 | QSettingsGroup::QSettingsGroup() | 322 | QSettingsGroup::QSettingsGroup() |
356 | : modified(FALSE) | 323 | : modified(FALSE) |
357 | { | 324 | { |
358 | } | 325 | } |
359 | 326 | ||
360 | 327 | ||
361 | 328 | ||
362 | 329 | ||
363 | void QSettingsHeading::read(const QString &filename) | 330 | void 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 | ||
393 | void QSettingsHeading::parseLine(QTextStream &stream) | 364 | void 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); |
432 | value = ""; | 403 | value = ""; |
433 | bool esc=TRUE; | 404 | bool esc=TRUE; |
434 | i++; | 405 | i++; |
435 | while (esc) { | 406 | while (esc) { |
436 | esc = FALSE; | 407 | esc = FALSE; |
437 | for ( ; i < (int)line.length(); i++ ) { | 408 | for ( ; i < (int)line.length(); i++ ) { |
438 | if ( esc ) { | 409 | if ( esc ) { |
439 | if ( line[i] == 'n' ) | 410 | if ( line[i] == 'n' ) |
440 | value.append('\n'); // escaped newline | 411 | value.append('\n'); // escaped newline |
441 | else if ( line[i] == '0' ) | 412 | else if ( line[i] == '0' ) |
442 | value = QString::null; // escaped empty string | 413 | value = QString::null; // escaped empty string |
443 | else | 414 | else |
444 | value.append(line[i]); | 415 | value.append(line[i]); |
445 | esc = FALSE; | 416 | esc = FALSE; |
446 | } else if ( line[i] == '\\' ) | 417 | } else if ( line[i] == '\\' ) |
447 | esc = TRUE; | 418 | esc = TRUE; |
448 | else | 419 | else |
449 | value.append(line[i]); | 420 | value.append(line[i]); |
450 | } | 421 | } |
451 | if ( esc ) { | 422 | if ( esc ) { |
452 | // Backwards-compatiblity... | 423 | // Backwards-compatiblity... |
453 | // still escaped at EOL - manually escaped "newline" | 424 | // still escaped at EOL - manually escaped "newline" |
454 | if (stream.atEnd()) { | 425 | if (stream.atEnd()) { |
455 | #if defined(QT_CHECK_STATE) | 426 | #if defined(QT_CHECK_STATE) |
456 | qWarning("QSettings: reached end of file, expected continued line"); | 427 | qWarning("QSettings: reached end of file, expected continued line"); |
457 | #endif | 428 | #endif |
458 | break; | 429 | break; |
459 | } | 430 | } |
460 | value.append('\n'); | 431 | value.append('\n'); |
461 | line = stream.readLine(); | 432 | line = stream.readLine(); |
462 | i = 0; | 433 | i = 0; |
463 | } | 434 | } |
464 | } | 435 | } |
465 | 436 | ||
466 | (*git).insert(key, value); | 437 | (*git).insert(key, value); |
467 | } | 438 | } |
468 | } | 439 | } |
469 | } | 440 | } |
470 | 441 | ||
471 | #ifdef Q_WS_WIN // for homedirpath reading from registry | 442 | #ifdef Q_WS_WIN // for homedirpath reading from registry |
472 | #include "qt_windows.h" | 443 | #include "qt_windows.h" |
473 | #include "qlibrary.h" | 444 | #include "qlibrary.h" |
474 | 445 | ||
475 | #ifndef CSIDL_APPDATA | 446 | #ifndef CSIDL_APPDATA |
476 | #define CSIDL_APPDATA 0x001a // <user name>\Application Data | 447 | #define CSIDL_APPDATA 0x001a // <user name>\Application Data |
477 | #endif | 448 | #endif |
478 | #ifndef CSIDL_COMMON_APPDATA | 449 | #ifndef CSIDL_COMMON_APPDATA |
479 | #define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data | 450 | #define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data |
480 | #endif | 451 | #endif |
481 | 452 | ||
482 | #endif | 453 | #endif |
483 | 454 | ||
484 | QSettingsPrivate::QSettingsPrivate( QSettings::Format format ) | 455 | QSettingsPrivate::QSettingsPrivate( QSettings::Format format ) |
485 | : groupDirty( TRUE ), modified(FALSE), globalScope(TRUE) | 456 | : groupDirty( TRUE ), modified(FALSE), globalScope(TRUE) |
486 | { | 457 | { |
487 | #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) | 458 | #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) |
488 | if ( format != QSettings::Ini ) | 459 | if ( format != QSettings::Ini ) |
489 | return; | 460 | return; |
490 | #else | 461 | #else |
491 | Q_UNUSED( format ); | 462 | Q_UNUSED( format ); |
492 | #endif | 463 | #endif |
493 | 464 | ||
494 | QString appSettings(QDir::homeDirPath() + "/.qt/"); | 465 | QString appSettings(QDir::homeDirPath() + "/.qt/"); |
495 | QString defPath; | 466 | QString defPath; |
496 | #ifdef Q_WS_WIN | 467 | #ifdef Q_WS_WIN |
497 | #ifdef Q_OS_TEMP | 468 | #ifdef Q_OS_TEMP |
498 | TCHAR path[MAX_PATH]; | 469 | TCHAR path[MAX_PATH]; |
499 | SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); | 470 | SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); |
500 | appSettings = QString::fromUcs2( path ); | 471 | appSettings = QString::fromUcs2( path ); |
501 | SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); | 472 | SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); |
502 | defPath = QString::fromUcs2( path ); | 473 | defPath = QString::fromUcs2( path ); |
503 | #else | 474 | #else |
504 | QLibrary library( "shell32" ); | 475 | QLibrary library( "shell32" ); |
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 | ||
550 | QSettingsPrivate::~QSettingsPrivate() | 517 | QSettingsPrivate::~QSettingsPrivate() |
551 | { | 518 | { |
552 | } | 519 | } |
553 | 520 | ||
554 | QSettingsGroup QSettingsPrivate::readGroup() | 521 | QSettingsGroup QSettingsPrivate::readGroup() |
555 | { | 522 | { |
556 | QSettingsHeading hd; | 523 | QSettingsHeading hd; |
557 | QSettingsGroup grp; | 524 | QSettingsGroup grp; |
558 | 525 | ||
559 | QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); | 526 | QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); |
560 | if (headingsit != headings.end()) | 527 | if (headingsit != headings.end()) |
561 | hd = *headingsit; | 528 | hd = *headingsit; |
562 | 529 | ||
563 | QSettingsHeading::Iterator grpit = hd.find(group); | 530 | QSettingsHeading::Iterator grpit = hd.find(group); |
564 | if (grpit == hd.end()) { | 531 | if (grpit == hd.end()) { |
565 | QStringList::Iterator it = searchPaths.begin(); | 532 | QStringList::Iterator it = searchPaths.begin(); |
566 | if ( !globalScope ) | 533 | if ( !globalScope ) |
567 | ++it; | 534 | ++it; |
568 | while (it != searchPaths.end()) { | 535 | while (it != searchPaths.end()) { |
569 | QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); | 536 | QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); |
570 | QString fn((*it++) + "/" + filebase + "rc"); | 537 | QString fn((*it++) + "/" + filebase + "rc"); |
571 | if (! hd.contains(fn + "cached")) { | 538 | if (! hd.contains(fn + "cached")) { |
572 | hd.read(fn); | 539 | hd.read(fn); |
573 | hd.insert(fn + "cached", QSettingsGroup()); | 540 | hd.insert(fn + "cached", QSettingsGroup()); |
574 | } | 541 | } |
575 | } | 542 | } |
576 | 543 | ||
577 | headings.replace(heading, hd); | 544 | headings.replace(heading, hd); |
578 | 545 | ||
579 | grpit = hd.find(group); | 546 | grpit = hd.find(group); |
580 | if (grpit != hd.end()) | 547 | if (grpit != hd.end()) |
581 | grp = *grpit; | 548 | grp = *grpit; |
582 | } else if (hd.count() != 0) | 549 | } else if (hd.count() != 0) |
583 | grp = *grpit; | 550 | grp = *grpit; |
584 | 551 | ||
585 | return grp; | 552 | return grp; |
586 | } | 553 | } |
587 | 554 | ||
588 | 555 | ||
589 | void QSettingsPrivate::removeGroup(const QString &key) | 556 | void QSettingsPrivate::removeGroup(const QString &key) |
590 | { | 557 | { |
591 | QSettingsHeading hd; | 558 | QSettingsHeading hd; |
592 | QSettingsGroup grp; | 559 | QSettingsGroup grp; |
593 | bool found = FALSE; | 560 | bool found = FALSE; |
594 | 561 | ||
595 | QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); | 562 | QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); |
596 | if (headingsit != headings.end()) | 563 | if (headingsit != headings.end()) |
597 | hd = *headingsit; | 564 | hd = *headingsit; |
@@ -640,243 +607,252 @@ void QSettingsPrivate::removeGroup(const QString &key) | |||
640 | } | 607 | } |
641 | 608 | ||
642 | 609 | ||
643 | void QSettingsPrivate::writeGroup(const QString &key, const QString &value) | 610 | void QSettingsPrivate::writeGroup(const QString &key, const QString &value) |
644 | { | 611 | { |
645 | QSettingsHeading hd; | 612 | QSettingsHeading hd; |
646 | QSettingsGroup grp; | 613 | QSettingsGroup grp; |
647 | 614 | ||
648 | QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); | 615 | QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); |
649 | if (headingsit != headings.end()) | 616 | if (headingsit != headings.end()) |
650 | hd = *headingsit; | 617 | hd = *headingsit; |
651 | 618 | ||
652 | QSettingsHeading::Iterator grpit = hd.find(group); | 619 | QSettingsHeading::Iterator grpit = hd.find(group); |
653 | if (grpit == hd.end()) { | 620 | if (grpit == hd.end()) { |
654 | QStringList::Iterator it = searchPaths.begin(); | 621 | QStringList::Iterator it = searchPaths.begin(); |
655 | if ( !globalScope ) | 622 | if ( !globalScope ) |
656 | ++it; | 623 | ++it; |
657 | while (it != searchPaths.end()) { | 624 | while (it != searchPaths.end()) { |
658 | QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); | 625 | QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); |
659 | QString fn((*it++) + "/" + filebase + "rc"); | 626 | QString fn((*it++) + "/" + filebase + "rc"); |
660 | if (! hd.contains(fn + "cached")) { | 627 | if (! hd.contains(fn + "cached")) { |
661 | hd.read(fn); | 628 | hd.read(fn); |
662 | hd.insert(fn + "cached", QSettingsGroup()); | 629 | hd.insert(fn + "cached", QSettingsGroup()); |
663 | } | 630 | } |
664 | } | 631 | } |
665 | 632 | ||
666 | headings.replace(heading, hd); | 633 | headings.replace(heading, hd); |
667 | 634 | ||
668 | grpit = hd.find(group); | 635 | grpit = hd.find(group); |
669 | if (grpit != hd.end()) | 636 | if (grpit != hd.end()) |
670 | grp = *grpit; | 637 | grp = *grpit; |
671 | } else if (hd.count() != 0) | 638 | } else if (hd.count() != 0) |
672 | grp = *grpit; | 639 | grp = *grpit; |
673 | 640 | ||
674 | grp.modified = TRUE; | 641 | grp.modified = TRUE; |
675 | grp.replace(key, value); | 642 | grp.replace(key, value); |
676 | hd.replace(group, grp); | 643 | hd.replace(group, grp); |
677 | headings.replace(heading, hd); | 644 | headings.replace(heading, hd); |
678 | 645 | ||
679 | modified = TRUE; | 646 | modified = TRUE; |
680 | } | 647 | } |
681 | 648 | ||
682 | 649 | ||
683 | QDateTime QSettingsPrivate::modificationTime() | 650 | QDateTime 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 | ||
702 | bool qt_verify_key( const QString &key ) | 669 | bool 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 | ||
709 | static inline QString groupKey( const QString &group, const QString &key ) | 676 | static 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 | */ |
805 | void QSettings::insertSearchPath( System s, const QString &path) | 781 | void 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) |
843 | QString defPath = d->globalScope ? d->searchPaths.first() : d->searchPaths.last(); | 819 | QString defPath = d->globalScope ? d->searchPaths.first() : d->searchPaths.last(); |
844 | realPath = defPath + path; | 820 | realPath = defPath + path; |
845 | #endif | 821 | #endif |
846 | 822 | ||
847 | QStringList::Iterator it = d->searchPaths.find(d->searchPaths.last()); | 823 | QStringList::Iterator it = d->searchPaths.find(d->searchPaths.last()); |
848 | if (it != d->searchPaths.end()) { | 824 | if (it != d->searchPaths.end()) { |
849 | d->searchPaths.insert(it, realPath); | 825 | d->searchPaths.insert(it, realPath); |
850 | } | 826 | } |
851 | } | 827 | } |
852 | 828 | ||
853 | 829 | ||
854 | /*! | 830 | /*! |
855 | Removes all occurrences of \a path (using exact matching) from the | 831 | Removes all occurrences of \a path (using exact matching) from the |
856 | settings search path for system \a s. Note that the default search | 832 | settings search path for system \a s. Note that the default search |
857 | paths cannot be removed. | 833 | paths cannot be removed. |
858 | 834 | ||
859 | \sa insertSearchPath() | 835 | \sa insertSearchPath() |
860 | */ | 836 | */ |
861 | void QSettings::removeSearchPath( System s, const QString &path) | 837 | void QSettings::removeSearchPath( System s, const QString &path) |
862 | { | 838 | { |
863 | if ( !qt_verify_key( path ) ) { | 839 | if ( !qt_verify_key( path ) ) { |
864 | #if defined(QT_CHECK_STATE) | 840 | #if defined(QT_CHECK_STATE) |
865 | qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() ); | 841 | qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() ); |
866 | #endif | 842 | #endif |
867 | return; | 843 | return; |
868 | } | 844 | } |
869 | 845 | ||
870 | #ifdef Q_WS_WIN | 846 | #ifdef Q_WS_WIN |
871 | if ( d->sysd ) { | 847 | if ( d->sysd ) { |
872 | d->sysRemoveSearchPath( s, path ); | 848 | d->sysRemoveSearchPath( s, path ); |
873 | return; | 849 | return; |
874 | } | 850 | } |
875 | #endif | 851 | #endif |
876 | #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) | 852 | #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) |
877 | if ( d->sysd && s != Unix ) { | 853 | if ( d->sysd && s != Unix ) { |
878 | #else | 854 | #else |
879 | if ( s != Unix ) { | 855 | if ( s != Unix ) { |
880 | #endif | 856 | #endif |
881 | #if !defined(QWS) && defined(Q_OS_MAC) | 857 | #if !defined(QWS) && defined(Q_OS_MAC) |
882 | if(s != Mac) //mac is respected on the mac as well | 858 | if(s != Mac) //mac is respected on the mac as well |
@@ -903,1151 +879,1186 @@ QSettings::QSettings() | |||
903 | d->sysd = 0; | 879 | d->sysd = 0; |
904 | d->sysInit(); | 880 | d->sysInit(); |
905 | #endif | 881 | #endif |
906 | } | 882 | } |
907 | 883 | ||
908 | /*! | 884 | /*! |
909 | Creates a settings object. If \a format is 'Ini' the settings will | 885 | Creates a settings object. If \a format is 'Ini' the settings will |
910 | be stored in a text file, using the Unix strategy (see above). If \a format | 886 | be stored in a text file, using the Unix strategy (see above). If \a format |
911 | is 'Native', the settings will be stored in a platform specific way | 887 | is 'Native', the settings will be stored in a platform specific way |
912 | (ie. the Windows registry). | 888 | (ie. the Windows registry). |
913 | */ | 889 | */ |
914 | QSettings::QSettings( Format format ) | 890 | QSettings::QSettings( Format format ) |
915 | { | 891 | { |
916 | d = new QSettingsPrivate( format ); | 892 | d = new QSettingsPrivate( format ); |
917 | Q_CHECK_PTR(d); | 893 | Q_CHECK_PTR(d); |
918 | 894 | ||
919 | #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) | 895 | #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) |
920 | d->sysd = 0; | 896 | d->sysd = 0; |
921 | if ( format == Native ) | 897 | if ( format == Native ) |
922 | d->sysInit(); | 898 | d->sysInit(); |
923 | #else | 899 | #else |
924 | Q_UNUSED(format); | 900 | Q_UNUSED(format); |
925 | #endif | 901 | #endif |
926 | } | 902 | } |
927 | 903 | ||
928 | /*! | 904 | /*! |
929 | Destroys the settings object. All modifications made to the settings | 905 | Destroys the settings object. All modifications made to the settings |
930 | will automatically be saved. | 906 | will automatically be saved. |
931 | 907 | ||
932 | */ | 908 | */ |
933 | QSettings::~QSettings() | 909 | QSettings::~QSettings() |
934 | { | 910 | { |
935 | sync(); | 911 | sync(); |
936 | 912 | ||
937 | #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) | 913 | #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) |
938 | if ( d->sysd ) | 914 | if ( d->sysd ) |
939 | d->sysClear(); | 915 | d->sysClear(); |
940 | #endif | 916 | #endif |
941 | 917 | ||
942 | delete d; | 918 | delete d; |
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 | */ |
950 | bool QSettings::sync() | 926 | bool 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(); |
1022 | if ( v.isNull() ) { | 1012 | if ( v.isNull() ) { |
1023 | v = "\\0"; // escape null string | 1013 | v = "\\0"; // escape null string |
1024 | } else { | 1014 | } else { |
1025 | v.replace("\\", "\\\\"); // escape backslash | 1015 | v.replace("\\", "\\\\"); // escape backslash |
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 | */ |
1073 | bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) | 1082 | bool 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 | */ |
1124 | double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) | 1134 | double 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 | */ |
1169 | int QSettings::readNumEntry(const QString &key, int def, bool *ok ) | 1180 | int 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 | */ |
1213 | QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) | 1225 | QString 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 | */ |
1291 | bool QSettings::writeEntry(const QString &key, bool value) | 1303 | bool 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 | */ |
1321 | bool QSettings::writeEntry(const QString &key, double value) | 1334 | bool 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 | */ |
1350 | bool QSettings::writeEntry(const QString &key, int value) | 1364 | bool 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 | */ |
1384 | bool QSettings::writeEntry(const QString &key, const char *value) | 1399 | bool 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 | */ |
1409 | bool QSettings::writeEntry(const QString &key, const QString &value) | 1417 | bool 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 | */ |
1470 | bool QSettings::removeEntry(const QString &key) | 1478 | bool 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 | */ |
1549 | QStringList QSettings::entryList(const QString &key) const | 1556 | QStringList 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 | } |
1618 | 1624 | ||
1619 | 1625 | ||
1620 | /*! | 1626 | /*! |
1621 | Returns a list of the keys which contain keys under \a key. Does \e | 1627 | Returns a list of the keys which contain keys under \a key. Does \e |
1622 | not return any keys that contain entries. | 1628 | not return any keys that contain entries. |
1623 | 1629 | ||
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 | */ |
1646 | QStringList QSettings::subkeyList(const QString &key) const | 1652 | QStringList 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 | */ |
1740 | QDateTime QSettings::lastModficationTime(const QString &key) | 1745 | QDateTime 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 | */ |
1804 | bool QSettings::writeEntry(const QString &key, const QStringList &value, | 1810 | bool 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 | */ |
1823 | bool QSettings::writeEntry(const QString &key, const QStringList &value) | 1829 | bool 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 | */ |
1872 | QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) | 1878 | QStringList 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); |
1879 | } | 1885 | } |
1880 | 1886 | ||
1881 | /*! | 1887 | /*! |
1882 | \fn QStringList QSettings::readListEntry(const QString &key, bool *ok ) const | 1888 | \fn QStringList QSettings::readListEntry(const QString &key, bool *ok ) const |
1883 | Reads the entry specified by \a key as a string. If \a ok is not | 1889 | Reads the entry specified by \a key as a string. If \a ok is not |
1884 | 0, \a *ok is set to TRUE if the key was read, otherwise \a *ok is | 1890 | 0, \a *ok is set to TRUE if the key was read, otherwise \a *ok is |
1885 | set to FALSE. | 1891 | set to FALSE. |
1886 | 1892 | ||
1887 | Note that if you want to iterate over the list, you should iterate | 1893 | Note that if you want to iterate over the list, you should iterate |
1888 | over a copy, e.g. | 1894 | over a copy, e.g. |
1889 | \code | 1895 | \code |
1890 | QStringList list = mySettings.readListEntry( "recentfiles" ); | 1896 | QStringList list = mySettings.readListEntry( "recentfiles" ); |
1891 | QStringList::Iterator it = list.begin(); | 1897 | QStringList::Iterator it = list.begin(); |
1892 | while( it != list.end() ) { | 1898 | while( it != list.end() ) { |
1893 | myProcessing( *it ); | 1899 | myProcessing( *it ); |
1894 | ++it; | 1900 | ++it; |
1895 | } | 1901 | } |
1896 | \endcode | 1902 | \endcode |
1897 | 1903 | ||
1898 | \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split() | 1904 | \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split() |
1899 | */ | 1905 | */ |
1900 | 1906 | ||
1901 | /*! | 1907 | /*! |
1902 | \internal | 1908 | \internal |
1903 | */ | 1909 | */ |
1904 | QStringList QSettings::readListEntry(const QString &key, bool *ok ) | 1910 | QStringList QSettings::readListEntry(const QString &key, bool *ok ) |
1905 | { | 1911 | { |
1906 | QString value = readEntry( key, QString::null, ok ); | 1912 | QString value = readEntry( key, QString::null, ok ); |
1907 | if ( ok && !*ok ) | 1913 | if ( ok && !*ok ) |
1908 | return QStringList(); | 1914 | return QStringList(); |
1909 | QStringList l; | 1915 | QStringList l; |
1910 | QString s; | 1916 | QString s; |
1911 | bool esc=FALSE; | 1917 | bool esc=FALSE; |
1912 | for (int i=0; i<(int)value.length(); i++) { | 1918 | for (int i=0; i<(int)value.length(); i++) { |
1913 | if ( esc ) { | 1919 | if ( esc ) { |
1914 | if ( value[i] == 'e' ) { // end-of-string | 1920 | if ( value[i] == 'e' ) { // end-of-string |
1915 | l.append(s); | 1921 | l.append(s); |
1916 | s=""; | 1922 | s=""; |
1917 | } else if ( value[i] == '0' ) { // null string | 1923 | } else if ( value[i] == '0' ) { // null string |
1918 | s=QString::null; | 1924 | s=QString::null; |
1919 | } else { | 1925 | } else { |
1920 | s.append(value[i]); | 1926 | s.append(value[i]); |
1921 | } | 1927 | } |
1922 | esc=FALSE; | 1928 | esc=FALSE; |
1923 | } else if ( value[i] == '^' ) { | 1929 | } else if ( value[i] == '^' ) { |
1924 | esc = TRUE; | 1930 | esc = TRUE; |
1925 | } else { | 1931 | } else { |
1926 | s.append(value[i]); | 1932 | s.append(value[i]); |
1927 | if ( i == (int)value.length()-1 ) | 1933 | if ( i == (int)value.length()-1 ) |
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 |
1935 | void qt_setSettingsBasePath(const QString &); //qsettings_mac.cpp | 1941 | void 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 | ||
1956 | void QSettings::setPath( const QString &domain, const QString &product, Scope scope ) | 1961 | void 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) |
1983 | QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + "."; | 1988 | if(lastDot != -1) { |
1984 | if ( !topLevelDomain.isEmpty() ) | 1989 | QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + "."; |
1985 | qt_setSettingsBasePath( topLevelDomain ); | 1990 | if ( !topLevelDomain.isEmpty() ) |
1986 | actualSearchPath = "/" + domain.left( lastDot ) + product; | 1991 | qt_setSettingsBasePath( topLevelDomain ); |
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 | */ |
2004 | void QSettings::beginGroup( const QString &group ) | 2015 | void 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 | ||
2014 | \code | 2025 | \code |
2015 | QSettings settings; | 2026 | QSettings settings; |
2016 | settings.beginGroup( "/MainWindow/Geometry" ); | 2027 | settings.beginGroup( "/MainWindow/Geometry" ); |
2017 | // read values | 2028 | // read values |
2018 | settings.endGroup(); | 2029 | settings.endGroup(); |
2019 | \endcode | 2030 | \endcode |
2020 | */ | 2031 | */ |
2021 | void QSettings::endGroup() | 2032 | void QSettings::endGroup() |
2022 | { | 2033 | { |
2023 | d->groupStack.pop(); | 2034 | d->groupStack.pop(); |
2024 | d->groupDirty = TRUE; | 2035 | d->groupDirty = TRUE; |
2025 | } | 2036 | } |
2026 | 2037 | ||
2027 | /*! | 2038 | /*! |
2028 | Set the current key prefix to the empty string. | 2039 | Set the current key prefix to the empty string. |
2029 | */ | 2040 | */ |
2030 | void QSettings::resetGroup() | 2041 | void QSettings::resetGroup() |
2031 | { | 2042 | { |
2032 | d->groupStack.clear(); | 2043 | d->groupStack.clear(); |
2033 | d->groupDirty = FALSE; | 2044 | d->groupDirty = FALSE; |
2034 | d->groupPrefix = QString::null; | 2045 | d->groupPrefix = QString::null; |
2035 | } | 2046 | } |
2036 | 2047 | ||
2037 | /*! | 2048 | /*! |
2038 | Returns the current key prefix, or a null string if there is no key prefix set. | 2049 | Returns the current key prefix, or a null string if there is no key prefix set. |
2039 | 2050 | ||
2040 | \sa beginGroup(); | 2051 | \sa beginGroup(); |
2041 | */ | 2052 | */ |
2042 | QString QSettings::group() const | 2053 | QString QSettings::group() const |
2043 | { | 2054 | { |
2044 | if ( d->groupDirty ) { | 2055 | if ( d->groupDirty ) { |
2045 | d->groupDirty = FALSE; | 2056 | d->groupDirty = FALSE; |
2046 | d->groupPrefix = QString::null; | 2057 | d->groupPrefix = QString::null; |
2047 | 2058 | ||
2048 | QValueStack<QString>::Iterator it = d->groupStack.begin(); | 2059 | QValueStack<QString>::Iterator it = d->groupStack.begin(); |
2049 | while ( it != d->groupStack.end() ) { | 2060 | while ( it != d->groupStack.end() ) { |
2050 | QString group = *it; | 2061 | QString group = *it; |
2051 | ++it; | 2062 | ++it; |
2052 | if ( group[0] != '/' ) | 2063 | if ( group[0] != '/' ) |
2053 | group.prepend( "/" ); | 2064 | group.prepend( "/" ); |