summaryrefslogtreecommitdiff
authorsandman <sandman>2002-11-01 12:55:33 (UTC)
committer sandman <sandman>2002-11-01 12:55:33 (UTC)
commit14bd24ba233e370b44ec23cab2733289a3387ca7 (patch) (unidiff)
tree5dc1bd3b37521f8817e0cef9fb19446b8d8e09f1
parent2c809a930ac38a95727c777f52e6673e316d25f2 (diff)
downloadopie-14bd24ba233e370b44ec23cab2733289a3387ca7.zip
opie-14bd24ba233e370b44ec23cab2733289a3387ca7.tar.gz
opie-14bd24ba233e370b44ec23cab2733289a3387ca7.tar.bz2
Config ignores comment lines now (all lines that start with a '#'). This is
necessary to load some pixmap themes from KDE and shouldn't change anything else ('#' not at the beginning of a line are not treated as a comment)
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--library/config.cpp4
1 files changed, 4 insertions, 0 deletions
diff --git a/library/config.cpp b/library/config.cpp
index e07eecb..1121cd4 100644
--- a/library/config.cpp
+++ b/library/config.cpp
@@ -1,554 +1,558 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#include <qdir.h> 21#include <qdir.h>
22#include <qfile.h> 22#include <qfile.h>
23#include <qfileinfo.h> 23#include <qfileinfo.h>
24#include <qmessagebox.h> 24#include <qmessagebox.h>
25#if QT_VERSION <= 230 && defined(QT_NO_CODECS) 25#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
26#include <qtextcodec.h> 26#include <qtextcodec.h>
27#endif 27#endif
28#include <qtextstream.h> 28#include <qtextstream.h>
29 29
30#include <sys/stat.h> 30#include <sys/stat.h>
31#include <sys/types.h> 31#include <sys/types.h>
32#include <fcntl.h> 32#include <fcntl.h>
33#include <stdlib.h> 33#include <stdlib.h>
34#include <unistd.h> 34#include <unistd.h>
35 35
36#define QTOPIA_INTERNAL_LANGLIST 36#define QTOPIA_INTERNAL_LANGLIST
37#include "config.h" 37#include "config.h"
38#include "global.h" 38#include "global.h"
39 39
40 40
41/*! 41/*!
42 \internal 42 \internal
43*/ 43*/
44QString Config::configFilename(const QString& name, Domain d) 44QString Config::configFilename(const QString& name, Domain d)
45{ 45{
46 switch (d) { 46 switch (d) {
47 case File: 47 case File:
48 return name; 48 return name;
49 case User: { 49 case User: {
50 QDir dir = (QString(getenv("HOME")) + "/Settings"); 50 QDir dir = (QString(getenv("HOME")) + "/Settings");
51 if ( !dir.exists() ) 51 if ( !dir.exists() )
52 mkdir(dir.path().local8Bit(),0700); 52 mkdir(dir.path().local8Bit(),0700);
53 return dir.path() + "/" + name + ".conf"; 53 return dir.path() + "/" + name + ".conf";
54 } 54 }
55 } 55 }
56 return name; 56 return name;
57} 57}
58 58
59/*! 59/*!
60 \class Config config.h 60 \class Config config.h
61 \brief The Config class provides for saving application cofniguration state. 61 \brief The Config class provides for saving application cofniguration state.
62 62
63 You should keep a Config in existence only while you do not want others 63 You should keep a Config in existence only while you do not want others
64 to be able to change the state. There is no locking currently, but there 64 to be able to change the state. There is no locking currently, but there
65 may be in the future. 65 may be in the future.
66*/ 66*/
67 67
68/*! 68/*!
69 \enum Config::ConfigGroup 69 \enum Config::ConfigGroup
70 \internal 70 \internal
71*/ 71*/
72 72
73/*! 73/*!
74 \enum Config::Domain 74 \enum Config::Domain
75 75
76 \value File 76 \value File
77 \value User 77 \value User
78 78
79 See Config for details. 79 See Config for details.
80*/ 80*/
81 81
82/*! 82/*!
83 Constructs a config that will load or create a configuration with the 83 Constructs a config that will load or create a configuration with the
84 given \a name in the given \a domain. 84 given \a name in the given \a domain.
85 85
86 You must call setGroup() before doing much else with the Config. 86 You must call setGroup() before doing much else with the Config.
87 87
88 In the default Domain, \e User, 88 In the default Domain, \e User,
89 the configuration is user-specific. \a name should not contain "/" in 89 the configuration is user-specific. \a name should not contain "/" in
90 this case, and in general should be the name of the C++ class that is 90 this case, and in general should be the name of the C++ class that is
91 primarily responsible for maintaining the configuration. 91 primarily responsible for maintaining the configuration.
92 92
93 In the File Domain, \a name is an absolute filename. 93 In the File Domain, \a name is an absolute filename.
94*/ 94*/
95Config::Config( const QString &name, Domain domain ) 95Config::Config( const QString &name, Domain domain )
96 : filename( configFilename(name,domain) ) 96 : filename( configFilename(name,domain) )
97{ 97{
98 git = groups.end(); 98 git = groups.end();
99 read(); 99 read();
100 QStringList l = Global::languageList(); 100 QStringList l = Global::languageList();
101 lang = l[0]; 101 lang = l[0];
102 glang = l[1]; 102 glang = l[1];
103} 103}
104 104
105/*! 105/*!
106 Writes any changes to disk and destroys the in-memory object. 106 Writes any changes to disk and destroys the in-memory object.
107*/ 107*/
108Config::~Config() 108Config::~Config()
109{ 109{
110 if ( changed ) 110 if ( changed )
111 write(); 111 write();
112} 112}
113 113
114/*! 114/*!
115 Returns whether the current group has an entry called \a key. 115 Returns whether the current group has an entry called \a key.
116*/ 116*/
117bool Config::hasKey( const QString &key ) const 117bool Config::hasKey( const QString &key ) const
118{ 118{
119 if ( groups.end() == git ) 119 if ( groups.end() == git )
120 return FALSE; 120 return FALSE;
121 ConfigGroup::ConstIterator it = ( *git ).find( key ); 121 ConfigGroup::ConstIterator it = ( *git ).find( key );
122 return it != ( *git ).end(); 122 return it != ( *git ).end();
123} 123}
124 124
125/*! 125/*!
126 Sets the current group for subsequent reading and writing of 126 Sets the current group for subsequent reading and writing of
127 entries to \a gname. Grouping allows the application to partition the namespace. 127 entries to \a gname. Grouping allows the application to partition the namespace.
128 128
129 This function must be called prior to any reading or writing 129 This function must be called prior to any reading or writing
130 of entries. 130 of entries.
131 131
132 The \a gname must not be empty. 132 The \a gname must not be empty.
133*/ 133*/
134void Config::setGroup( const QString &gname ) 134void Config::setGroup( const QString &gname )
135{ 135{
136 QMap< QString, ConfigGroup>::Iterator it = groups.find( gname ); 136 QMap< QString, ConfigGroup>::Iterator it = groups.find( gname );
137 if ( it == groups.end() ) { 137 if ( it == groups.end() ) {
138 git = groups.insert( gname, ConfigGroup() ); 138 git = groups.insert( gname, ConfigGroup() );
139 changed = TRUE; 139 changed = TRUE;
140 return; 140 return;
141 } 141 }
142 git = it; 142 git = it;
143} 143}
144 144
145/*! 145/*!
146 Writes a (\a key, \a value) entry to the current group. 146 Writes a (\a key, \a value) entry to the current group.
147 147
148 \sa readEntry() 148 \sa readEntry()
149*/ 149*/
150void Config::writeEntry( const QString &key, const char* value ) 150void Config::writeEntry( const QString &key, const char* value )
151{ 151{
152 writeEntry(key,QString(value)); 152 writeEntry(key,QString(value));
153} 153}
154 154
155/*! 155/*!
156 Writes a (\a key, \a value) entry to the current group. 156 Writes a (\a key, \a value) entry to the current group.
157 157
158 \sa readEntry() 158 \sa readEntry()
159*/ 159*/
160void Config::writeEntry( const QString &key, const QString &value ) 160void Config::writeEntry( const QString &key, const QString &value )
161{ 161{
162 if ( git == groups.end() ) { 162 if ( git == groups.end() ) {
163 qWarning( "no group set" ); 163 qWarning( "no group set" );
164 return; 164 return;
165 } 165 }
166 if ( (*git)[key] != value ) { 166 if ( (*git)[key] != value ) {
167 ( *git ).insert( key, value ); 167 ( *git ).insert( key, value );
168 changed = TRUE; 168 changed = TRUE;
169 } 169 }
170} 170}
171 171
172/* 172/*
173 Note that the degree of protection offered by the encryption here is 173 Note that the degree of protection offered by the encryption here is
174 only sufficient to avoid the most casual observation of the configuration 174 only sufficient to avoid the most casual observation of the configuration
175 files. People with access to the files can write down the contents and 175 files. People with access to the files can write down the contents and
176 decrypt it using this source code. 176 decrypt it using this source code.
177 177
178 Conceivably, and at some burden to the user, this encryption could 178 Conceivably, and at some burden to the user, this encryption could
179 be improved. 179 be improved.
180*/ 180*/
181static QString encipher(const QString& plain) 181static QString encipher(const QString& plain)
182{ 182{
183 // mainly, we make it long 183 // mainly, we make it long
184 QString cipher; 184 QString cipher;
185 int mix=28730492; 185 int mix=28730492;
186 for (int i=0; i<(int)plain.length(); i++) { 186 for (int i=0; i<(int)plain.length(); i++) {
187 int u = plain[i].unicode(); 187 int u = plain[i].unicode();
188 int c = u ^ mix; 188 int c = u ^ mix;
189 QString x = QString::number(c,36); 189 QString x = QString::number(c,36);
190 cipher.append(QChar('a'+x.length())); 190 cipher.append(QChar('a'+x.length()));
191 cipher.append(x); 191 cipher.append(x);
192 mix *= u; 192 mix *= u;
193 } 193 }
194 return cipher; 194 return cipher;
195} 195}
196 196
197static QString decipher(const QString& cipher) 197static QString decipher(const QString& cipher)
198{ 198{
199 QString plain; 199 QString plain;
200 int mix=28730492; 200 int mix=28730492;
201 for (int i=0; i<(int)cipher.length();) { 201 for (int i=0; i<(int)cipher.length();) {
202 int l = cipher[i].unicode()-'a'; 202 int l = cipher[i].unicode()-'a';
203 QString x = cipher.mid(i+1,l); i+=l+1; 203 QString x = cipher.mid(i+1,l); i+=l+1;
204 int u = x.toInt(0,36) ^ mix; 204 int u = x.toInt(0,36) ^ mix;
205 plain.append(QChar(u)); 205 plain.append(QChar(u));
206 mix *= u; 206 mix *= u;
207 } 207 }
208 return plain; 208 return plain;
209} 209}
210 210
211/*! 211/*!
212 Writes an encrypted (\a key, \a value) entry to the current group. 212 Writes an encrypted (\a key, \a value) entry to the current group.
213 213
214 Note that the degree of protection offered by the encryption is 214 Note that the degree of protection offered by the encryption is
215 only sufficient to avoid the most casual observation of the configuration 215 only sufficient to avoid the most casual observation of the configuration
216 files. 216 files.
217 217
218 \sa readEntry() 218 \sa readEntry()
219*/ 219*/
220void Config::writeEntryCrypt( const QString &key, const QString &value ) 220void Config::writeEntryCrypt( const QString &key, const QString &value )
221{ 221{
222 if ( git == groups.end() ) { 222 if ( git == groups.end() ) {
223 qWarning( "no group set" ); 223 qWarning( "no group set" );
224 return; 224 return;
225 } 225 }
226 QString evalue = encipher(value); 226 QString evalue = encipher(value);
227 if ( (*git)[key] != evalue ) { 227 if ( (*git)[key] != evalue ) {
228 ( *git ).insert( key, evalue ); 228 ( *git ).insert( key, evalue );
229 changed = TRUE; 229 changed = TRUE;
230 } 230 }
231} 231}
232 232
233/*! 233/*!
234 Writes a (\a key, \a num) entry to the current group. 234 Writes a (\a key, \a num) entry to the current group.
235 235
236 \sa readNumEntry() 236 \sa readNumEntry()
237*/ 237*/
238void Config::writeEntry( const QString &key, int num ) 238void Config::writeEntry( const QString &key, int num )
239{ 239{
240 QString s; 240 QString s;
241 s.setNum( num ); 241 s.setNum( num );
242 writeEntry( key, s ); 242 writeEntry( key, s );
243} 243}
244 244
245#ifdef Q_HAS_BOOL_TYPE 245#ifdef Q_HAS_BOOL_TYPE
246/*! 246/*!
247 Writes a (\a key, \a b) entry to the current group. This is equivalent 247 Writes a (\a key, \a b) entry to the current group. This is equivalent
248 to writing a 0 or 1 as an integer entry. 248 to writing a 0 or 1 as an integer entry.
249 249
250 \sa readBoolEntry() 250 \sa readBoolEntry()
251*/ 251*/
252void Config::writeEntry( const QString &key, bool b ) 252void Config::writeEntry( const QString &key, bool b )
253{ 253{
254 QString s; 254 QString s;
255 s.setNum( ( int )b ); 255 s.setNum( ( int )b );
256 writeEntry( key, s ); 256 writeEntry( key, s );
257} 257}
258#endif 258#endif
259 259
260/*! 260/*!
261 Writes a (\a key, \a lst) entry to the current group. The list 261 Writes a (\a key, \a lst) entry to the current group. The list
262 is separated by \a sep, so the strings must not contain that character. 262 is separated by \a sep, so the strings must not contain that character.
263 263
264 \sa readListEntry() 264 \sa readListEntry()
265*/ 265*/
266void Config::writeEntry( const QString &key, const QStringList &lst, const QChar &sep ) 266void Config::writeEntry( const QString &key, const QStringList &lst, const QChar &sep )
267{ 267{
268 QString s; 268 QString s;
269 QStringList::ConstIterator it = lst.begin(); 269 QStringList::ConstIterator it = lst.begin();
270 for ( ; it != lst.end(); ++it ) 270 for ( ; it != lst.end(); ++it )
271 s += *it + sep; 271 s += *it + sep;
272 writeEntry( key, s ); 272 writeEntry( key, s );
273} 273}
274 274
275/*! 275/*!
276 Removes the \a key entry from the current group. Does nothing if 276 Removes the \a key entry from the current group. Does nothing if
277 there is no such entry. 277 there is no such entry.
278*/ 278*/
279 279
280void Config::removeEntry( const QString &key ) 280void Config::removeEntry( const QString &key )
281{ 281{
282 if ( git == groups.end() ) { 282 if ( git == groups.end() ) {
283 qWarning( "no group set" ); 283 qWarning( "no group set" );
284 return; 284 return;
285 } 285 }
286 ( *git ).remove( key ); 286 ( *git ).remove( key );
287 changed = TRUE; 287 changed = TRUE;
288} 288}
289 289
290/*! 290/*!
291 \fn bool Config::operator == ( const Config & other ) const 291 \fn bool Config::operator == ( const Config & other ) const
292 292
293 Tests for equality with \a other. Config objects are equal if they refer to the same filename. 293 Tests for equality with \a other. Config objects are equal if they refer to the same filename.
294*/ 294*/
295 295
296/*! 296/*!
297 \fn bool Config::operator != ( const Config & other ) const 297 \fn bool Config::operator != ( const Config & other ) const
298 298
299 Tests for inequality with \a other. Config objects are equal if they refer to the same filename. 299 Tests for inequality with \a other. Config objects are equal if they refer to the same filename.
300*/ 300*/
301 301
302/*! 302/*!
303 \fn QString Config::readEntry( const QString &key, const QString &deflt ) const 303 \fn QString Config::readEntry( const QString &key, const QString &deflt ) const
304 304
305 Reads a string entry stored with \a key, defaulting to \a deflt if there is no entry. 305 Reads a string entry stored with \a key, defaulting to \a deflt if there is no entry.
306*/ 306*/
307 307
308/*! 308/*!
309 \internal 309 \internal
310 For compatibility, non-const version. 310 For compatibility, non-const version.
311*/ 311*/
312QString Config::readEntry( const QString &key, const QString &deflt ) 312QString Config::readEntry( const QString &key, const QString &deflt )
313{ 313{
314 QString res = readEntryDirect( key+"["+lang+"]" ); 314 QString res = readEntryDirect( key+"["+lang+"]" );
315 if ( !res.isNull() ) 315 if ( !res.isNull() )
316 return res; 316 return res;
317 if ( !glang.isEmpty() ) { 317 if ( !glang.isEmpty() ) {
318 res = readEntryDirect( key+"["+glang+"]" ); 318 res = readEntryDirect( key+"["+glang+"]" );
319 if ( !res.isNull() ) 319 if ( !res.isNull() )
320 return res; 320 return res;
321 } 321 }
322 return readEntryDirect( key, deflt ); 322 return readEntryDirect( key, deflt );
323} 323}
324 324
325/*! 325/*!
326 \fn QString Config::readEntryCrypt( const QString &key, const QString &deflt ) const 326 \fn QString Config::readEntryCrypt( const QString &key, const QString &deflt ) const
327 327
328 Reads an encrypted string entry stored with \a key, defaulting to \a deflt if there is no entry. 328 Reads an encrypted string entry stored with \a key, defaulting to \a deflt if there is no entry.
329*/ 329*/
330 330
331/*! 331/*!
332 \internal 332 \internal
333 For compatibility, non-const version. 333 For compatibility, non-const version.
334*/ 334*/
335QString Config::readEntryCrypt( const QString &key, const QString &deflt ) 335QString Config::readEntryCrypt( const QString &key, const QString &deflt )
336{ 336{
337 QString res = readEntryDirect( key+"["+lang+"]" ); 337 QString res = readEntryDirect( key+"["+lang+"]" );
338 if ( res.isNull() && glang.isEmpty() ) 338 if ( res.isNull() && glang.isEmpty() )
339 res = readEntryDirect( key+"["+glang+"]" ); 339 res = readEntryDirect( key+"["+glang+"]" );
340 if ( res.isNull() ) 340 if ( res.isNull() )
341 res = readEntryDirect( key, QString::null ); 341 res = readEntryDirect( key, QString::null );
342 if ( res.isNull() ) 342 if ( res.isNull() )
343 return deflt; 343 return deflt;
344 return decipher(res); 344 return decipher(res);
345} 345}
346 346
347/*! 347/*!
348 \fn QString Config::readEntryDirect( const QString &key, const QString &deflt ) const 348 \fn QString Config::readEntryDirect( const QString &key, const QString &deflt ) const
349 \internal 349 \internal
350*/ 350*/
351 351
352/*! 352/*!
353 \internal 353 \internal
354 For compatibility, non-const version. 354 For compatibility, non-const version.
355*/ 355*/
356QString Config::readEntryDirect( const QString &key, const QString &deflt ) 356QString Config::readEntryDirect( const QString &key, const QString &deflt )
357{ 357{
358 if ( git == groups.end() ) { 358 if ( git == groups.end() ) {
359 //qWarning( "no group set" ); 359 //qWarning( "no group set" );
360 return deflt; 360 return deflt;
361 } 361 }
362 ConfigGroup::ConstIterator it = ( *git ).find( key ); 362 ConfigGroup::ConstIterator it = ( *git ).find( key );
363 if ( it != ( *git ).end() ) 363 if ( it != ( *git ).end() )
364 return *it; 364 return *it;
365 else 365 else
366 return deflt; 366 return deflt;
367} 367}
368 368
369/*! 369/*!
370 \fn int Config::readNumEntry( const QString &key, int deflt ) const 370 \fn int Config::readNumEntry( const QString &key, int deflt ) const
371 Reads a numeric entry stored with \a key, defaulting to \a deflt if there is no entry. 371 Reads a numeric entry stored with \a key, defaulting to \a deflt if there is no entry.
372*/ 372*/
373 373
374/*! 374/*!
375 \internal 375 \internal
376 For compatibility, non-const version. 376 For compatibility, non-const version.
377*/ 377*/
378int Config::readNumEntry( const QString &key, int deflt ) 378int Config::readNumEntry( const QString &key, int deflt )
379{ 379{
380 QString s = readEntry( key ); 380 QString s = readEntry( key );
381 if ( s.isEmpty() ) 381 if ( s.isEmpty() )
382 return deflt; 382 return deflt;
383 else 383 else
384 return s.toInt(); 384 return s.toInt();
385} 385}
386 386
387/*! 387/*!
388 \fn bool Config::readBoolEntry( const QString &key, bool deflt ) const 388 \fn bool Config::readBoolEntry( const QString &key, bool deflt ) const
389 Reads a bool entry stored with \a key, defaulting to \a deflt if there is no entry. 389 Reads a bool entry stored with \a key, defaulting to \a deflt if there is no entry.
390*/ 390*/
391 391
392/*! 392/*!
393 \internal 393 \internal
394 For compatibility, non-const version. 394 For compatibility, non-const version.
395*/ 395*/
396bool Config::readBoolEntry( const QString &key, bool deflt ) 396bool Config::readBoolEntry( const QString &key, bool deflt )
397{ 397{
398 QString s = readEntry( key ); 398 QString s = readEntry( key );
399 if ( s.isEmpty() ) 399 if ( s.isEmpty() )
400 return deflt; 400 return deflt;
401 else 401 else
402 return (bool)s.toInt(); 402 return (bool)s.toInt();
403} 403}
404 404
405/*! 405/*!
406 \fn QStringList Config::readListEntry( const QString &key, const QChar &sep ) const 406 \fn QStringList Config::readListEntry( const QString &key, const QChar &sep ) const
407 Reads a string list entry stored with \a key, and with \a sep as the separator. 407 Reads a string list entry stored with \a key, and with \a sep as the separator.
408*/ 408*/
409 409
410/*! 410/*!
411 \internal 411 \internal
412 For compatibility, non-const version. 412 For compatibility, non-const version.
413*/ 413*/
414QStringList Config::readListEntry( const QString &key, const QChar &sep ) 414QStringList Config::readListEntry( const QString &key, const QChar &sep )
415{ 415{
416 QString s = readEntry( key ); 416 QString s = readEntry( key );
417 if ( s.isEmpty() ) 417 if ( s.isEmpty() )
418 return QStringList(); 418 return QStringList();
419 else 419 else
420 return QStringList::split( sep, s ); 420 return QStringList::split( sep, s );
421} 421}
422 422
423/*! 423/*!
424 Removes all entries from the current group. 424 Removes all entries from the current group.
425*/ 425*/
426void Config::clearGroup() 426void Config::clearGroup()
427{ 427{
428 if ( git == groups.end() ) { 428 if ( git == groups.end() ) {
429 qWarning( "no group set" ); 429 qWarning( "no group set" );
430 return; 430 return;
431 } 431 }
432 if ( !(*git).isEmpty() ) { 432 if ( !(*git).isEmpty() ) {
433 ( *git ).clear(); 433 ( *git ).clear();
434 changed = TRUE; 434 changed = TRUE;
435 } 435 }
436} 436}
437 437
438/*! 438/*!
439 \internal 439 \internal
440*/ 440*/
441void Config::write( const QString &fn ) 441void Config::write( const QString &fn )
442{ 442{
443 QString strNewFile; 443 QString strNewFile;
444 if ( !fn.isEmpty() ) 444 if ( !fn.isEmpty() )
445 filename = fn; 445 filename = fn;
446 strNewFile = filename + ".new"; 446 strNewFile = filename + ".new";
447 447
448 QFile f( strNewFile ); 448 QFile f( strNewFile );
449 if ( !f.open( IO_WriteOnly|IO_Raw ) ) { 449 if ( !f.open( IO_WriteOnly|IO_Raw ) ) {
450 qWarning( "could not open for writing `%s'", strNewFile.latin1() ); 450 qWarning( "could not open for writing `%s'", strNewFile.latin1() );
451 git = groups.end(); 451 git = groups.end();
452 return; 452 return;
453 } 453 }
454 454
455 QString str; 455 QString str;
456 QCString cstr; 456 QCString cstr;
457 QMap< QString, ConfigGroup >::Iterator g_it = groups.begin(); 457 QMap< QString, ConfigGroup >::Iterator g_it = groups.begin();
458 458
459 for ( ; g_it != groups.end(); ++g_it ) { 459 for ( ; g_it != groups.end(); ++g_it ) {
460 str += "[" + g_it.key() + "]\n"; 460 str += "[" + g_it.key() + "]\n";
461 ConfigGroup::Iterator e_it = ( *g_it ).begin(); 461 ConfigGroup::Iterator e_it = ( *g_it ).begin();
462 for ( ; e_it != ( *g_it ).end(); ++e_it ) 462 for ( ; e_it != ( *g_it ).end(); ++e_it )
463 str += e_it.key() + " = " + *e_it + "\n"; 463 str += e_it.key() + " = " + *e_it + "\n";
464 } 464 }
465 cstr = str.utf8(); 465 cstr = str.utf8();
466 466
467 int total_length; 467 int total_length;
468 total_length = f.writeBlock( cstr.data(), cstr.length() ); 468 total_length = f.writeBlock( cstr.data(), cstr.length() );
469 if ( total_length != int(cstr.length()) ) { 469 if ( total_length != int(cstr.length()) ) {
470 QMessageBox::critical( 0, QObject::tr("Out of Space"), 470 QMessageBox::critical( 0, QObject::tr("Out of Space"),
471 QObject::tr("There was a problem creating\nConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") ); 471 QObject::tr("There was a problem creating\nConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") );
472 f.close(); 472 f.close();
473 QFile::remove( strNewFile ); 473 QFile::remove( strNewFile );
474 return; 474 return;
475 } 475 }
476 476
477 f.close(); 477 f.close();
478 // now rename the file... 478 // now rename the file...
479 if ( rename( strNewFile, filename ) < 0 ) { 479 if ( rename( strNewFile, filename ) < 0 ) {
480 qWarning( "problem renaming the file %s to %s", strNewFile.latin1(), 480 qWarning( "problem renaming the file %s to %s", strNewFile.latin1(),
481 filename.latin1() ); 481 filename.latin1() );
482 QFile::remove( strNewFile ); 482 QFile::remove( strNewFile );
483 } 483 }
484} 484}
485 485
486/*! 486/*!
487 Returns whether the Config is in a valid state. 487 Returns whether the Config is in a valid state.
488*/ 488*/
489bool Config::isValid() const 489bool Config::isValid() const
490{ 490{
491 return groups.end() != git; 491 return groups.end() != git;
492} 492}
493 493
494/*! 494/*!
495 \internal 495 \internal
496*/ 496*/
497void Config::read() 497void Config::read()
498{ 498{
499 changed = FALSE; 499 changed = FALSE;
500 500
501 if ( !QFileInfo( filename ).exists() ) { 501 if ( !QFileInfo( filename ).exists() ) {
502 git = groups.end(); 502 git = groups.end();
503 return; 503 return;
504 } 504 }
505 505
506 QFile f( filename ); 506 QFile f( filename );
507 if ( !f.open( IO_ReadOnly ) ) { 507 if ( !f.open( IO_ReadOnly ) ) {
508 git = groups.end(); 508 git = groups.end();
509 return; 509 return;
510 } 510 }
511 511
512 QTextStream s( &f ); 512 QTextStream s( &f );
513#if QT_VERSION <= 230 && defined(QT_NO_CODECS) 513#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
514 // The below should work, but doesn't in Qt 2.3.0 514 // The below should work, but doesn't in Qt 2.3.0
515 s.setCodec( QTextCodec::codecForMib( 106 ) ); 515 s.setCodec( QTextCodec::codecForMib( 106 ) );
516#else 516#else
517 s.setEncoding( QTextStream::UnicodeUTF8 ); 517 s.setEncoding( QTextStream::UnicodeUTF8 );
518#endif 518#endif
519 519
520 QStringList list = QStringList::split('\n', s.read() ); 520 QStringList list = QStringList::split('\n', s.read() );
521 f.close(); 521 f.close();
522 522
523 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { 523 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
524 if ( !parse( *it ) ) { 524 if ( !parse( *it ) ) {
525 git = groups.end(); 525 git = groups.end();
526 return; 526 return;
527 } 527 }
528 } 528 }
529} 529}
530 530
531/*! 531/*!
532 \internal 532 \internal
533*/ 533*/
534bool Config::parse( const QString &l ) 534bool Config::parse( const QString &l )
535{ 535{
536 QString line = l.stripWhiteSpace(); 536 QString line = l.stripWhiteSpace();
537
538 if ( line [0] == QChar ( '#' ))
539 return true; // ignore comments
540
537 if ( line[ 0 ] == QChar( '[' ) ) { 541 if ( line[ 0 ] == QChar( '[' ) ) {
538 QString gname = line; 542 QString gname = line;
539 gname = gname.remove( 0, 1 ); 543 gname = gname.remove( 0, 1 );
540 if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) ) 544 if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) )
541 gname = gname.remove( gname.length() - 1, 1 ); 545 gname = gname.remove( gname.length() - 1, 1 );
542 git = groups.insert( gname, ConfigGroup() ); 546 git = groups.insert( gname, ConfigGroup() );
543 } else if ( !line.isEmpty() ) { 547 } else if ( !line.isEmpty() ) {
544 if ( git == groups.end() ) 548 if ( git == groups.end() )
545 return FALSE; 549 return FALSE;
546 int eq = line.find( '=' ); 550 int eq = line.find( '=' );
547 if ( eq == -1 ) 551 if ( eq == -1 )
548 return FALSE; 552 return FALSE;
549 QString key = line.left(eq).stripWhiteSpace(); 553 QString key = line.left(eq).stripWhiteSpace();
550 QString value = line.mid(eq+1).stripWhiteSpace(); 554 QString value = line.mid(eq+1).stripWhiteSpace();
551 ( *git ).insert( key, value ); 555 ( *git ).insert( key, value );
552 } 556 }
553 return TRUE; 557 return TRUE;
554} 558}