summaryrefslogtreecommitdiff
path: root/library
Unidiff
Diffstat (limited to 'library') (more/less context) (ignore whitespace changes)
-rw-r--r--library/config.cpp264
1 files changed, 122 insertions, 142 deletions
diff --git a/library/config.cpp b/library/config.cpp
index f68c336..e9cae4c 100644
--- a/library/config.cpp
+++ b/library/config.cpp
@@ -24,278 +24,258 @@
24#include <qtextcodec.h> 24#include <qtextcodec.h>
25#endif 25#endif
26#include <qtextstream.h> 26#include <qtextstream.h>
27 27
28#include <sys/stat.h> 28#include <sys/stat.h>
29#include <sys/types.h> 29#include <sys/types.h>
30#include <sys/time.h> 30#include <sys/time.h>
31#include <fcntl.h> 31#include <fcntl.h>
32#include <stdlib.h> 32#include <stdlib.h>
33#include <time.h> 33#include <time.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#include "qpeapplication.h" 39#include "qpeapplication.h"
40 40
41 41
42/* 42/*
43 * Internal Class 43 * Internal Class
44 */ 44 */
45class ConfigPrivate { 45class ConfigPrivate {
46public: 46public:
47 ConfigPrivate() : multilang(FALSE) {} 47 ConfigPrivate() : multilang(FALSE) {}
48 ConfigPrivate(const ConfigPrivate& o) : 48 ConfigPrivate(const ConfigPrivate& o) :
49 trfile(o.trfile), 49 trfile(o.trfile),
50 trcontext(o.trcontext), 50 trcontext(o.trcontext),
51 multilang(o.multilang) 51 multilang(o.multilang)
52 {} 52 {}
53 ConfigPrivate& operator=(const ConfigPrivate& o) 53 ConfigPrivate& operator=(const ConfigPrivate& o)
54 { 54 {
55 trfile = o.trfile; 55 trfile = o.trfile;
56 trcontext = o.trcontext; 56 trcontext = o.trcontext;
57 multilang = o.multilang; 57 multilang = o.multilang;
58 return *this; 58 return *this;
59 } 59 }
60 60
61 QString trfile; 61 QString trfile;
62 QCString trcontext; 62 QCString trcontext;
63 bool multilang; 63 bool multilang;
64}; 64};
65 65
66///////////////////////////////////////////////////////////////// 66/////////////////////////////////////////////////////////////////
67///////////////////////////////////////////////////////////////// 67/////////////////////////////////////////////////////////////////
68 68
69#ifndef Q_OS_WIN32 69#ifndef Q_OS_WIN32
70 70
71//#define DEBUG_CONFIG_CACHE 71//#define DEBUG_CONFIG_CACHE
72
73const int CONFIG_CACHE_SIZE = 8192;
74const int CONFIG_CACHE_TIMEOUT = 1000;
75
76class ConfigData 72class ConfigData
77{ 73{
78public: 74public:
79 ConfigData(const ConfigData& o) : 75 ConfigData() {}
80 cfg(o.cfg), 76 ConfigData( const ConfigGroupMap& cf, const ConfigPrivate& pri,
81 priv(o.priv ? new ConfigPrivate(*o.priv) : 0), 77 struct stat sbuf )
82 mtime(o.mtime), 78 : cfg( cf ), priv( pri ), mtime( sbuf.st_mtime ),
83 size(o.size), 79 size( sbuf.st_size )
84 used(o.used) 80 {
85 { } 81 gettimeofday(&used, 0 );
86 82 }
87 ConfigData& operator=(const ConfigData& o)
88 {
89 cfg = o.cfg;
90 delete priv;
91 priv = o.priv ? new ConfigPrivate(*o.priv) : 0;
92 mtime = o.mtime;
93 size = o.size;
94 used = o.used;
95 return *this;
96 }
97
98 ConfigData() : priv(0) {}
99 ~ConfigData() { delete priv; }
100 83
101 ConfigGroupMap cfg; 84 ConfigGroupMap cfg;
102 ConfigPrivate *priv; // Owned by this object 85 ConfigPrivate priv; // Owned by this object
103 time_t mtime; 86 time_t mtime;
104 unsigned int size; 87 unsigned int size;
105 struct timeval used; 88 struct timeval used;
106}; 89};
107 90
108class ConfigCache : public QObject
109{
110public:
111 ConfigCache();
112 91
113 void insert(const QString &filename, const ConfigGroupMap &cfg, const ConfigPrivate* priv); 92class ConfigCache : public QObject {
114 bool find(const QString &filename, ConfigGroupMap &cfg, ConfigPrivate*& priv); 93public:
115 void remove(const QString &filename); 94 static ConfigCache* instance();
116 95
96 void insert( const QString& fileName, const ConfigGroupMap& cfg,
97 const ConfigPrivate *priv );
98 bool find(const QString& fileName, ConfigGroupMap& cfg,
99 ConfigPrivate** priv );
117protected: 100protected:
118 void timerEvent(QTimerEvent *); 101 void timerEvent( QTimerEvent* );
119 102
120private: 103private:
104 ConfigCache();
105 void remove( const QString& fileName );
121 void removeLru(); 106 void removeLru();
122 107
123 QMap<QString, ConfigData> configData; 108private:
124 unsigned int totalsize; 109 QMap<QString, ConfigData> m_cached;
125 int tid; 110 unsigned int m_totalSize;
111 int m_tid;
112private:
113 static ConfigCache* m_inst;
114 static const unsigned int CONFIG_CACHE_SIZE = 8192;
115 static const unsigned int CONFIG_CACHE_TIMEOUT = 1000;
126}; 116};
127 117
128ConfigCache::ConfigCache() : QObject(), totalsize(0), tid(0) 118ConfigCache* ConfigCache::m_inst = 0;
129{ 119/*
130} 120 * get destroyed when qApp gets destroyed
131 121 */
132void ConfigCache::insert(const QString &filename, const ConfigGroupMap &cfg, const ConfigPrivate* priv) 122ConfigCache::ConfigCache() : QObject( qApp ), m_totalSize( 0 ), m_tid( 0 ) {}
133{ 123ConfigCache* ConfigCache::instance() {
134 // use stat() rather than QFileInfo for speed. 124 if ( !m_inst )
135 struct stat sbuf; 125 m_inst = new ConfigCache();
136 stat(filename.local8Bit().data(), &sbuf);
137
138 if (sbuf.st_size < CONFIG_CACHE_SIZE/2) {
139 ConfigData data;
140 data.cfg = cfg;
141 data.priv = priv ? new ConfigPrivate(*priv) : 0;
142 data.mtime = sbuf.st_mtime;
143 data.size = sbuf.st_size;
144 gettimeofday(&data.used, 0);
145
146 remove(filename);
147 configData.insert(filename, data);
148
149 totalsize += data.size;
150#ifdef DEBUG_CONFIG_CACHE
151 qDebug("++++++ insert %s", filename.latin1());
152#endif
153 }
154 126
155 if (totalsize > (uint)CONFIG_CACHE_SIZE) { 127 return m_inst;
156 // We'll delay deleting anything until later.
157 // This lets us grow quite large during some operations,
158 // but we'll be reduced to a decent size later.
159 // This works well with the main use case - app startup.
160 if (!tid)
161 tid = startTimer(CONFIG_CACHE_TIMEOUT);
162 }
163} 128}
164 129
165bool ConfigCache::find(const QString &filename, ConfigGroupMap &cfg, ConfigPrivate*& priv) 130void ConfigCache::remove( const QString& fileName ) {
166{ 131 QMap<QString, ConfigData>::Iterator it = m_cached.find( fileName );
167 QMap<QString, ConfigData>::Iterator it = configData.find(filename);
168 if (it != configData.end()) {
169 ConfigData data = *it;
170 // use stat() rather than QFileInfo for speed.
171 struct stat sbuf;
172 stat(filename.local8Bit().data(), &sbuf);
173
174 if (data.mtime == sbuf.st_mtime && (int)data.size == sbuf.st_size) {
175 cfg = data.cfg;
176 delete priv;
177 priv = data.priv ? new ConfigPrivate(*data.priv) : 0;
178 gettimeofday(&data.used, 0);
179#ifdef DEBUG_CONFIG_CACHE
180 qDebug("******* Cache hit: %s", filename.latin1());
181#endif
182 return TRUE;
183 }
184 }
185
186#ifdef DEBUG_CONFIG_CACHE
187 qDebug("------- Cache miss: %s", filename.latin1());
188#endif
189 132
190 return FALSE; 133 if ( it == m_cached.end() )
191} 134 return;
192 135
193void ConfigCache::remove(const QString &filename) 136 m_totalSize -= (*it).size;
194{ 137 m_cached.remove( it );
195 QMap<QString, ConfigData>::Iterator it = configData.find(filename);
196 if (it != configData.end()) {
197 totalsize -= (*it).size;
198 configData.remove(it);
199 }
200} 138}
201 139
202void ConfigCache::timerEvent(QTimerEvent *) 140void ConfigCache::removeLru() {
203{ 141 QMap<QString, ConfigData>::Iterator it = m_cached.begin();
204#ifdef DEBUG_CONFIG_CACHE
205 qDebug( "cache size: %d", totalsize);
206#endif
207 while (totalsize > (uint)CONFIG_CACHE_SIZE)
208 removeLru();
209 killTimer(tid);
210 tid = 0;
211}
212
213void ConfigCache::removeLru()
214{
215 QMap<QString, ConfigData>::Iterator it = configData.begin();
216 QMap<QString, ConfigData>::Iterator lru = it; 142 QMap<QString, ConfigData>::Iterator lru = it;
217 ++it; 143 ++it;
218 for (; it != configData.end(); ++it) { 144 for (; it != m_cached.end(); ++it)
219 if ((*it).used.tv_sec < (*lru).used.tv_sec || 145 if ((*it).used.tv_sec < (*lru).used.tv_sec ||
220 ((*it).used.tv_sec == (*lru).used.tv_sec && 146 ((*it).used.tv_sec == (*lru).used.tv_sec &&
221 (*it).used.tv_usec < (*lru).used.tv_usec)) 147 (*it).used.tv_usec < (*lru).used.tv_usec))
222 lru = it; 148 lru = it;
223 }
224 149
225#ifdef DEBUG_CONFIG_CACHE 150 qWarning( "Removing item" );
226 qDebug("Cache full, removing: %s", lru.key().latin1()); 151 m_totalSize -= (*lru).size;
227#endif 152 m_cached.remove(lru);
228 totalsize -= (*lru).size; 153}
229 configData.remove(lru); 154
155void ConfigCache::timerEvent( QTimerEvent* ) {
156 while ( m_totalSize > CONFIG_CACHE_SIZE )
157 removeLru();
158
159 killTimer(m_tid);
160 m_tid = 0;
230} 161}
231 162
232static ConfigCache *qpe_configCache = 0; 163void ConfigCache::insert( const QString& fileName, const ConfigGroupMap& cfg,
164 const ConfigPrivate* _priv ) {
233 165
234#endif /* Q_OS_WIN32 */
235 166
167 struct stat sbuf;
168 ::stat( QFile::encodeName(fileName), &sbuf );
169 if ( static_cast<unsigned int>(sbuf.st_size) >= CONFIG_CACHE_SIZE>>1)
170 return;
236 171
237// ========================================================================== 172 /*
173 * remove the old version and use the new one
174 */
175 ConfigPrivate priv = _priv ? *_priv : ConfigPrivate();
176 ConfigData data( cfg, priv, sbuf );
177 m_totalSize += data.size;
178
179 remove( fileName );
180 m_cached.insert( fileName, data );
181
182 /*
183 * we've overcommited allocation, let us clean up
184 * soon
185 */
186 if ( m_totalSize >= CONFIG_CACHE_SIZE )
187 if ( !m_tid )
188 m_tid = startTimer(CONFIG_CACHE_TIMEOUT);
189}
190
191bool ConfigCache::find( const QString& fileName, ConfigGroupMap& cfg,
192 ConfigPrivate **ppriv ) {
193 QMap<QString, ConfigData>::Iterator it = m_cached.find(fileName);
194 if (it != m_cached.end()) {
195 ConfigData &data = *it;
196 struct stat sbuf;
197 ::stat(QFile::encodeName( fileName ), &sbuf);
198
199 if (data.mtime == sbuf.st_mtime && (int)data.size == sbuf.st_size) {
200 cfg = data.cfg;
201
202 /*
203 * null pointer
204 */
205 if ( *ppriv == 0 )
206 *ppriv = new ConfigPrivate( data.priv );
207 **ppriv = data.priv;
208 gettimeofday(&data.used, 0);
209
210 return true;
211 }
212 }
213
214 return false;
215}
216
217#endif
238 218
239 219
240/*! 220/*!
241 \internal 221 \internal
242*/ 222*/
243QString Config::configFilename(const QString& name, Domain d) 223QString Config::configFilename(const QString& name, Domain d)
244{ 224{
245 switch (d) { 225 switch (d) {
246 case File: 226 case File:
247 return name; 227 return name;
248 case User: { 228 case User: {
249 QDir dir = (QString(getenv("HOME")) + "/Settings"); 229 QDir dir = (QString(getenv("HOME")) + "/Settings");
250 if ( !dir.exists() ) 230 if ( !dir.exists() )
251 mkdir(dir.path().local8Bit(),0700); 231 mkdir(dir.path().local8Bit(),0700);
252 return dir.path() + "/" + name + ".conf"; 232 return dir.path() + "/" + name + ".conf";
253 } 233 }
254 } 234 }
255 return name; 235 return name;
256} 236}
257 237
258/* This cannot be made public because of binary compat issues */ 238/* This cannot be made public because of binary compat issues */
259void Config::read( QTextStream &s ) 239void Config::read( QTextStream &s )
260{ 240{
261#if QT_VERSION <= 230 && defined(QT_NO_CODECS) 241#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
262 // The below should work, but doesn't in Qt 2.3.0 242 // The below should work, but doesn't in Qt 2.3.0
263 s.setCodec( QTextCodec::codecForMib( 106 ) ); 243 s.setCodec( QTextCodec::codecForMib( 106 ) );
264#else 244#else
265 s.setEncoding( QTextStream::UnicodeUTF8 ); 245 s.setEncoding( QTextStream::UnicodeUTF8 );
266#endif 246#endif
267 247
268 QStringList list = QStringList::split('\n', s.read() ); 248 QStringList list = QStringList::split('\n', s.read() );
269 249
270 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { 250 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
271 if ( !parse( *it ) ) { 251 if ( !parse( *it ) ) {
272 git = groups.end(); 252 git = groups.end();
273 return; 253 return;
274 } 254 }
275 } 255 }
276} 256}
277 257
278/*! 258/*!
279 \class Config config.h 259 \class Config config.h
280 \brief The Config class provides for saving application cofniguration state. 260 \brief The Config class provides for saving application cofniguration state.
281 261
282 You should keep a Config in existence only while you do not want others 262 You should keep a Config in existence only while you do not want others
283 to be able to change the state. There is no locking currently, but there 263 to be able to change the state. There is no locking currently, but there
284 may be in the future. 264 may be in the future.
285*/ 265*/
286 266
287/*! 267/*!
288 \enum Config::ConfigGroup 268 \enum Config::ConfigGroup
289 \internal 269 \internal
290*/ 270*/
291 271
292/*! 272/*!
293 \enum Config::Domain 273 \enum Config::Domain
294 274
295 \value File 275 \value File
296 \value User 276 \value User
297 277
298 See Config for details. 278 See Config for details.
299*/ 279*/
300 280
301/*! 281/*!
@@ -650,214 +630,214 @@ int Config::readNumEntry( const QString &key, int deflt )
650*/ 630*/
651bool Config::readBoolEntry( const QString &key, bool deflt ) 631bool Config::readBoolEntry( const QString &key, bool deflt )
652{ 632{
653 QString s = readEntry( key ); 633 QString s = readEntry( key );
654 if ( s.isEmpty() ) 634 if ( s.isEmpty() )
655 return deflt; 635 return deflt;
656 else 636 else
657 return (bool)s.toInt(); 637 return (bool)s.toInt();
658} 638}
659 639
660/*! 640/*!
661 \fn QStringList Config::readListEntry( const QString &key, const QChar &sep ) const 641 \fn QStringList Config::readListEntry( const QString &key, const QChar &sep ) const
662 Reads a string list entry stored with \a key, and with \a sep as the separator. 642 Reads a string list entry stored with \a key, and with \a sep as the separator.
663*/ 643*/
664 644
665/*! 645/*!
666 \internal 646 \internal
667 For compatibility, non-const version. 647 For compatibility, non-const version.
668*/ 648*/
669QStringList Config::readListEntry( const QString &key, const QChar &sep ) 649QStringList Config::readListEntry( const QString &key, const QChar &sep )
670{ 650{
671 QString s = readEntry( key ); 651 QString s = readEntry( key );
672 if ( s.isEmpty() ) 652 if ( s.isEmpty() )
673 return QStringList(); 653 return QStringList();
674 else 654 else
675 return QStringList::split( sep, s ); 655 return QStringList::split( sep, s );
676} 656}
677 657
678/*! 658/*!
679 Removes all entries from the current group. 659 Removes all entries from the current group.
680*/ 660*/
681void Config::clearGroup() 661void Config::clearGroup()
682{ 662{
683 if ( git == groups.end() ) { 663 if ( git == groups.end() ) {
684 qWarning( "no group set" ); 664 qWarning( "no group set" );
685 return; 665 return;
686 } 666 }
687 if ( !(*git).isEmpty() ) { 667 if ( !(*git).isEmpty() ) {
688 ( *git ).clear(); 668 ( *git ).clear();
689 changed = TRUE; 669 changed = TRUE;
690 } 670 }
691} 671}
692 672
693/*! 673/*!
694 \internal 674 \internal
695*/ 675*/
696void Config::write( const QString &fn ) 676void Config::write( const QString &fn )
697{ 677{
678 QString oldGroup = git.key();
679
698 QString strNewFile; 680 QString strNewFile;
699 if ( !fn.isEmpty() ) 681 if ( !fn.isEmpty() )
700 filename = fn; 682 filename = fn;
701 strNewFile = filename + ".new"; 683 strNewFile = filename + ".new";
702 684
703 QFile f( strNewFile ); 685 QFile f( strNewFile );
704 if ( !f.open( IO_WriteOnly|IO_Raw ) ) { 686 if ( !f.open( IO_WriteOnly|IO_Raw ) ) {
705 qWarning( "could not open for writing `%s'", strNewFile.latin1() ); 687 qWarning( "could not open for writing `%s'", strNewFile.latin1() );
706 git = groups.end(); 688 git = groups.end();
707 return; 689 return;
708 } 690 }
709 691
710 QString str; 692 QString str;
711 QCString cstr; 693 QCString cstr;
712 QMap< QString, ConfigGroup >::Iterator g_it = groups.begin(); 694 QMap< QString, ConfigGroup >::Iterator g_it = groups.begin();
713 695
714 for ( ; g_it != groups.end(); ++g_it ) { 696 for ( ; g_it != groups.end(); ++g_it ) {
715 str += "[" + g_it.key() + "]\n"; 697 str += "[" + g_it.key() + "]\n";
716 ConfigGroup::Iterator e_it = ( *g_it ).begin(); 698 ConfigGroup::Iterator e_it = ( *g_it ).begin();
717 for ( ; e_it != ( *g_it ).end(); ++e_it ) 699 for ( ; e_it != ( *g_it ).end(); ++e_it )
718 str += e_it.key() + " = " + *e_it + "\n"; 700 str += e_it.key() + " = " + *e_it + "\n";
719 } 701 }
720 cstr = str.utf8(); 702 cstr = str.utf8();
721 703
722 int total_length; 704 int total_length;
723 total_length = f.writeBlock( cstr.data(), cstr.length() ); 705 total_length = f.writeBlock( cstr.data(), cstr.length() );
724 if ( total_length != int(cstr.length()) ) { 706 if ( total_length != int(cstr.length()) ) {
725 QMessageBox::critical( 0, QObject::tr("Out of Space"), 707 QMessageBox::critical( 0, QObject::tr("Out of Space"),
726 QObject::tr("There was a problem creating\nConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") ); 708 QObject::tr("There was a problem creating\nConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") );
727 f.close(); 709 f.close();
728 QFile::remove( strNewFile ); 710 QFile::remove( strNewFile );
729 return; 711 return;
730 } 712 }
731 713
732 f.close(); 714 f.close();
733 // now rename the file... 715 // now rename the file...
734 if ( rename( strNewFile, filename ) < 0 ) { 716 if ( rename( strNewFile, filename ) < 0 ) {
735 qWarning( "problem renaming the file %s to %s", strNewFile.latin1(), 717 qWarning( "problem renaming the file %s to %s", strNewFile.latin1(),
736 filename.latin1() ); 718 filename.latin1() );
737 QFile::remove( strNewFile ); 719 QFile::remove( strNewFile );
738 return; 720 return;
739 } 721 }
740 722
741#ifndef Q_OS_WIN32 723#ifndef Q_OS_WIN32
742 if (qpe_configCache) 724 ConfigCache::instance()->insert( filename, groups, d );
743 qpe_configCache->insert(filename, groups, d); 725 setGroup( oldGroup );
744#endif 726#endif
745 changed = FALSE; 727 changed = FALSE;
746} 728}
747 729
748/*! 730/*!
749 Returns whether the Config is in a valid state. 731 Returns whether the Config is in a valid state.
750*/ 732*/
751bool Config::isValid() const 733bool Config::isValid() const
752{ 734{
753 return groups.end() != git; 735 return groups.end() != git;
754} 736}
755 737
756/*! 738/*!
757 \internal 739 \internal
758*/ 740*/
759void Config::read() 741void Config::read()
760{ 742{
761 changed = FALSE; 743 changed = FALSE;
762 744
763 QString readFilename(filename); 745 QString readFilename(filename);
764 746
765 if ( !QFile::exists(filename) ) { 747 if ( !QFile::exists(filename) ) {
766 bool failed = TRUE; 748 bool failed = TRUE;
767 QFileInfo fi(filename); 749 QFileInfo fi(filename);
768 QString settingsDir = QDir::homeDirPath() + "/Settings"; 750 QString settingsDir = QDir::homeDirPath() + "/Settings";
769 if (fi.dirPath(TRUE) == settingsDir) { 751 if (fi.dirPath(TRUE) == settingsDir) {
770 // User setting - see if there is a default in $OPIEDIR/etc/default/ 752 // User setting - see if there is a default in $OPIEDIR/etc/default/
771 QString dftlFile = QPEApplication::qpeDir() + "etc/default/" + fi.fileName(); 753 QString dftlFile = QPEApplication::qpeDir() + "etc/default/" + fi.fileName();
772 if (QFile::exists(dftlFile)) { 754 if (QFile::exists(dftlFile)) {
773 readFilename = dftlFile; 755 readFilename = dftlFile;
774 failed = FALSE; 756 failed = FALSE;
775 } 757 }
776 } 758 }
777 if (failed) { 759 if (failed) {
778 git = groups.end(); 760 git = groups.end();
779 return; 761 return;
780 } 762 }
781 } 763 }
782 764
783#ifndef Q_OS_WIN32 765#ifndef Q_OS_WIN32
784 if (!qpe_configCache)
785 qpe_configCache = new ConfigCache;
786 766
787 if (qpe_configCache->find(readFilename, groups, d)) { 767 if (ConfigCache::instance()->find(readFilename, groups, &d)) {
788 if ( d && d->multilang ) { 768 if ( d && d->multilang ) {
789 QStringList l = Global::languageList(); 769 QStringList l = Global::languageList();
790 lang = l[0]; 770 lang = l[0];
791 glang = l[1]; 771 glang = l[1];
792 } 772 }
793 git = groups.begin(); 773 git = groups.begin();
794 return; 774 return;
795 } 775 }
796#endif 776#endif
797 777
798 QFile f( readFilename ); 778 QFile f( readFilename );
799 if ( !f.open( IO_ReadOnly ) ) { 779 if ( !f.open( IO_ReadOnly ) ) {
800 git = groups.end(); 780 git = groups.end();
801 return; 781 return;
802 } 782 }
803 783
804 if (f.getch()!='[') { 784 if (f.getch()!='[') {
805 git = groups.end(); 785 git = groups.end();
806 return; 786 return;
807 } 787 }
808 f.ungetch('['); 788 f.ungetch('[');
809 789
810 QTextStream s( &f ); 790 QTextStream s( &f );
811 read( s ); 791 read( s );
812 f.close(); 792 f.close();
813 793
814#ifndef Q_OS_WIN32 794#ifndef Q_OS_WIN32
815 qpe_configCache->insert(readFilename, groups, d); 795 ConfigCache::instance()->insert(readFilename, groups, d);
816#endif 796#endif
817} 797}
818 798
819/*! 799/*!
820 \internal 800 \internal
821*/ 801*/
822bool Config::parse( const QString &l ) 802bool Config::parse( const QString &l )
823{ 803{
824 QString line = l.stripWhiteSpace(); 804 QString line = l.stripWhiteSpace();
825 if ( line[ 0 ] == QChar( '[' ) ) { 805 if ( line[ 0 ] == QChar( '[' ) ) {
826 QString gname = line; 806 QString gname = line;
827 gname = gname.remove( 0, 1 ); 807 gname = gname.remove( 0, 1 );
828 if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) ) 808 if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) )
829 gname = gname.remove( gname.length() - 1, 1 ); 809 gname = gname.remove( gname.length() - 1, 1 );
830 git = groups.insert( gname, ConfigGroup() ); 810 git = groups.insert( gname, ConfigGroup() );
831 } else if ( !line.isEmpty() ) { 811 } else if ( !line.isEmpty() ) {
832 if ( git == groups.end() ) 812 if ( git == groups.end() )
833 return FALSE; 813 return FALSE;
834 int eq = line.find( '=' ); 814 int eq = line.find( '=' );
835 if ( eq == -1 ) 815 if ( eq == -1 )
836 return FALSE; 816 return FALSE;
837 QString key = line.left(eq).stripWhiteSpace(); 817 QString key = line.left(eq).stripWhiteSpace();
838 QString value = line.mid(eq+1).stripWhiteSpace(); 818 QString value = line.mid(eq+1).stripWhiteSpace();
839 819
840 if ( git.key() == "Translation" ) { 820 if ( git.key() == "Translation" ) {
841 if ( key == "File" ) { 821 if ( key == "File" ) {
842 if ( !d ) 822 if ( !d )
843 d = new ConfigPrivate; 823 d = new ConfigPrivate;
844 d->trfile = value; 824 d->trfile = value;
845 } else if ( key == "Context" ) { 825 } else if ( key == "Context" ) {
846 if ( !d ) 826 if ( !d )
847 d = new ConfigPrivate; 827 d = new ConfigPrivate;
848 d->trcontext = value.latin1(); 828 d->trcontext = value.latin1();
849 } else if ( key.startsWith("Comment") ) { 829 } else if ( key.startsWith("Comment") ) {
850 return TRUE; // ignore comment for ts file 830 return TRUE; // ignore comment for ts file
851 } else { 831 } else {
852 return FALSE; // Unrecognized 832 return FALSE; // Unrecognized
853 } 833 }
854 } 834 }
855 835
856 int kl = key.length(); 836 int kl = key.length();
857 if ( kl > 1 && key[kl-1] == ']' && key[kl-2] != '[' ) { 837 if ( kl > 1 && key[kl-1] == ']' && key[kl-2] != '[' ) {
858 // Old-style translation (inefficient) 838 // Old-style translation (inefficient)
859 if ( !d ) 839 if ( !d )
860 d = new ConfigPrivate; 840 d = new ConfigPrivate;
861 if ( !d->multilang ) { 841 if ( !d->multilang ) {
862 QStringList l = Global::languageList(); 842 QStringList l = Global::languageList();
863 lang = l[0]; 843 lang = l[0];