KDECore
kconfigdata.h
Go to the documentation of this file.
00001 /* 00002 This file is part of the KDE libraries 00003 Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com> 00004 Copyright (c) 1999-2000 Preston Brown <pbrown@kde.org> 00005 Copyright (C) 1996-2000 Matthias Kalle Dalheimer <kalle@kde.org> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #ifndef KCONFIGDATA_H 00024 #define KCONFIGDATA_H 00025 00026 #include <QtCore/QByteArray> 00027 #include <QtCore/QString> 00028 #include <QtCore/QMap> 00029 #include <QtCore/QDebug> 00030 00035 struct KEntry 00036 { 00038 KEntry() 00039 : mValue(), bDirty(false), 00040 bGlobal(false), bImmutable(false), bDeleted(false), bExpand(false) {} 00042 QByteArray mValue; 00046 bool bDirty :1; 00050 bool bGlobal:1; 00054 bool bImmutable:1; 00058 bool bDeleted:1; 00062 bool bExpand:1; 00063 }; 00064 00065 // These operators are used to check whether an entry which is about 00066 // to be written equals the previous value. As such, this intentionally 00067 // omits the dirty flag from the comparison. 00068 inline bool operator ==(const KEntry &k1, const KEntry &k2) 00069 { 00070 return k1.bGlobal == k2.bGlobal && k1.bImmutable == k2.bImmutable 00071 && k1.bDeleted == k2.bDeleted && k1.bExpand == k2.bExpand 00072 && k1.mValue == k2.mValue; 00073 } 00074 00075 inline bool operator !=(const KEntry &k1, const KEntry &k2) 00076 { 00077 return !(k1 == k2); 00078 } 00079 00085 struct KEntryKey 00086 { 00088 KEntryKey(const QByteArray& _group = QByteArray(), 00089 const QByteArray& _key = QByteArray(), bool isLocalized=false, bool isDefault=false) 00090 : mGroup(_group), mKey(_key), bLocal(isLocalized), bDefault(isDefault), bRaw(false) 00091 { ; } 00095 QByteArray mGroup; 00099 QByteArray mKey; 00103 bool bLocal :1; 00107 bool bDefault:1; 00112 bool bRaw:1; 00113 }; 00114 00120 inline bool operator <(const KEntryKey &k1, const KEntryKey &k2) 00121 { 00122 int result = qstrcmp(k1.mGroup, k2.mGroup); 00123 if (result != 0) { 00124 return result < 0; 00125 } 00126 00127 result = qstrcmp(k1.mKey, k2.mKey); 00128 if (result != 0) { 00129 return result < 0; 00130 } 00131 00132 if (k1.bLocal != k2.bLocal) 00133 return k1.bLocal; 00134 return (!k1.bDefault && k2.bDefault); 00135 } 00136 00144 class KEntryMap : public QMap<KEntryKey, KEntry> 00145 { 00146 public: 00147 enum SearchFlag { 00148 SearchDefaults=1, 00149 SearchLocalized=2 00150 }; 00151 Q_DECLARE_FLAGS(SearchFlags, SearchFlag) 00152 00153 enum EntryOption { 00154 EntryDirty=1, 00155 EntryGlobal=2, 00156 EntryImmutable=4, 00157 EntryDeleted=8, 00158 EntryExpansion=16, 00159 EntryRawKey=32, 00160 EntryDefault=(SearchDefaults<<16), 00161 EntryLocalized=(SearchLocalized<<16) 00162 }; 00163 Q_DECLARE_FLAGS(EntryOptions, EntryOption) 00164 00165 Iterator findExactEntry(const QByteArray& group, const QByteArray& key = QByteArray(), 00166 SearchFlags flags = SearchFlags()) 00167 { 00168 KEntryKey theKey(group, key, false, bool(flags&SearchDefaults)); 00169 00170 // try the localized key first 00171 if (flags&SearchLocalized) { 00172 theKey.bLocal = true; 00173 return find(theKey); 00174 } 00175 return find(theKey); 00176 } 00177 00178 Iterator findEntry(const QByteArray& group, const QByteArray& key = QByteArray(), 00179 SearchFlags flags = SearchFlags()) 00180 { 00181 KEntryKey theKey(group, key, false, bool(flags&SearchDefaults)); 00182 00183 // try the localized key first 00184 if (flags&SearchLocalized) { 00185 theKey.bLocal = true; 00186 00187 Iterator it = find(theKey); 00188 if (it != end()) 00189 return it; 00190 00191 theKey.bLocal = false; 00192 } 00193 return find(theKey); 00194 } 00195 00196 ConstIterator findEntry(const QByteArray& group, const QByteArray& key = QByteArray(), 00197 SearchFlags flags = SearchFlags()) const 00198 { 00199 KEntryKey theKey(group, key, false, bool(flags&SearchDefaults)); 00200 00201 // try the localized key first 00202 if (flags&SearchLocalized) { 00203 theKey.bLocal = true; 00204 00205 ConstIterator it = find(theKey); 00206 if (it != constEnd()) 00207 return it; 00208 00209 theKey.bLocal = false; 00210 } 00211 return find(theKey); 00212 } 00213 00217 bool setEntry(const QByteArray& group, const QByteArray& key, 00218 const QByteArray& value, EntryOptions options) 00219 { 00220 KEntryKey k; 00221 KEntry e; 00222 bool newKey = false; 00223 00224 const Iterator it = findExactEntry(group, key, SearchFlags(options>>16)); 00225 00226 if (key.isEmpty()) { // inserting a group marker 00227 k.mGroup = group; 00228 e.bImmutable = (options&EntryImmutable); 00229 if (options&EntryDeleted) { qWarning("Internal KConfig error: cannot mark groups as deleted"); } 00230 if(it == end()) { 00231 insert(k, e); 00232 return true; 00233 } else if(it.value() == e) { 00234 return false; 00235 } 00236 00237 it.value() = e; 00238 return true; 00239 } 00240 00241 00242 if (it != end()) { 00243 if (it->bImmutable) 00244 return false; // we cannot change this entry. Inherits group immutability. 00245 k = it.key(); 00246 e = *it; 00247 } else { 00248 // make sure the group marker is in the map 00249 KEntryMap const *that = this; 00250 ConstIterator cit = that->findEntry(group); 00251 if (cit == constEnd()) 00252 insert(KEntryKey(group), KEntry()); 00253 else if (cit->bImmutable) 00254 return false; // this group is immutable, so we cannot change this entry. 00255 00256 k = KEntryKey(group, key); 00257 newKey = true; 00258 } 00259 00260 // set these here, since we may be changing the type of key from the one we found 00261 k.bLocal = (options&EntryLocalized); 00262 k.bDefault = (options&EntryDefault); 00263 k.bRaw = (options&EntryRawKey); 00264 00265 //qDebug() << "changing [" << group << "," << key << "] =" << e.mValue; 00266 e.mValue = value; 00267 e.bDirty = e.bDirty || (options&EntryDirty); 00268 e.bGlobal = (options&EntryGlobal); //we can't use || here, because changes to entries in 00269 //kdeglobals would be written to kdeglobals instead 00270 //of the local config file, regardless of the globals flag 00271 e.bImmutable = e.bImmutable || (options&EntryImmutable); 00272 if (value.isNull()) 00273 e.bDeleted = e.bDeleted || (options&EntryDeleted); 00274 else 00275 e.bDeleted = false; // setting a value to a previously deleted entry 00276 e.bExpand = (options&EntryExpansion); 00277 00278 //qDebug() << "to [" << group << "," << key << "] =" << e.mValue << "newKey=" << newKey; 00279 if(newKey) 00280 { 00281 insert(k, e); 00282 if(k.bDefault) 00283 { 00284 k.bDefault = false; 00285 insert(k, e); 00286 } 00287 // TODO check for presence of unlocalized key 00288 return true; 00289 } else { 00290 // KEntry e2 = it.value(); 00291 if(it.value() != e) 00292 { 00293 it.value() = e; 00294 if(k.bDefault) 00295 { 00296 k.bDefault = false; 00297 insert(k, e); 00298 } 00299 if (!(options & EntryLocalized)) { 00300 KEntryKey theKey(group, key, true, false); 00301 remove(theKey); 00302 if (k.bDefault) { 00303 theKey.bDefault = false; 00304 remove(theKey); 00305 } 00306 } 00307 return true; 00308 } else { 00309 if (!(options & EntryLocalized)) { 00310 KEntryKey theKey(group, key, true, false); 00311 bool ret = false; 00312 Iterator cit = find(theKey); 00313 if (cit != end()) { 00314 erase(cit); 00315 ret = true; 00316 } 00317 if (k.bDefault) { 00318 theKey.bDefault = false; 00319 Iterator cit = find(theKey); 00320 if (cit != end()) { 00321 erase(cit); 00322 return true; 00323 } 00324 } 00325 return ret; 00326 } 00327 // When we are writing a default, we know that the non- 00328 // default is the same as the default, so we can simply 00329 // use the same branch. 00330 return false; 00331 } 00332 } 00333 } 00334 00335 void setEntry(const QByteArray& group, const QByteArray& key, 00336 const QString & value, EntryOptions options) 00337 { 00338 setEntry(group, key, value.toUtf8(), options); 00339 } 00340 00341 QString getEntry(const QByteArray& group, const QByteArray& key, 00342 const QString & defaultValue = QString(), 00343 SearchFlags flags = SearchFlags(), 00344 bool * expand=0) const 00345 { 00346 const ConstIterator it = findEntry(group, key, flags); 00347 QString theValue = defaultValue; 00348 00349 if (it != constEnd() && !it->bDeleted) { 00350 if (!it->mValue.isNull()) { 00351 const QByteArray data=it->mValue; 00352 theValue = QString::fromUtf8(data.constData(), data.length()); 00353 if (expand) 00354 *expand = it->bExpand; 00355 } 00356 } 00357 00358 return theValue; 00359 } 00360 00361 00362 00363 bool hasEntry(const QByteArray& group, const QByteArray& key = QByteArray(), 00364 SearchFlags flags = SearchFlags()) const 00365 { 00366 const ConstIterator it = findEntry(group, key, flags); 00367 if (it == constEnd()) 00368 return false; 00369 if (it->bDeleted) 00370 return false; 00371 if (key.isNull()) { // looking for group marker 00372 return it->mValue.isNull(); 00373 } 00374 return true; 00375 } 00376 00377 bool getEntryOption(const ConstIterator& it, EntryOption option) const 00378 { 00379 if (it != constEnd()) { 00380 switch (option) { 00381 case EntryDirty: 00382 return it->bDirty; 00383 case EntryLocalized: 00384 return it.key().bLocal; 00385 case EntryGlobal: 00386 return it->bGlobal; 00387 case EntryImmutable: 00388 return it->bImmutable; 00389 case EntryDeleted: 00390 return it->bDeleted; 00391 case EntryExpansion: 00392 return it->bExpand; 00393 default: 00394 break; // fall through 00395 } 00396 } 00397 00398 return false; 00399 } 00400 bool getEntryOption(const QByteArray& group, const QByteArray& key, 00401 SearchFlags flags, EntryOption option) const 00402 { 00403 return getEntryOption(findEntry(group, key, flags), option); 00404 } 00405 00406 void setEntryOption(Iterator it, EntryOption option, bool bf) 00407 { 00408 if (it != end()) { 00409 switch (option) { 00410 case EntryDirty: 00411 it->bDirty = bf; 00412 break; 00413 case EntryGlobal: 00414 it->bGlobal = bf; 00415 break; 00416 case EntryImmutable: 00417 it->bImmutable = bf; 00418 break; 00419 case EntryDeleted: 00420 it->bDeleted = bf; 00421 break; 00422 case EntryExpansion: 00423 it->bExpand = bf; 00424 break; 00425 default: 00426 break; // fall through 00427 } 00428 } 00429 } 00430 void setEntryOption(const QByteArray& group, const QByteArray& key, SearchFlags flags, 00431 EntryOption option, bool bf) 00432 { 00433 setEntryOption(findEntry(group, key, flags), option, bf); 00434 } 00435 00436 void revertEntry(const QByteArray& group, const QByteArray& key, SearchFlags flags=SearchFlags()) 00437 { 00438 Iterator entry = findEntry(group, key, flags); 00439 if (entry != end()) { 00440 //qDebug() << "reverting [" << group << "," << key << "] = " << entry->mValue; 00441 const ConstIterator defaultEntry(entry+1); 00442 if (defaultEntry != constEnd() && defaultEntry.key().bDefault) { 00443 *entry = *defaultEntry; 00444 entry->bDirty = true; 00445 } else if (!entry->mValue.isNull()){ 00446 entry->mValue = QByteArray(); 00447 entry->bDirty = true; 00448 entry->bDeleted = true; 00449 } 00450 //qDebug() << "to [" << group << "," << key << "] =" << entry->mValue; 00451 } 00452 } 00453 }; 00454 Q_DECLARE_OPERATORS_FOR_FLAGS(KEntryMap::SearchFlags) 00455 Q_DECLARE_OPERATORS_FOR_FLAGS(KEntryMap::EntryOptions) 00456 00462 typedef QMap<KEntryKey, KEntry>::Iterator KEntryMapIterator; 00463 00471 typedef QMap<KEntryKey, KEntry>::ConstIterator KEntryMapConstIterator; 00472 00473 #endif
KDE 4.6 API Reference