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