8be7efbc707df81c5bb54f92491ce20153580da3
[duncan/yast2-qt4.git] / src / QY2Settings.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                          contributed Qt classes                      |
10 |                                                    (C) SuSE Linux AG |
11 \----------------------------------------------------------------------/
12
13   File:       QY2Settings.cpp
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17   This is a pure Qt class - it can be used independently of YaST2.
18
19 /-*/
20
21
22
23 #include "QY2Settings.h"
24
25 #include <qfile.h>
26 #include <qregexp.h>
27
28 #include <iostream>
29
30 using std::cout;
31 using std::cerr;
32 using std::endl;
33
34
35 QY2Settings::QY2Settings( const QString & fileName, AccessMode accessMode )
36     : _fileName( fileName )
37     , _accessMode( accessMode )
38 {
39     _sections.setAutoDelete( true );
40
41     if ( _accessMode == ReadOnly || _accessMode == ReadWrite )
42         load();
43     else
44         initSections();
45 }
46
47 void QY2Settings::initSections()
48 {
49     _defaultSection = new Section( "" );
50     Q_CHECK_PTR( _defaultSection );
51
52     _currentSection = _defaultSection;
53     _sections.insert( "", _defaultSection );
54 }
55
56
57
58 QY2Settings::~QY2Settings()
59 {
60     if ( _dirty && _accessMode != ReadOnly )
61         save();
62 }
63
64
65 bool QY2Settings::selectSection( const QString & sectionName )
66 {
67     _currentSection = _sections[ sectionName ];
68
69     if ( _currentSection )
70     {
71         return true;
72     }
73     else
74     {
75         _currentSection = _defaultSection;
76         return false;
77     }
78 }
79
80
81 void QY2Settings::selectDefaultSection()
82 {
83     _currentSection = _defaultSection;
84 }
85
86
87 QStringList QY2Settings::sections( bool includeUnnamed ) const
88 {
89     QStringList sectionList;
90     SectionIterator it( _sections );
91
92     while ( *it )
93     {
94         QString sectionName = (*it)->name();
95
96         if ( includeUnnamed || ! sectionName.isEmpty() )
97             sectionList.append( sectionName );
98
99         ++it;
100     }
101
102     return sectionList;
103 }
104
105
106 QString QY2Settings::get( const QString & key, const QString & fallback ) const
107 {
108     // Can't use operator[] here since we have a pointer
109
110     Section::const_iterator it = _currentSection->find( key );
111
112     if ( it == _currentSection->constEnd() )
113         return fallback;
114
115     return it.value();
116 }
117
118
119 QString QY2Settings::operator[] ( const QString & key )
120 {
121     return get( key );
122 }
123
124
125 bool QY2Settings::hasKey( const QString & key )
126 {
127     return _currentSection->contains( key );
128 }
129
130
131 QStringList QY2Settings::keys() const
132 {
133     QStringList keyList;
134
135     for ( Section::const_iterator it = _currentSection->constBegin();
136           it != _currentSection->constEnd();
137           ++it )
138     {
139         keyList.append( it.key() );
140     }
141
142     return keyList;
143 }
144
145
146 bool QY2Settings::load()
147 {
148     initSections();
149     _readError = false;
150     
151     if ( _accessMode == WriteOnly )
152         return false;
153
154     
155     QFile file( _fileName );
156
157     if ( ! file.open( QIODevice::ReadOnly ) )
158     {
159         cerr << "Can't load settings from " << qPrintable(_fileName)
160              << ": " << qPrintable(file.errorString())
161              << endl;
162         
163         _readError = true;
164         
165         return false;
166     }
167     
168     Q3TextStream str( &file );
169     str.setEncoding( Q3TextStream::UnicodeUTF8 );
170     QString line;
171     int lineCount = 0;
172
173     while ( ! file.atEnd() )
174     {
175         line = str.readLine().trimmed();
176         lineCount++;
177         
178         
179         // Skip empty lines
180         
181         if ( line.isEmpty() ) continue;
182
183         
184         // Skip comment lines
185
186         if ( line.startsWith( "#"  ) ) continue;
187         if ( line.startsWith( ";"  ) ) continue;
188         if ( line.startsWith( "//" ) ) continue;
189
190
191         if ( line.startsWith( "[" ) )
192         {
193             // New section
194
195             line.replace( QRegExp( "^\\[\\s*" ), "" );
196             line.replace( QRegExp( "\\s*\\].*$" ), "" );
197             addSection( line );
198         }
199         else if ( line.contains( "=" ) )
200         {
201             // key=value pair
202
203             QString key   = line.section( "=", 0, 0 ).trimmed();
204             QString value = line.section( "=", 1, 1 ).trimmed();
205
206             value.replace( QRegExp( "^\"" ), "" );      // strip leading "
207             value.replace( QRegExp( "\"$" ), "" );      // strip trailing "
208             value.replace( "\\\"", "\"" );              // un-escape "
209
210             // qDebug( "Read %s=%s", (const char *) key, (const char *) value );
211             set( key, value );
212         }
213         else
214         {
215             qWarning( "%s:%d: Syntax error: %s",
216                       qPrintable( _fileName), lineCount, qPrintable(line) );
217         }
218     }
219
220     _dirty = false;
221
222     return true;
223 }
224
225
226 bool QY2Settings::save()
227 {
228     if ( _accessMode == ReadOnly )
229         return false;
230
231     QFile file( _fileName );
232
233     if ( ! file.open( QIODevice::WriteOnly ) )
234     {
235         cerr << "Can't save settings to " << qPrintable(_fileName)
236              << ": " << qPrintable(file.errorString())
237              << endl;
238         
239         return false;
240     }
241     
242     Q3TextStream str( &file );
243     str.setEncoding( Q3TextStream::UnicodeUTF8 );
244
245     // The default section must be saved first since it doesn't have a section
246     // name that could be used for a headline
247     saveSection( str, _defaultSection );
248     
249     SectionIterator sectIt( _sections );
250     
251     while ( *sectIt )
252     {
253         if ( *sectIt != _defaultSection )
254             saveSection( str, *sectIt );
255         ++sectIt;
256     }
257
258     _dirty = false;
259
260     return true;
261 }
262
263
264 void QY2Settings::saveSection( Q3TextStream & str, Section * sect )
265 {
266     // Section header
267
268     if ( ! sect->name().isEmpty() )
269         str << "[" << sect->name() << "]" << endl;
270
271     // value=key pairs for this section
272
273     for ( Section::iterator it = sect->begin();
274           it != sect->end();
275           ++it )
276     {
277         QString value = it.value();
278         value.replace( "\"", "\\\"" );  // Escape embedded " with \"
279
280         str << it.key() << "= \"" << value << "\"" << endl;
281     }
282
283     str << endl;
284 }
285
286
287 void QY2Settings::set( const QString & key, const QString & value )
288 {
289     _currentSection->insert( key, value );
290     _dirty = true;
291 }
292
293
294 void QY2Settings::addSection( const QString & sectionName )
295 {
296     _currentSection = _sections[ sectionName ]; // already there?
297
298     if ( _currentSection )                      // -> use it
299         return;
300
301     _currentSection = new Section( sectionName );
302     Q_CHECK_PTR( _currentSection );
303
304     _sections.insert( sectionName, _currentSection );
305     _dirty = true;
306 }
307
308
309 void QY2Settings::clearSection()
310 {
311     _currentSection->clear();
312     _dirty = true;
313 }
314
315