00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "kconfiggroup.h"
00024 #include "kconfiggroup_p.h"
00025
00026 #include <config.h>
00027
00028 #include "kconfig.h"
00029 #include "kconfig_p.h"
00030 #include "ksharedconfig.h"
00031 #include "kstringhandler.h"
00032 #include "kcomponentdata.h"
00033 #include "kstandarddirs.h"
00034 #include "kconfigdata.h"
00035 #include "kde_file.h"
00036 #include <kdebug.h>
00037
00038 #include <QtCore/QDate>
00039 #include <QtCore/QSharedData>
00040 #include <QtCore/QFile>
00041 #include <QtCore/QPoint>
00042 #include <QtCore/QRect>
00043 #include <QtCore/QString>
00044 #include <QtCore/QTextStream>
00045 #include <QtCore/QDir>
00046
00047 #include <stdlib.h>
00048
00049 class KConfigGroupPrivate : public QSharedData
00050 {
00051 public:
00052 KConfigGroupPrivate(KConfig* owner, bool isImmutable, bool isConst, const QByteArray &name)
00053 : mOwner(owner), mName(name), bImmutable(isImmutable), bConst(isConst)
00054 {
00055 }
00056
00057 KConfigGroupPrivate(const KSharedConfigPtr &owner, const QByteArray& name)
00058 : sOwner(owner), mOwner(sOwner.data()), mName(name),
00059 bImmutable(name.isEmpty()? owner->isImmutable(): owner->isGroupImmutable(name)), bConst(false)
00060 {
00061 }
00062
00063 KConfigGroupPrivate(KConfigGroup* parent, bool isImmutable, bool isConst, const QByteArray& name)
00064 : sOwner(parent->d->sOwner), mOwner(parent->d->mOwner), mName(name),
00065 bImmutable(isImmutable), bConst(isConst)
00066 {
00067 if (!parent->d->mName.isEmpty())
00068 mParent = parent->d;
00069 }
00070
00071 KConfigGroupPrivate(const KConfigGroupPrivate* other, bool isImmutable, const QByteArray &name)
00072 : sOwner(other->sOwner), mOwner(other->mOwner), mName(name),
00073 bImmutable(isImmutable), bConst(other->bConst)
00074 {
00075 if (!other->mName.isEmpty())
00076 mParent = const_cast<KConfigGroupPrivate *>(other);
00077 }
00078
00079 KSharedConfig::Ptr sOwner;
00080 KConfig *mOwner;
00081 QExplicitlySharedDataPointer<KConfigGroupPrivate> mParent;
00082 QByteArray mName;
00083
00084
00085 const bool bImmutable:1;
00086 const bool bConst:1;
00087
00088 QByteArray fullName() const
00089 {
00090 if (!mParent) {
00091 return name();
00092 }
00093 return mParent->fullName(mName);
00094 }
00095
00096 QByteArray name() const
00097 {
00098 if (mName.isEmpty())
00099 return "<default>";
00100 return mName;
00101 }
00102
00103 QByteArray fullName(const QByteArray& aGroup) const
00104 {
00105 if (mName.isEmpty())
00106 return aGroup;
00107 return fullName() + '\x1d' + aGroup;
00108 }
00109
00110 static QString expandString(const QString& value);
00111
00112 static QExplicitlySharedDataPointer<KConfigGroupPrivate> create(KConfigBase *master,
00113 const QByteArray &name,
00114 bool isImmutable,
00115 bool isConst)
00116 {
00117 QExplicitlySharedDataPointer<KConfigGroupPrivate> data;
00118 if (dynamic_cast<KConfigGroup*>(master))
00119 data = new KConfigGroupPrivate(dynamic_cast<KConfigGroup*>(master), isImmutable, isConst, name);
00120 else
00121 data = new KConfigGroupPrivate(dynamic_cast<KConfig*>(master), isImmutable, isConst, name);
00122 return data;
00123 }
00124
00125 static QByteArray serializeList(const QList<QByteArray> &list);
00126 static QStringList deserializeList(const QString &data);
00127 };
00128
00129 QByteArray KConfigGroupPrivate::serializeList(const QList<QByteArray> &list)
00130 {
00131 QByteArray value = "";
00132
00133 if (!list.isEmpty()) {
00134 QList<QByteArray>::ConstIterator it = list.constBegin();
00135 const QList<QByteArray>::ConstIterator end = list.constEnd();
00136
00137 value = QByteArray(*it).replace('\\', "\\\\").replace(',', "\\,");
00138
00139 while (++it != end) {
00140
00141
00142 value.reserve(4096);
00143
00144 value += ',';
00145 value += QByteArray(*it).replace('\\', "\\\\").replace(',', "\\,");
00146 }
00147
00148
00149 if (value.isEmpty())
00150 value = "\\0";
00151 }
00152
00153 return value;
00154 }
00155
00156 QStringList KConfigGroupPrivate::deserializeList(const QString &data)
00157 {
00158 if (data.isEmpty())
00159 return QStringList();
00160 if (data == "\\0")
00161 return QStringList(QString());
00162 QStringList value;
00163 QString val;
00164 val.reserve(data.size());
00165 bool quoted = false;
00166 for (int p = 0; p < data.length(); p++) {
00167 if (quoted) {
00168 val += data[p];
00169 quoted = false;
00170 } else if (data[p] == '\\') {
00171 quoted = true;
00172 } else if (data[p] == ',') {
00173 val.squeeze();
00174 value.append(val);
00175 val.clear();
00176 val.reserve(data.size() - p);
00177 } else {
00178 val += data[p];
00179 }
00180 }
00181 value.append(val);
00182 return value;
00183 }
00184
00185 static QList<int> asIntList(const QByteArray& string)
00186 {
00187 QList<int> list;
00188 Q_FOREACH(const QByteArray& s, string.split(','))
00189 list << s.toInt();
00190 return list;
00191 }
00192
00193 static QList<qreal> asRealList(const QByteArray& string)
00194 {
00195 QList<qreal> list;
00196 Q_FOREACH(const QByteArray& s, string.split(','))
00197 list << s.toDouble();
00198 return list;
00199 }
00200
00201 static QString errString( const char * pKey, const QByteArray & value, const QVariant & aDefault ) {
00202 return QString::fromLatin1("\"%1\" - conversion of \"%3\" to %2 failed")
00203 .arg(pKey).arg(QVariant::typeToName(aDefault.type())).arg(value.constData());
00204 }
00205
00206 static QString formatError( int expected, int got ) {
00207 return QString::fromLatin1(" (wrong format: expected %1 items, got %2)").arg( expected ).arg( got );
00208 }
00209
00210 QVariant KConfigGroup::convertToQVariant(const char *pKey, const QByteArray& value, const QVariant& aDefault)
00211 {
00212
00213
00214
00215 switch( aDefault.type() ) {
00216 case QVariant::Invalid:
00217 return QVariant();
00218 case QVariant::String:
00219
00220
00221
00222 return QString::fromUtf8(value);
00223 case QVariant::List:
00224 case QVariant::StringList:
00225 return KConfigGroupPrivate::deserializeList(QString::fromUtf8(value));
00226 case QVariant::ByteArray:
00227 return value;
00228 case QVariant::Bool: {
00229 const QByteArray lower(value.toLower());
00230 if (lower == "false" || lower == "no" || lower == "off" || lower == "0")
00231 return false;
00232 return true;
00233 }
00234 case QVariant::Double:
00235 case QVariant::Int:
00236 case QVariant::UInt:
00237 case QVariant::LongLong:
00238 case QVariant::ULongLong: {
00239 QVariant tmp = value;
00240 if ( !tmp.convert(aDefault.type()) )
00241 tmp = aDefault;
00242 return tmp;
00243 }
00244 case QVariant::Point: {
00245 const QList<int> list = asIntList(value);
00246
00247 if ( list.count() != 2 ) {
00248 kError() << errString( pKey, value, aDefault )
00249 << formatError( 2, list.count() );
00250 return aDefault;
00251 }
00252 return QPoint(list.at( 0 ), list.at( 1 ));
00253 }
00254 case QVariant::PointF: {
00255 const QList<qreal> list = asRealList(value);
00256
00257 if ( list.count() != 2 ) {
00258 kError() << errString( pKey, value, aDefault )
00259 << formatError( 2, list.count() );
00260 return aDefault;
00261 }
00262 return QPointF(list.at( 0 ), list.at( 1 ));
00263 }
00264 case QVariant::Rect: {
00265 const QList<int> list = asIntList(value);
00266
00267 if ( list.count() != 4 ) {
00268 kError() << errString( pKey, value, aDefault )
00269 << formatError( 4, list.count() );
00270 return aDefault;
00271 }
00272 const QRect rect(list.at( 0 ), list.at( 1 ), list.at( 2 ), list.at( 3 ));
00273 if ( !rect.isValid() ) {
00274 kError() << errString( pKey, value, aDefault );
00275 return aDefault;
00276 }
00277 return rect;
00278 }
00279 case QVariant::RectF: {
00280 const QList<qreal> list = asRealList(value);
00281
00282 if ( list.count() != 4 ) {
00283 kError() << errString( pKey, value, aDefault )
00284 << formatError( 4, list.count() );
00285 return aDefault;
00286 }
00287 const QRectF rect(list.at( 0 ), list.at( 1 ), list.at( 2 ), list.at( 3 ));
00288 if ( !rect.isValid() ) {
00289 kError() << errString( pKey, value, aDefault );
00290 return aDefault;
00291 }
00292 return rect;
00293 }
00294 case QVariant::Size: {
00295 const QList<int> list = asIntList(value);
00296
00297 if ( list.count() != 2 ) {
00298 kError() << errString( pKey, value, aDefault )
00299 << formatError( 2, list.count() );
00300 return aDefault;
00301 }
00302 const QSize size(list.at( 0 ), list.at( 1 ));
00303 if ( !size.isValid() ) {
00304 kError() << errString( pKey, value, aDefault );
00305 return aDefault;
00306 }
00307 return size;
00308 }
00309 case QVariant::SizeF: {
00310 const QList<qreal> list = asRealList(value);
00311
00312 if ( list.count() != 2 ) {
00313 kError() << errString( pKey, value, aDefault )
00314 << formatError( 2, list.count() );
00315 return aDefault;
00316 }
00317 const QSizeF size(list.at( 0 ), list.at( 1 ));
00318 if ( !size.isValid() ) {
00319 kError() << errString( pKey, value, aDefault );
00320 return aDefault;
00321 }
00322 return size;
00323 }
00324 case QVariant::DateTime: {
00325 const QList<int> list = asIntList(value);
00326 if ( list.count() != 6 ) {
00327 kError() << errString( pKey, value, aDefault )
00328 << formatError( 6, list.count() );
00329 return aDefault;
00330 }
00331 const QDate date( list.at( 0 ), list.at( 1 ), list.at( 2 ) );
00332 const QTime time( list.at( 3 ), list.at( 4 ), list.at( 5 ) );
00333 const QDateTime dt( date, time );
00334 if ( !dt.isValid() ) {
00335 kError() << errString( pKey, value, aDefault );
00336 return aDefault;
00337 }
00338 return dt;
00339 }
00340 case QVariant::Date: {
00341 QList<int> list = asIntList(value);
00342 if ( list.count() == 6 )
00343 list = list.mid(0, 3);
00344 if ( list.count() != 3 ) {
00345 kError() << errString( pKey, value, aDefault )
00346 << formatError( 3, list.count() );
00347 return aDefault;
00348 }
00349 const QDate date( list.at( 0 ), list.at( 1 ), list.at( 2 ) );
00350 if ( !date.isValid() ) {
00351 kError() << errString( pKey, value, aDefault );
00352 return aDefault;
00353 }
00354 return date;
00355 }
00356 case QVariant::Color:
00357 case QVariant::Font:
00358 kWarning() << "KConfigGroup::readEntry was passed GUI type '"
00359 << aDefault.typeName()
00360 << "' but kdeui isn't linked! If it is linked to your program, "
00361 "this is a platform bug. Please inform the KDE developers";
00362 break;
00363 case QVariant::Url:
00364 return QUrl(QString::fromUtf8(value));
00365
00366 default:
00367 if( aDefault.canConvert<KUrl>() ) {
00368 const KUrl url(QString::fromUtf8(value));
00369 return qVariantFromValue<KUrl>( url );
00370 }
00371 break;
00372 }
00373
00374 kWarning() << "unhandled type " << aDefault.typeName();
00375 return QVariant();
00376 }
00377
00378 QString KConfigGroupPrivate::expandString(const QString& value)
00379 {
00380 QString aValue = value;
00381
00382
00383 int nDollarPos = aValue.indexOf( '$' );
00384 while( nDollarPos != -1 && nDollarPos+1 < aValue.length()) {
00385
00386 if( aValue[nDollarPos+1] == '(' ) {
00387 int nEndPos = nDollarPos+1;
00388
00389 while ( (nEndPos <= aValue.length()) && (aValue[nEndPos]!=')') )
00390 nEndPos++;
00391 nEndPos++;
00392 QString cmd = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
00393
00394 QString result;
00395 QByteArray oldpath = qgetenv( "PATH" );
00396 QByteArray newpath = QFile::encodeName( KGlobal::dirs()->resourceDirs( "exe" ).join( QChar( KPATH_SEPARATOR ) ) );
00397 if( !newpath.isEmpty() && !oldpath.isEmpty() )
00398 newpath += KPATH_SEPARATOR;
00399 newpath += oldpath;
00400 setenv( "PATH", newpath, 1 );
00401 FILE *fs = popen(QFile::encodeName(cmd).data(), "r");
00402 if (fs) {
00403 QTextStream ts(fs, QIODevice::ReadOnly);
00404 result = ts.readAll().trimmed();
00405 pclose(fs);
00406 }
00407 setenv( "PATH", oldpath, 1 );
00408 aValue.replace( nDollarPos, nEndPos-nDollarPos, result );
00409 nDollarPos += result.length();
00410 } else if( aValue[nDollarPos+1] != '$' ) {
00411 int nEndPos = nDollarPos+1;
00412
00413 QString aVarName;
00414 if ( aValue[nEndPos]=='{' ) {
00415 while ( (nEndPos <= aValue.length()) && (aValue[nEndPos]!='}') )
00416 nEndPos++;
00417 nEndPos++;
00418 aVarName = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
00419 } else {
00420 while ( nEndPos <= aValue.length() &&
00421 (aValue[nEndPos].isNumber() ||
00422 aValue[nEndPos].isLetter() ||
00423 aValue[nEndPos]=='_' ) )
00424 nEndPos++;
00425 aVarName = aValue.mid( nDollarPos+1, nEndPos-nDollarPos-1 );
00426 }
00427 QString env;
00428 if (!aVarName.isEmpty()) {
00429 #ifdef Q_OS_WIN
00430 if (aVarName == "HOME")
00431 env = QDir::homePath();
00432 else
00433 #endif
00434 {
00435 QByteArray pEnv = qgetenv( aVarName.toAscii() );
00436 if( !pEnv.isEmpty() )
00437
00438
00439
00440 env = KStringHandler::from8Bit( pEnv );
00441 }
00442 aValue.replace(nDollarPos, nEndPos-nDollarPos, env);
00443 nDollarPos += env.length();
00444 } else
00445 aValue.remove( nDollarPos, nEndPos-nDollarPos );
00446 } else {
00447
00448 aValue.remove( nDollarPos, 1 );
00449 nDollarPos++;
00450 }
00451 nDollarPos = aValue.indexOf( '$', nDollarPos );
00452 }
00453
00454 return aValue;
00455 }
00456
00457 #ifdef Q_WS_WIN
00458 # include <QtCore/QDir>
00459 #endif
00460
00461 static bool cleanHomeDirPath( QString &path, const QString &homeDir )
00462 {
00463 #ifdef Q_WS_WIN //safer
00464 if (!QDir::convertSeparators(path).startsWith(QDir::convertSeparators(homeDir)))
00465 return false;
00466 #else
00467 if (!path.startsWith(homeDir))
00468 return false;
00469 #endif
00470
00471 int len = homeDir.length();
00472
00473 if (len && (path.length() == len || path[len] == '/')) {
00474 path.replace(0, len, QString::fromLatin1("$HOME"));
00475 return true;
00476 } else
00477 return false;
00478 }
00479
00480 static QString translatePath( QString path )
00481 {
00482 if (path.isEmpty())
00483 return path;
00484
00485
00486 path.replace('$', "$$");
00487
00488 bool startsWithFile = path.startsWith(QLatin1String("file:"), Qt::CaseInsensitive);
00489
00490
00491
00492 if ((!startsWithFile && QFileInfo(path).isRelative()) ||
00493 (startsWithFile && QFileInfo(path.mid(5)).isRelative()))
00494 return path;
00495
00496 if (startsWithFile)
00497 path.remove(0,5);
00498
00499
00500 while (path[0] == '/' && path[1] == '/')
00501 path.remove(0,1);
00502
00503
00504
00505
00506
00507 const QString homeDir0 = QFile::decodeName(qgetenv("HOME"));
00508 const QString homeDir1 = QDir::homePath();
00509 const QString homeDir2 = QDir(homeDir1).canonicalPath();
00510 if (cleanHomeDirPath(path, homeDir0) ||
00511 cleanHomeDirPath(path, homeDir1) ||
00512 cleanHomeDirPath(path, homeDir2) ) {
00513
00514 }
00515
00516 if (startsWithFile)
00517 path.prepend( "file://" );
00518
00519 return path;
00520 }
00521
00522
00523 KConfigGroup::KConfigGroup() : d(0)
00524 {
00525 }
00526
00527 bool KConfigGroup::isValid() const
00528 {
00529 return 0 != d.constData();
00530 }
00531
00532 KConfigGroupGui _kde_internal_KConfigGroupGui;
00533 static inline bool readEntryGui(const QByteArray& data, const char* key, const QVariant &input,
00534 QVariant &output)
00535 {
00536 if (_kde_internal_KConfigGroupGui.readEntryGui)
00537 return _kde_internal_KConfigGroupGui.readEntryGui(data, key, input, output);
00538 return false;
00539 }
00540
00541 static inline bool writeEntryGui(KConfigGroup *cg, const char* key, const QVariant &input,
00542 KConfigGroup::WriteConfigFlags flags)
00543 {
00544 if (_kde_internal_KConfigGroupGui.writeEntryGui)
00545 return _kde_internal_KConfigGroupGui.writeEntryGui(cg, key, input, flags);
00546 return false;
00547 }
00548
00549 KConfigGroup::KConfigGroup(KConfigBase *master, const QString &_group)
00550 : d(KConfigGroupPrivate::create(master, _group.toUtf8(), master->isGroupImmutable(_group), false))
00551 {
00552 }
00553
00554 KConfigGroup::KConfigGroup(KConfigBase *master, const char *_group)
00555 : d(KConfigGroupPrivate::create(master, _group, master->isGroupImmutable(_group), false))
00556 {
00557 }
00558
00559 KConfigGroup::KConfigGroup(const KConfigBase *master, const QString &_group)
00560 : d(KConfigGroupPrivate::create(const_cast<KConfigBase*>(master), _group.toUtf8(), master->isGroupImmutable(_group), true))
00561 {
00562 }
00563
00564 KConfigGroup::KConfigGroup(const KConfigBase *master, const char * _group)
00565 : d(KConfigGroupPrivate::create(const_cast<KConfigBase*>(master), _group, master->isGroupImmutable(_group), true))
00566 {
00567 }
00568
00569 KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const QString &_group)
00570 : d(new KConfigGroupPrivate(master, _group.toUtf8()))
00571 {
00572 }
00573
00574 KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const char * _group)
00575 : d(new KConfigGroupPrivate(master, _group))
00576 {
00577 }
00578
00579 KConfigGroup &KConfigGroup::operator=(const KConfigGroup &rhs)
00580 {
00581 d = rhs.d;
00582 return *this;
00583 }
00584
00585 KConfigGroup::KConfigGroup(const KConfigGroup &rhs)
00586 : KConfigBase(), d(rhs.d)
00587 {
00588 }
00589
00590 KConfigGroup::~KConfigGroup()
00591 {
00592 d = 0;
00593 }
00594
00595 KConfigGroup KConfigGroup::groupImpl(const QByteArray& aGroup)
00596 {
00597 Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
00598 Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
00599
00600 KConfigGroup newGroup;
00601
00602 newGroup.d = new KConfigGroupPrivate(this, isGroupImmutableImpl(aGroup), d->bConst, aGroup);
00603
00604 return newGroup;
00605 }
00606
00607 const KConfigGroup KConfigGroup::groupImpl(const QByteArray& aGroup) const
00608 {
00609 Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
00610 Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
00611
00612 KConfigGroup newGroup;
00613
00614 newGroup.d = new KConfigGroupPrivate(const_cast<KConfigGroup*>(this), isGroupImmutableImpl(aGroup),
00615 true, aGroup);
00616
00617 return newGroup;
00618 }
00619
00620 KConfigGroup KConfigGroup::parent() const
00621 {
00622 Q_ASSERT_X(isValid(), "KConfigGroup::parent", "accessing an invalid group");
00623
00624 KConfigGroup parentGroup;
00625
00626 if (d->mParent) {
00627 parentGroup.d = d->mParent;
00628 } else {
00629 parentGroup.d = new KConfigGroupPrivate(d->mOwner, d->mOwner->isImmutable(), d->bConst, "");
00630
00631 parentGroup.d->sOwner = d->sOwner;
00632 }
00633
00634 return parentGroup;
00635 }
00636
00637 void KConfigGroup::deleteGroup(WriteConfigFlags flags)
00638 {
00639 Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroup", "accessing an invalid group");
00640 Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteGroup", "deleting a read-only group");
00641
00642 config()->deleteGroup(d->fullName(), flags);
00643 }
00644
00645 void KConfigGroup::changeGroup( const QString &group )
00646 {
00647 changeGroup(group.toUtf8().constData());
00648 }
00649
00650 void KConfigGroup::changeGroup( const char *group )
00651 {
00652 Q_ASSERT_X(isValid(), "KConfigGroup::changeGroup", "accessing an invalid group");
00653
00654 KConfigGroup pnt(parent());
00655
00656
00657 d = new KConfigGroupPrivate(&pnt, pnt.isGroupImmutable(group), d->bConst, group);
00658 }
00659
00660 QString KConfigGroup::name() const
00661 {
00662 Q_ASSERT_X(isValid(), "KConfigGroup::name", "accessing an invalid group");
00663
00664 return QString::fromUtf8(d->name());
00665 }
00666
00667 bool KConfigGroup::exists() const
00668 {
00669 Q_ASSERT_X(isValid(), "KConfigGroup::exists", "accessing an invalid group");
00670
00671 return config()->hasGroup( d->fullName() );
00672 }
00673
00674 void KConfigGroup::sync()
00675 {
00676 Q_ASSERT_X(isValid(), "KConfigGroup::sync", "accessing an invalid group");
00677
00678 if (!d->bConst)
00679 config()->sync();
00680 }
00681
00682 QMap<QString, QString> KConfigGroup::entryMap() const
00683 {
00684 Q_ASSERT_X(isValid(), "KConfigGroup::entryMap", "accessing an invalid group");
00685
00686 return config()->entryMap(d->fullName());
00687 }
00688
00689 KConfig* KConfigGroup::config()
00690 {
00691 Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
00692
00693 return d->mOwner;
00694 }
00695
00696 const KConfig* KConfigGroup::config() const
00697 {
00698 Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
00699
00700 return d->mOwner;
00701 }
00702
00703 bool KConfigGroup::isEntryImmutable(const char* key) const
00704 {
00705 Q_ASSERT_X(isValid(), "KConfigGroup::isEntryImmutable", "accessing an invalid group");
00706
00707 return (isImmutable() ||
00708 !config()->d_func()->canWriteEntry(d->fullName(), key, config()->readDefaults()));
00709 }
00710
00711 bool KConfigGroup::isEntryImmutable(const QString& key) const
00712 {
00713 return isEntryImmutable(key.toUtf8().constData());
00714 }
00715
00716 QString KConfigGroup::readEntryUntranslated(const QString& pKey, const QString& aDefault) const
00717 {
00718 return readEntryUntranslated(pKey.toUtf8().constData(), aDefault);
00719 }
00720
00721 QString KConfigGroup::readEntryUntranslated(const char *key, const QString& aDefault) const
00722 {
00723 Q_ASSERT_X(isValid(), "KConfigGroup::readEntryUntranslated", "accessing an invalid group");
00724
00725 QString result = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchFlags(), 0);
00726 if (result.isNull())
00727 return aDefault;
00728 return result;
00729 }
00730
00731 QString KConfigGroup::readEntry(const char *key, const char* aDefault) const
00732 {
00733 return readEntry(key, QString::fromUtf8(aDefault));
00734 }
00735
00736 QString KConfigGroup::readEntry(const QString &key, const char* aDefault) const
00737 {
00738 return readEntry(key.toUtf8().constData(), aDefault);
00739 }
00740
00741 QString KConfigGroup::readEntry(const char* key, const QString& aDefault) const
00742 {
00743 Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
00744
00745 bool expand = false;
00746
00747
00748 QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized,
00749 &expand);
00750 if (aValue.isNull())
00751 aValue = aDefault;
00752
00753 if (expand)
00754 return KConfigGroupPrivate::expandString(aValue);
00755
00756 return aValue;
00757 }
00758
00759 QString KConfigGroup::readEntry(const QString &key, const QString& aDefault) const
00760 {
00761 return readEntry(key.toUtf8().constData(), aDefault);
00762 }
00763
00764 QStringList KConfigGroup::readEntry(const char* key, const QStringList& aDefault) const
00765 {
00766 Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
00767
00768 const QString data = readEntry(key, QString());
00769 if (data.isNull())
00770 return aDefault;
00771
00772 return KConfigGroupPrivate::deserializeList(data);
00773 }
00774
00775 QStringList KConfigGroup::readEntry( const QString& key, const QStringList& aDefault) const
00776 {
00777 return readEntry( key.toUtf8().constData(), aDefault );
00778 }
00779
00780 QVariant KConfigGroup::readEntry( const char* key, const QVariant &aDefault ) const
00781 {
00782 Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
00783
00784 const QByteArray data = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchFlags());
00785 if (data.isNull())
00786 return aDefault;
00787
00788 QVariant value;
00789 if (!readEntryGui( data, key, aDefault, value ))
00790 return convertToQVariant(key, data, aDefault);
00791
00792 return value;
00793 }
00794
00795 QVariant KConfigGroup::readEntry( const QString& key, const QVariant& aDefault) const
00796 {
00797 return readEntry( key.toUtf8().constData(), aDefault );
00798 }
00799
00800 QVariantList KConfigGroup::readEntry( const char* key, const QVariantList& aDefault) const
00801 {
00802 Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
00803
00804 const QString data = readEntry(key, QString());
00805 if (data.isNull())
00806 return aDefault;
00807
00808 QVariantList value;
00809 foreach(const QString& v, KConfigGroupPrivate::deserializeList(data))
00810 value << v;
00811
00812 return value;
00813 }
00814
00815 QVariantList KConfigGroup::readEntry( const QString& key, const QVariantList& aDefault) const
00816 {
00817 return readEntry( key.toUtf8().constData(), aDefault );
00818 }
00819
00820 QStringList KConfigGroup::readXdgListEntry(const QString& key, const QStringList& aDefault) const
00821 {
00822 return readXdgListEntry(key.toUtf8().constData(), aDefault);
00823 }
00824
00825 QStringList KConfigGroup::readXdgListEntry(const char *key, const QStringList& aDefault) const
00826 {
00827 Q_ASSERT_X(isValid(), "KConfigGroup::readXdgListEntry", "accessing an invalid group");
00828
00829 const QString data = readEntry(key, QString());
00830 if (data.isNull())
00831 return aDefault;
00832
00833 QStringList value;
00834 QString val;
00835 val.reserve(data.size());
00836
00837
00838 bool quoted = false;
00839 for (int p = 0; p < data.length(); p++) {
00840 if (quoted) {
00841 val += data[p];
00842 quoted = false;
00843 } else if (data[p] == '\\') {
00844 quoted = true;
00845 } else if (data[p] == ';') {
00846 value.append(val);
00847 val.clear();
00848 val.reserve(data.size() - p);
00849 } else {
00850 val += data[p];
00851 }
00852 }
00853 if (!val.isEmpty()) {
00854 kWarning() << "List entry" << key << "in" << config()->name() << "is not compliant with XDG standard (missing trailing semicolon).";
00855 value.append(val);
00856 }
00857 return value;
00858 }
00859
00860 QString KConfigGroup::readPathEntry(const QString& pKey, const QString & aDefault) const
00861 {
00862 return readPathEntry(pKey.toUtf8().constData(), aDefault);
00863 }
00864
00865 QString KConfigGroup::readPathEntry(const char *key, const QString & aDefault) const
00866 {
00867 Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
00868
00869 bool expand = false;
00870
00871 QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized,
00872 &expand);
00873 if (aValue.isNull())
00874 aValue = aDefault;
00875
00876 return KConfigGroupPrivate::expandString(aValue);
00877 }
00878
00879 QStringList KConfigGroup::readPathEntry(const QString& pKey, const QStringList& aDefault) const
00880 {
00881 return readPathEntry(pKey.toUtf8().constData(), aDefault);
00882 }
00883
00884 QStringList KConfigGroup::readPathEntry(const char *key, const QStringList& aDefault) const
00885 {
00886 Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
00887
00888 const QString data = readPathEntry(key, QString());
00889 if (data.isNull())
00890 return aDefault;
00891
00892 return KConfigGroupPrivate::deserializeList(data);
00893 }
00894
00895 void KConfigGroup::writeEntry( const char* key, const QString& value, WriteConfigFlags flags )
00896 {
00897 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00898 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00899
00900 writeEntry(key, value.toUtf8(), flags);
00901 }
00902
00903 void KConfigGroup::writeEntry( const QString& key, const QString& value, WriteConfigFlags flags )
00904 {
00905 writeEntry(key.toUtf8().constData(), value, flags);
00906 }
00907
00908 void KConfigGroup::writeEntry(const QString &key, const char *value, WriteConfigFlags pFlags)
00909 {
00910 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00911 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00912
00913 writeEntry(key.toUtf8().constData(), QVariant(value), pFlags);
00914 }
00915
00916 void KConfigGroup::writeEntry(const char *key, const char *value, WriteConfigFlags pFlags)
00917 {
00918 writeEntry(key, QVariant(value), pFlags);
00919 }
00920
00921 void KConfigGroup::writeEntry( const char* key, const QByteArray& value,
00922 WriteConfigFlags flags )
00923 {
00924 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00925 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00926
00927 config()->d_func()->putData(d->fullName(), key, value.isNull()? QByteArray(""): value, flags);
00928 }
00929
00930 void KConfigGroup::writeEntry(const QString& key, const QByteArray& value,
00931 WriteConfigFlags pFlags)
00932 {
00933 writeEntry(key.toUtf8().constData(), value, pFlags);
00934 }
00935
00936 void KConfigGroup::writeEntry(const char* key, const QStringList &list, WriteConfigFlags flags)
00937 {
00938 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00939 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00940
00941 QList<QByteArray> balist;
00942
00943 foreach(const QString &entry, list)
00944 balist.append(entry.toUtf8());
00945
00946 writeEntry(key, KConfigGroupPrivate::serializeList(balist), flags);
00947 }
00948
00949 void KConfigGroup::writeEntry(const QString& key, const QStringList &list, WriteConfigFlags flags)
00950 {
00951 writeEntry(key.toUtf8().constData(), list, flags);
00952 }
00953
00954 void KConfigGroup::writeEntry( const char* key, const QVariantList& list, WriteConfigFlags flags )
00955 {
00956 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00957 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00958
00959 QList<QByteArray> data;
00960
00961 foreach(const QVariant& v, list) {
00962 if (v.type() == QVariant::ByteArray)
00963 data << v.toByteArray();
00964 else
00965 data << v.toString().toUtf8();
00966 }
00967
00968 writeEntry(key, KConfigGroupPrivate::serializeList(data), flags);
00969 }
00970
00971 void KConfigGroup::writeEntry( const char* key, const QVariant &value,
00972 WriteConfigFlags flags )
00973 {
00974 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00975 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00976
00977 if ( writeEntryGui( this, key, value, flags ) )
00978 return;
00979
00980 QByteArray data;
00981
00982
00983
00984 switch( value.type() ) {
00985 case QVariant::Invalid:
00986 data = "";
00987 break;
00988 case QVariant::ByteArray:
00989 data = value.toByteArray();
00990 break;
00991 case QVariant::String:
00992 case QVariant::Int:
00993 case QVariant::UInt:
00994 case QVariant::Double:
00995 case QVariant::Bool:
00996 case QVariant::LongLong:
00997 case QVariant::ULongLong:
00998 data = value.toString().toUtf8();
00999 break;
01000 case QVariant::List:
01001 kError(!value.canConvert(QVariant::StringList))
01002 << "not all types in \"" << key << "\" can convert to QString,"
01003 " information will be lost";
01004 case QVariant::StringList:
01005 writeEntry( key, value.toList(), flags );
01006 return;
01007 case QVariant::Point: {
01008 QVariantList list;
01009 const QPoint rPoint = value.toPoint();
01010 list.insert( 0, rPoint.x() );
01011 list.insert( 1, rPoint.y() );
01012
01013 writeEntry( key, list, flags );
01014 return;
01015 }
01016 case QVariant::PointF: {
01017 QVariantList list;
01018 const QPointF point = value.toPointF();
01019 list.insert( 0, point.x() );
01020 list.insert( 1, point.y() );
01021
01022 writeEntry( key, list, flags );
01023 return;
01024 }
01025 case QVariant::Rect:{
01026 QVariantList list;
01027 const QRect rRect = value.toRect();
01028 list.insert( 0, rRect.left() );
01029 list.insert( 1, rRect.top() );
01030 list.insert( 2, rRect.width() );
01031 list.insert( 3, rRect.height() );
01032
01033 writeEntry( key, list, flags );
01034 return;
01035 }
01036 case QVariant::RectF:{
01037 QVariantList list;
01038 const QRectF rRectF = value.toRectF();
01039 list.insert(0, rRectF.left());
01040 list.insert(1, rRectF.top());
01041 list.insert(2, rRectF.width());
01042 list.insert(3, rRectF.height());
01043
01044 writeEntry(key, list, flags);
01045 return;
01046 }
01047 case QVariant::Size:{
01048 QVariantList list;
01049 const QSize rSize = value.toSize();
01050 list.insert( 0, rSize.width() );
01051 list.insert( 1, rSize.height() );
01052
01053 writeEntry( key, list, flags );
01054 return;
01055 }
01056 case QVariant::SizeF:{
01057 QVariantList list;
01058 const QSizeF rSizeF = value.toSizeF();
01059 list.insert(0, rSizeF.width());
01060 list.insert(1, rSizeF.height());
01061
01062 writeEntry(key, list, flags);
01063 return;
01064 }
01065 case QVariant::Date: {
01066 QVariantList list;
01067 const QDate date = value.toDate();
01068
01069 list.insert( 0, date.year() );
01070 list.insert( 1, date.month() );
01071 list.insert( 2, date.day() );
01072
01073 writeEntry( key, list, flags );
01074 return;
01075 }
01076 case QVariant::DateTime: {
01077 QVariantList list;
01078 const QDateTime rDateTime = value.toDateTime();
01079
01080 const QTime time = rDateTime.time();
01081 const QDate date = rDateTime.date();
01082
01083 list.insert( 0, date.year() );
01084 list.insert( 1, date.month() );
01085 list.insert( 2, date.day() );
01086
01087 list.insert( 3, time.hour() );
01088 list.insert( 4, time.minute() );
01089 list.insert( 5, time.second() );
01090
01091 writeEntry( key, list, flags );
01092 return;
01093 }
01094
01095 case QVariant::Color:
01096 case QVariant::Font:
01097 kWarning() << "KConfigGroup::writeEntry was passed GUI type '"
01098 << value.typeName()
01099 << "' but kdeui isn't linked! If it is linked to your program, this is a platform bug. "
01100 "Please inform the KDE developers";
01101 break;
01102 case QVariant::Url:
01103 data = KUrl(value.toUrl()).url().toUtf8();
01104 break;
01105 default:
01106 if( value.canConvert<KUrl>() ) {
01107 data = qvariant_cast<KUrl>(value).url().toUtf8();
01108 break;
01109 }
01110 kWarning() << "KConfigGroup::writeEntry - unhandled type" << value.typeName() << "in group" << name();
01111 }
01112
01113 writeEntry(key, data, flags);
01114 }
01115
01116 void KConfigGroup::writeEntry( const QString& key, const QVariant& value, WriteConfigFlags flags )
01117 {
01118 writeEntry(key.toUtf8().constData(), value, flags);
01119 }
01120
01121 void KConfigGroup::writeEntry(const QString& key, const QVariantList &list, WriteConfigFlags flags)
01122 {
01123 writeEntry(key.toUtf8().constData(), list, flags);
01124 }
01125
01126 void KConfigGroup::writeXdgListEntry(const QString& key, const QStringList &value, WriteConfigFlags pFlags)
01127 {
01128 writeXdgListEntry(key.toUtf8().constData(), value, pFlags);
01129 }
01130
01131 void KConfigGroup::writeXdgListEntry(const char *key, const QStringList &list, WriteConfigFlags flags)
01132 {
01133 Q_ASSERT_X(isValid(), "KConfigGroup::writeXdgListEntry", "accessing an invalid group");
01134 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeXdgListEntry", "writing to a read-only group");
01135
01136 QString value;
01137 value.reserve(4096);
01138
01139
01140
01141 QStringList::ConstIterator it = list.constBegin();
01142 const QStringList::ConstIterator end = list.constEnd();
01143 for (; it != end; ++it) {
01144 QString val(*it);
01145 val.replace('\\', "\\\\").replace(';', "\\;");
01146 value += val;
01147 value += ';';
01148 }
01149
01150 writeEntry(key, value, flags);
01151 }
01152
01153 void KConfigGroup::writePathEntry(const QString& pKey, const QString & path, WriteConfigFlags pFlags)
01154 {
01155 writePathEntry(pKey.toUtf8().constData(), path, pFlags);
01156 }
01157
01158 void KConfigGroup::writePathEntry(const char *pKey, const QString & path, WriteConfigFlags pFlags)
01159 {
01160 Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
01161 Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
01162
01163 config()->d_func()->putData(d->fullName(), pKey, translatePath(path).toUtf8(), pFlags, true);
01164 }
01165
01166 void KConfigGroup::writePathEntry(const QString& pKey, const QStringList &value, WriteConfigFlags pFlags)
01167 {
01168 writePathEntry(pKey.toUtf8().constData(), value, pFlags);
01169 }
01170
01171 void KConfigGroup::writePathEntry(const char *pKey, const QStringList &value, WriteConfigFlags pFlags)
01172 {
01173 Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
01174 Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
01175
01176 QList<QByteArray> list;
01177 foreach(const QString& path, value)
01178 list << translatePath(path).toUtf8();
01179
01180 config()->d_func()->putData(d->fullName(), pKey, KConfigGroupPrivate::serializeList(list), pFlags, true);
01181 }
01182
01183 void KConfigGroup::deleteEntry( const char *key, WriteConfigFlags flags)
01184 {
01185 Q_ASSERT_X(isValid(), "KConfigGroup::deleteEntry", "accessing an invalid group");
01186 Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteEntry", "deleting from a read-only group");
01187
01188 config()->d_func()->putData(d->fullName(), key, QByteArray(), flags);
01189 }
01190
01191 void KConfigGroup::deleteEntry( const QString& key, WriteConfigFlags flags)
01192 {
01193 deleteEntry(key.toUtf8().constData(), flags);
01194 }
01195
01196 void KConfigGroup::revertToDefault(const char *key)
01197 {
01198 Q_ASSERT_X(isValid(), "KConfigGroup::revertToDefault", "accessing an invalid group");
01199 Q_ASSERT_X(!d->bConst, "KConfigGroup::revertToDefault", "writing to a read-only group");
01200
01201 const QByteArray theDefault = config()->d_func()->lookupData(d->fullName(), key,
01202 KEntryMap::SearchDefaults|KEntryMap::SearchLocalized);
01203
01204 config()->d_func()->putData(d->fullName(), key, theDefault, KConfig::Normal);
01205 }
01206
01207 void KConfigGroup::revertToDefault(const QString &key)
01208 {
01209 revertToDefault(key.toUtf8().constData());
01210 }
01211
01212 bool KConfigGroup::hasDefault(const char *key) const
01213 {
01214 Q_ASSERT_X(isValid(), "KConfigGroup::hasDefault", "accessing an invalid group");
01215
01216 KEntryMap::SearchFlags flags = KEntryMap::SearchDefaults|KEntryMap::SearchLocalized;
01217
01218 return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
01219 }
01220
01221 bool KConfigGroup::hasDefault(const QString &key) const
01222 {
01223 return hasDefault(key.toUtf8().constData());
01224 }
01225
01226 bool KConfigGroup::hasKey(const char *key) const
01227 {
01228 Q_ASSERT_X(isValid(), "KConfigGroup::hasKey", "accessing an invalid group");
01229
01230 KEntryMap::SearchFlags flags = KEntryMap::SearchLocalized;
01231 if ( config()->readDefaults() )
01232 flags |= KEntryMap::SearchDefaults;
01233
01234 return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
01235 }
01236
01237 bool KConfigGroup::hasKey(const QString &key) const
01238 {
01239 return hasKey(key.toUtf8().constData());
01240 }
01241
01242 bool KConfigGroup::isImmutable() const
01243 {
01244 Q_ASSERT_X(isValid(), "KConfigGroup::isImmutable", "accessing an invalid group");
01245
01246 return d->bImmutable;
01247 }
01248
01249 QStringList KConfigGroup::groupList() const
01250 {
01251 Q_ASSERT_X(isValid(), "KConfigGroup::groupList", "accessing an invalid group");
01252
01253 return config()->d_func()->groupList(d->fullName());
01254 }
01255
01256 QStringList KConfigGroup::keyList() const
01257 {
01258 Q_ASSERT_X(isValid(), "KConfigGroup::keyList", "accessing an invalid group");
01259
01260 return entryMap().keys();
01261 }
01262
01263 void KConfigGroup::markAsClean()
01264 {
01265 Q_ASSERT_X(isValid(), "KConfigGroup::markAsClean", "accessing an invalid group");
01266
01267 config()->markAsClean();
01268 }
01269
01270 KConfigGroup::AccessMode KConfigGroup::accessMode() const
01271 {
01272 Q_ASSERT_X(isValid(), "KConfigGroup::accessMode", "accessing an invalid group");
01273
01274 return config()->accessMode();
01275 }
01276
01277 bool KConfigGroup::hasGroupImpl(const QByteArray & b) const
01278 {
01279 Q_ASSERT_X(isValid(), "KConfigGroup::hasGroupImpl", "accessing an invalid group");
01280
01281 return config()->hasGroup(d->fullName(b));
01282 }
01283
01284 void KConfigGroup::deleteGroupImpl(const QByteArray &b, WriteConfigFlags flags)
01285 {
01286 Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroupImpl", "accessing an invalid group");
01287 Q_ASSERT_X(!d->bConst,"KConfigGroup::deleteGroupImpl", "deleting from a read-only group");
01288
01289 config()->deleteGroup(d->fullName(b), flags);
01290 }
01291
01292 bool KConfigGroup::isGroupImmutableImpl(const QByteArray& b) const
01293 {
01294 Q_ASSERT_X(isValid(), "KConfigGroup::isGroupImmutableImpl", "accessing an invalid group");
01295
01296 if (!hasGroupImpl(b))
01297 return d->bImmutable;
01298
01299 return config()->isGroupImmutable(d->fullName(b));
01300 }
01301
01302 void KConfigGroup::copyTo(KConfigBase* other, WriteConfigFlags pFlags) const
01303 {
01304 Q_ASSERT_X(isValid(), "KConfigGroup::copyTo", "accessing an invalid group");
01305 Q_ASSERT(other != 0);
01306
01307 if (KConfigGroup *otherGroup = dynamic_cast<KConfigGroup*>(other)) {
01308 config()->d_func()->copyGroup(d->fullName(), otherGroup->d->fullName(), otherGroup, pFlags);
01309 } else if (KConfig* otherConfig = dynamic_cast<KConfig*>(other)) {
01310 KConfigGroup newGroup = otherConfig->group(d->fullName());
01311 otherConfig->d_func()->copyGroup(d->fullName(), d->fullName(), &newGroup, pFlags);
01312 } else {
01313 Q_ASSERT_X(false, "KConfigGroup::copyTo", "unknown type of KConfigBase");
01314 }
01315 }
01316
01317 void KConfigGroup::reparent(KConfigBase* parent, WriteConfigFlags pFlags)
01318 {
01319 Q_ASSERT_X(isValid(), "KConfigGroup::reparent", "accessing an invalid group");
01320 Q_ASSERT_X(!d->bConst, "KConfigGroup::reparent", "reparenting a read-only group");
01321 Q_ASSERT_X(!d->bImmutable, "KConfigGroup::reparent", "reparenting an immutable group");
01322 Q_ASSERT(parent != 0);
01323
01324 KConfigGroup oldGroup(*this);
01325
01326 d = KConfigGroupPrivate::create(parent, d->mName, false, false);
01327 oldGroup.copyTo(this, pFlags);
01328 oldGroup.deleteGroup();
01329 }