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