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;
00397 if (KGlobal::hasMainComponent()) {
00398 newpath = QFile::encodeName( KGlobal::dirs()->resourceDirs( "exe" ).join( QChar( KPATH_SEPARATOR ) ) );
00399 if (!newpath.isEmpty() && !oldpath.isEmpty())
00400 newpath += KPATH_SEPARATOR;
00401 }
00402 newpath += oldpath;
00403 setenv( "PATH", newpath, 1 );
00404 FILE *fs = popen(QFile::encodeName(cmd).data(), "r");
00405 if (fs) {
00406 QTextStream ts(fs, QIODevice::ReadOnly);
00407 result = ts.readAll().trimmed();
00408 pclose(fs);
00409 }
00410 setenv( "PATH", oldpath, 1 );
00411 aValue.replace( nDollarPos, nEndPos-nDollarPos, result );
00412 nDollarPos += result.length();
00413 } else if( aValue[nDollarPos+1] != '$' ) {
00414 int nEndPos = nDollarPos+1;
00415
00416 QString aVarName;
00417 if ( aValue[nEndPos]=='{' ) {
00418 while ( (nEndPos <= aValue.length()) && (aValue[nEndPos]!='}') )
00419 nEndPos++;
00420 nEndPos++;
00421 aVarName = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
00422 } else {
00423 while ( nEndPos <= aValue.length() &&
00424 (aValue[nEndPos].isNumber() ||
00425 aValue[nEndPos].isLetter() ||
00426 aValue[nEndPos]=='_' ) )
00427 nEndPos++;
00428 aVarName = aValue.mid( nDollarPos+1, nEndPos-nDollarPos-1 );
00429 }
00430 QString env;
00431 if (!aVarName.isEmpty()) {
00432 #ifdef Q_OS_WIN
00433 if (aVarName == "HOME")
00434 env = QDir::homePath();
00435 else
00436 #endif
00437 {
00438 QByteArray pEnv = qgetenv( aVarName.toAscii() );
00439 if( !pEnv.isEmpty() )
00440
00441
00442
00443 env = KStringHandler::from8Bit( pEnv );
00444 }
00445 aValue.replace(nDollarPos, nEndPos-nDollarPos, env);
00446 nDollarPos += env.length();
00447 } else
00448 aValue.remove( nDollarPos, nEndPos-nDollarPos );
00449 } else {
00450
00451 aValue.remove( nDollarPos, 1 );
00452 nDollarPos++;
00453 }
00454 nDollarPos = aValue.indexOf( '$', nDollarPos );
00455 }
00456
00457 return aValue;
00458 }
00459
00460 #ifdef Q_WS_WIN
00461 # include <QtCore/QDir>
00462 #endif
00463
00464 static bool cleanHomeDirPath( QString &path, const QString &homeDir )
00465 {
00466 #ifdef Q_WS_WIN //safer
00467 if (!QDir::convertSeparators(path).startsWith(QDir::convertSeparators(homeDir)))
00468 return false;
00469 #else
00470 if (!path.startsWith(homeDir))
00471 return false;
00472 #endif
00473
00474 int len = homeDir.length();
00475
00476 if (len && (path.length() == len || path[len] == '/')) {
00477 path.replace(0, len, QString::fromLatin1("$HOME"));
00478 return true;
00479 } else
00480 return false;
00481 }
00482
00483 static QString translatePath( QString path )
00484 {
00485 if (path.isEmpty())
00486 return path;
00487
00488
00489 path.replace('$', "$$");
00490
00491 bool startsWithFile = path.startsWith(QLatin1String("file:"), Qt::CaseInsensitive);
00492
00493
00494
00495 if ((!startsWithFile && QFileInfo(path).isRelative()) ||
00496 (startsWithFile && QFileInfo(path.mid(5)).isRelative()))
00497 return path;
00498
00499 if (startsWithFile)
00500 path.remove(0,5);
00501
00502
00503 while (path[0] == '/' && path[1] == '/')
00504 path.remove(0,1);
00505
00506
00507
00508
00509
00510 const QString homeDir0 = QFile::decodeName(qgetenv("HOME"));
00511 const QString homeDir1 = QDir::homePath();
00512 const QString homeDir2 = QDir(homeDir1).canonicalPath();
00513 if (cleanHomeDirPath(path, homeDir0) ||
00514 cleanHomeDirPath(path, homeDir1) ||
00515 cleanHomeDirPath(path, homeDir2) ) {
00516
00517 }
00518
00519 if (startsWithFile)
00520 path.prepend( "file://" );
00521
00522 return path;
00523 }
00524
00525
00526 KConfigGroup::KConfigGroup() : d(0)
00527 {
00528 }
00529
00530 bool KConfigGroup::isValid() const
00531 {
00532 return 0 != d.constData();
00533 }
00534
00535 KConfigGroupGui _kde_internal_KConfigGroupGui;
00536 static inline bool readEntryGui(const QByteArray& data, const char* key, const QVariant &input,
00537 QVariant &output)
00538 {
00539 if (_kde_internal_KConfigGroupGui.readEntryGui)
00540 return _kde_internal_KConfigGroupGui.readEntryGui(data, key, input, output);
00541 return false;
00542 }
00543
00544 static inline bool writeEntryGui(KConfigGroup *cg, const char* key, const QVariant &input,
00545 KConfigGroup::WriteConfigFlags flags)
00546 {
00547 if (_kde_internal_KConfigGroupGui.writeEntryGui)
00548 return _kde_internal_KConfigGroupGui.writeEntryGui(cg, key, input, flags);
00549 return false;
00550 }
00551
00552 KConfigGroup::KConfigGroup(KConfigBase *master, const QString &_group)
00553 : d(KConfigGroupPrivate::create(master, _group.toUtf8(), master->isGroupImmutable(_group), false))
00554 {
00555 }
00556
00557 KConfigGroup::KConfigGroup(KConfigBase *master, const char *_group)
00558 : d(KConfigGroupPrivate::create(master, _group, master->isGroupImmutable(_group), false))
00559 {
00560 }
00561
00562 KConfigGroup::KConfigGroup(const KConfigBase *master, const QString &_group)
00563 : d(KConfigGroupPrivate::create(const_cast<KConfigBase*>(master), _group.toUtf8(), master->isGroupImmutable(_group), true))
00564 {
00565 }
00566
00567 KConfigGroup::KConfigGroup(const KConfigBase *master, const char * _group)
00568 : d(KConfigGroupPrivate::create(const_cast<KConfigBase*>(master), _group, master->isGroupImmutable(_group), true))
00569 {
00570 }
00571
00572 KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const QString &_group)
00573 : d(new KConfigGroupPrivate(master, _group.toUtf8()))
00574 {
00575 }
00576
00577 KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const char * _group)
00578 : d(new KConfigGroupPrivate(master, _group))
00579 {
00580 }
00581
00582 KConfigGroup &KConfigGroup::operator=(const KConfigGroup &rhs)
00583 {
00584 d = rhs.d;
00585 return *this;
00586 }
00587
00588 KConfigGroup::KConfigGroup(const KConfigGroup &rhs)
00589 : KConfigBase(), d(rhs.d)
00590 {
00591 }
00592
00593 KConfigGroup::~KConfigGroup()
00594 {
00595 d = 0;
00596 }
00597
00598 KConfigGroup KConfigGroup::groupImpl(const QByteArray& aGroup)
00599 {
00600 Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
00601 Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
00602
00603 KConfigGroup newGroup;
00604
00605 newGroup.d = new KConfigGroupPrivate(this, isGroupImmutableImpl(aGroup), d->bConst, aGroup);
00606
00607 return newGroup;
00608 }
00609
00610 const KConfigGroup KConfigGroup::groupImpl(const QByteArray& aGroup) const
00611 {
00612 Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
00613 Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
00614
00615 KConfigGroup newGroup;
00616
00617 newGroup.d = new KConfigGroupPrivate(const_cast<KConfigGroup*>(this), isGroupImmutableImpl(aGroup),
00618 true, aGroup);
00619
00620 return newGroup;
00621 }
00622
00623 KConfigGroup KConfigGroup::parent() const
00624 {
00625 Q_ASSERT_X(isValid(), "KConfigGroup::parent", "accessing an invalid group");
00626
00627 KConfigGroup parentGroup;
00628
00629 if (d->mParent) {
00630 parentGroup.d = d->mParent;
00631 } else {
00632 parentGroup.d = new KConfigGroupPrivate(d->mOwner, d->mOwner->isImmutable(), d->bConst, "");
00633
00634 parentGroup.d->sOwner = d->sOwner;
00635 }
00636
00637 return parentGroup;
00638 }
00639
00640 void KConfigGroup::deleteGroup(WriteConfigFlags flags)
00641 {
00642 Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroup", "accessing an invalid group");
00643 Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteGroup", "deleting a read-only group");
00644
00645 config()->deleteGroup(d->fullName(), flags);
00646 }
00647
00648 void KConfigGroup::changeGroup( const QString &group )
00649 {
00650 changeGroup(group.toUtf8().constData());
00651 }
00652
00653 void KConfigGroup::changeGroup( const char *group )
00654 {
00655 Q_ASSERT_X(isValid(), "KConfigGroup::changeGroup", "accessing an invalid group");
00656
00657 KConfigGroup pnt(parent());
00658
00659
00660 d = new KConfigGroupPrivate(&pnt, pnt.isGroupImmutable(group), d->bConst, group);
00661 }
00662
00663 QString KConfigGroup::name() const
00664 {
00665 Q_ASSERT_X(isValid(), "KConfigGroup::name", "accessing an invalid group");
00666
00667 return QString::fromUtf8(d->name());
00668 }
00669
00670 bool KConfigGroup::exists() const
00671 {
00672 Q_ASSERT_X(isValid(), "KConfigGroup::exists", "accessing an invalid group");
00673
00674 return config()->hasGroup( d->fullName() );
00675 }
00676
00677 void KConfigGroup::sync()
00678 {
00679 Q_ASSERT_X(isValid(), "KConfigGroup::sync", "accessing an invalid group");
00680
00681 if (!d->bConst)
00682 config()->sync();
00683 }
00684
00685 QMap<QString, QString> KConfigGroup::entryMap() const
00686 {
00687 Q_ASSERT_X(isValid(), "KConfigGroup::entryMap", "accessing an invalid group");
00688
00689 return config()->entryMap(d->fullName());
00690 }
00691
00692 KConfig* KConfigGroup::config()
00693 {
00694 Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
00695
00696 return d->mOwner;
00697 }
00698
00699 const KConfig* KConfigGroup::config() const
00700 {
00701 Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
00702
00703 return d->mOwner;
00704 }
00705
00706 bool KConfigGroup::isEntryImmutable(const char* key) const
00707 {
00708 Q_ASSERT_X(isValid(), "KConfigGroup::isEntryImmutable", "accessing an invalid group");
00709
00710 return (isImmutable() ||
00711 !config()->d_func()->canWriteEntry(d->fullName(), key, config()->readDefaults()));
00712 }
00713
00714 bool KConfigGroup::isEntryImmutable(const QString& key) const
00715 {
00716 return isEntryImmutable(key.toUtf8().constData());
00717 }
00718
00719 QString KConfigGroup::readEntryUntranslated(const QString& pKey, const QString& aDefault) const
00720 {
00721 return readEntryUntranslated(pKey.toUtf8().constData(), aDefault);
00722 }
00723
00724 QString KConfigGroup::readEntryUntranslated(const char *key, const QString& aDefault) const
00725 {
00726 Q_ASSERT_X(isValid(), "KConfigGroup::readEntryUntranslated", "accessing an invalid group");
00727
00728 QString result = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchFlags(), 0);
00729 if (result.isNull())
00730 return aDefault;
00731 return result;
00732 }
00733
00734 QString KConfigGroup::readEntry(const char *key, const char* aDefault) const
00735 {
00736 return readEntry(key, QString::fromUtf8(aDefault));
00737 }
00738
00739 QString KConfigGroup::readEntry(const QString &key, const char* aDefault) const
00740 {
00741 return readEntry(key.toUtf8().constData(), aDefault);
00742 }
00743
00744 QString KConfigGroup::readEntry(const char* key, const QString& aDefault) const
00745 {
00746 Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
00747
00748 bool expand = false;
00749
00750
00751 QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized,
00752 &expand);
00753 if (aValue.isNull())
00754 aValue = aDefault;
00755
00756 if (expand)
00757 return KConfigGroupPrivate::expandString(aValue);
00758
00759 return aValue;
00760 }
00761
00762 QString KConfigGroup::readEntry(const QString &key, const QString& aDefault) const
00763 {
00764 return readEntry(key.toUtf8().constData(), aDefault);
00765 }
00766
00767 QStringList KConfigGroup::readEntry(const char* key, const QStringList& aDefault) const
00768 {
00769 Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
00770
00771 const QString data = readEntry(key, QString());
00772 if (data.isNull())
00773 return aDefault;
00774
00775 return KConfigGroupPrivate::deserializeList(data);
00776 }
00777
00778 QStringList KConfigGroup::readEntry( const QString& key, const QStringList& aDefault) const
00779 {
00780 return readEntry( key.toUtf8().constData(), aDefault );
00781 }
00782
00783 QVariant KConfigGroup::readEntry( const char* key, const QVariant &aDefault ) const
00784 {
00785 Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
00786
00787 const QByteArray data = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchFlags());
00788 if (data.isNull())
00789 return aDefault;
00790
00791 QVariant value;
00792 if (!readEntryGui( data, key, aDefault, value ))
00793 return convertToQVariant(key, data, aDefault);
00794
00795 return value;
00796 }
00797
00798 QVariant KConfigGroup::readEntry( const QString& key, const QVariant& aDefault) const
00799 {
00800 return readEntry( key.toUtf8().constData(), aDefault );
00801 }
00802
00803 QVariantList KConfigGroup::readEntry( const char* key, const QVariantList& aDefault) const
00804 {
00805 Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
00806
00807 const QString data = readEntry(key, QString());
00808 if (data.isNull())
00809 return aDefault;
00810
00811 QVariantList value;
00812 foreach(const QString& v, KConfigGroupPrivate::deserializeList(data))
00813 value << v;
00814
00815 return value;
00816 }
00817
00818 QVariantList KConfigGroup::readEntry( const QString& key, const QVariantList& aDefault) const
00819 {
00820 return readEntry( key.toUtf8().constData(), aDefault );
00821 }
00822
00823 QStringList KConfigGroup::readXdgListEntry(const QString& key, const QStringList& aDefault) const
00824 {
00825 return readXdgListEntry(key.toUtf8().constData(), aDefault);
00826 }
00827
00828 QStringList KConfigGroup::readXdgListEntry(const char *key, const QStringList& aDefault) const
00829 {
00830 Q_ASSERT_X(isValid(), "KConfigGroup::readXdgListEntry", "accessing an invalid group");
00831
00832 const QString data = readEntry(key, QString());
00833 if (data.isNull())
00834 return aDefault;
00835
00836 QStringList value;
00837 QString val;
00838 val.reserve(data.size());
00839
00840
00841 bool quoted = false;
00842 for (int p = 0; p < data.length(); p++) {
00843 if (quoted) {
00844 val += data[p];
00845 quoted = false;
00846 } else if (data[p] == '\\') {
00847 quoted = true;
00848 } else if (data[p] == ';') {
00849 value.append(val);
00850 val.clear();
00851 val.reserve(data.size() - p);
00852 } else {
00853 val += data[p];
00854 }
00855 }
00856 if (!val.isEmpty()) {
00857 kWarning() << "List entry" << key << "in" << config()->name() << "is not compliant with XDG standard (missing trailing semicolon).";
00858 value.append(val);
00859 }
00860 return value;
00861 }
00862
00863 QString KConfigGroup::readPathEntry(const QString& pKey, const QString & aDefault) const
00864 {
00865 return readPathEntry(pKey.toUtf8().constData(), aDefault);
00866 }
00867
00868 QString KConfigGroup::readPathEntry(const char *key, const QString & aDefault) const
00869 {
00870 Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
00871
00872 bool expand = false;
00873
00874 QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized,
00875 &expand);
00876 if (aValue.isNull())
00877 aValue = aDefault;
00878
00879 return KConfigGroupPrivate::expandString(aValue);
00880 }
00881
00882 QStringList KConfigGroup::readPathEntry(const QString& pKey, const QStringList& aDefault) const
00883 {
00884 return readPathEntry(pKey.toUtf8().constData(), aDefault);
00885 }
00886
00887 QStringList KConfigGroup::readPathEntry(const char *key, const QStringList& aDefault) const
00888 {
00889 Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
00890
00891 const QString data = readPathEntry(key, QString());
00892 if (data.isNull())
00893 return aDefault;
00894
00895 return KConfigGroupPrivate::deserializeList(data);
00896 }
00897
00898 void KConfigGroup::writeEntry( const char* key, const QString& value, WriteConfigFlags flags )
00899 {
00900 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00901 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00902
00903 writeEntry(key, value.toUtf8(), flags);
00904 }
00905
00906 void KConfigGroup::writeEntry( const QString& key, const QString& value, WriteConfigFlags flags )
00907 {
00908 writeEntry(key.toUtf8().constData(), value, flags);
00909 }
00910
00911 void KConfigGroup::writeEntry(const QString &key, const char *value, WriteConfigFlags pFlags)
00912 {
00913 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00914 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00915
00916 writeEntry(key.toUtf8().constData(), QVariant(value), pFlags);
00917 }
00918
00919 void KConfigGroup::writeEntry(const char *key, const char *value, WriteConfigFlags pFlags)
00920 {
00921 writeEntry(key, QVariant(value), pFlags);
00922 }
00923
00924 void KConfigGroup::writeEntry( const char* key, const QByteArray& value,
00925 WriteConfigFlags flags )
00926 {
00927 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00928 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00929
00930 config()->d_func()->putData(d->fullName(), key, value.isNull()? QByteArray(""): value, flags);
00931 }
00932
00933 void KConfigGroup::writeEntry(const QString& key, const QByteArray& value,
00934 WriteConfigFlags pFlags)
00935 {
00936 writeEntry(key.toUtf8().constData(), value, pFlags);
00937 }
00938
00939 void KConfigGroup::writeEntry(const char* key, const QStringList &list, WriteConfigFlags flags)
00940 {
00941 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00942 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00943
00944 QList<QByteArray> balist;
00945
00946 foreach(const QString &entry, list)
00947 balist.append(entry.toUtf8());
00948
00949 writeEntry(key, KConfigGroupPrivate::serializeList(balist), flags);
00950 }
00951
00952 void KConfigGroup::writeEntry(const QString& key, const QStringList &list, WriteConfigFlags flags)
00953 {
00954 writeEntry(key.toUtf8().constData(), list, flags);
00955 }
00956
00957 void KConfigGroup::writeEntry( const char* key, const QVariantList& list, WriteConfigFlags flags )
00958 {
00959 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00960 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00961
00962 QList<QByteArray> data;
00963
00964 foreach(const QVariant& v, list) {
00965 if (v.type() == QVariant::ByteArray)
00966 data << v.toByteArray();
00967 else
00968 data << v.toString().toUtf8();
00969 }
00970
00971 writeEntry(key, KConfigGroupPrivate::serializeList(data), flags);
00972 }
00973
00974 void KConfigGroup::writeEntry( const char* key, const QVariant &value,
00975 WriteConfigFlags flags )
00976 {
00977 Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
00978 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
00979
00980 if ( writeEntryGui( this, key, value, flags ) )
00981 return;
00982
00983 QByteArray data;
00984
00985
00986
00987 switch( value.type() ) {
00988 case QVariant::Invalid:
00989 data = "";
00990 break;
00991 case QVariant::ByteArray:
00992 data = value.toByteArray();
00993 break;
00994 case QVariant::String:
00995 case QVariant::Int:
00996 case QVariant::UInt:
00997 case QVariant::Double:
00998 case QVariant::Bool:
00999 case QVariant::LongLong:
01000 case QVariant::ULongLong:
01001 data = value.toString().toUtf8();
01002 break;
01003 case QVariant::List:
01004 kError(!value.canConvert(QVariant::StringList))
01005 << "not all types in \"" << key << "\" can convert to QString,"
01006 " information will be lost";
01007 case QVariant::StringList:
01008 writeEntry( key, value.toList(), flags );
01009 return;
01010 case QVariant::Point: {
01011 QVariantList list;
01012 const QPoint rPoint = value.toPoint();
01013 list.insert( 0, rPoint.x() );
01014 list.insert( 1, rPoint.y() );
01015
01016 writeEntry( key, list, flags );
01017 return;
01018 }
01019 case QVariant::PointF: {
01020 QVariantList list;
01021 const QPointF point = value.toPointF();
01022 list.insert( 0, point.x() );
01023 list.insert( 1, point.y() );
01024
01025 writeEntry( key, list, flags );
01026 return;
01027 }
01028 case QVariant::Rect:{
01029 QVariantList list;
01030 const QRect rRect = value.toRect();
01031 list.insert( 0, rRect.left() );
01032 list.insert( 1, rRect.top() );
01033 list.insert( 2, rRect.width() );
01034 list.insert( 3, rRect.height() );
01035
01036 writeEntry( key, list, flags );
01037 return;
01038 }
01039 case QVariant::RectF:{
01040 QVariantList list;
01041 const QRectF rRectF = value.toRectF();
01042 list.insert(0, rRectF.left());
01043 list.insert(1, rRectF.top());
01044 list.insert(2, rRectF.width());
01045 list.insert(3, rRectF.height());
01046
01047 writeEntry(key, list, flags);
01048 return;
01049 }
01050 case QVariant::Size:{
01051 QVariantList list;
01052 const QSize rSize = value.toSize();
01053 list.insert( 0, rSize.width() );
01054 list.insert( 1, rSize.height() );
01055
01056 writeEntry( key, list, flags );
01057 return;
01058 }
01059 case QVariant::SizeF:{
01060 QVariantList list;
01061 const QSizeF rSizeF = value.toSizeF();
01062 list.insert(0, rSizeF.width());
01063 list.insert(1, rSizeF.height());
01064
01065 writeEntry(key, list, flags);
01066 return;
01067 }
01068 case QVariant::Date: {
01069 QVariantList list;
01070 const QDate date = value.toDate();
01071
01072 list.insert( 0, date.year() );
01073 list.insert( 1, date.month() );
01074 list.insert( 2, date.day() );
01075
01076 writeEntry( key, list, flags );
01077 return;
01078 }
01079 case QVariant::DateTime: {
01080 QVariantList list;
01081 const QDateTime rDateTime = value.toDateTime();
01082
01083 const QTime time = rDateTime.time();
01084 const QDate date = rDateTime.date();
01085
01086 list.insert( 0, date.year() );
01087 list.insert( 1, date.month() );
01088 list.insert( 2, date.day() );
01089
01090 list.insert( 3, time.hour() );
01091 list.insert( 4, time.minute() );
01092 list.insert( 5, time.second() );
01093
01094 writeEntry( key, list, flags );
01095 return;
01096 }
01097
01098 case QVariant::Color:
01099 case QVariant::Font:
01100 kWarning() << "KConfigGroup::writeEntry was passed GUI type '"
01101 << value.typeName()
01102 << "' but kdeui isn't linked! If it is linked to your program, this is a platform bug. "
01103 "Please inform the KDE developers";
01104 break;
01105 case QVariant::Url:
01106 data = KUrl(value.toUrl()).url().toUtf8();
01107 break;
01108 default:
01109 if( value.canConvert<KUrl>() ) {
01110 data = qvariant_cast<KUrl>(value).url().toUtf8();
01111 break;
01112 }
01113 kWarning() << "KConfigGroup::writeEntry - unhandled type" << value.typeName() << "in group" << name();
01114 }
01115
01116 writeEntry(key, data, flags);
01117 }
01118
01119 void KConfigGroup::writeEntry( const QString& key, const QVariant& value, WriteConfigFlags flags )
01120 {
01121 writeEntry(key.toUtf8().constData(), value, flags);
01122 }
01123
01124 void KConfigGroup::writeEntry(const QString& key, const QVariantList &list, WriteConfigFlags flags)
01125 {
01126 writeEntry(key.toUtf8().constData(), list, flags);
01127 }
01128
01129 void KConfigGroup::writeXdgListEntry(const QString& key, const QStringList &value, WriteConfigFlags pFlags)
01130 {
01131 writeXdgListEntry(key.toUtf8().constData(), value, pFlags);
01132 }
01133
01134 void KConfigGroup::writeXdgListEntry(const char *key, const QStringList &list, WriteConfigFlags flags)
01135 {
01136 Q_ASSERT_X(isValid(), "KConfigGroup::writeXdgListEntry", "accessing an invalid group");
01137 Q_ASSERT_X(!d->bConst, "KConfigGroup::writeXdgListEntry", "writing to a read-only group");
01138
01139 QString value;
01140 value.reserve(4096);
01141
01142
01143
01144 QStringList::ConstIterator it = list.constBegin();
01145 const QStringList::ConstIterator end = list.constEnd();
01146 for (; it != end; ++it) {
01147 QString val(*it);
01148 val.replace('\\', "\\\\").replace(';', "\\;");
01149 value += val;
01150 value += ';';
01151 }
01152
01153 writeEntry(key, value, flags);
01154 }
01155
01156 void KConfigGroup::writePathEntry(const QString& pKey, const QString & path, WriteConfigFlags pFlags)
01157 {
01158 writePathEntry(pKey.toUtf8().constData(), path, pFlags);
01159 }
01160
01161 void KConfigGroup::writePathEntry(const char *pKey, const QString & path, WriteConfigFlags pFlags)
01162 {
01163 Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
01164 Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
01165
01166 config()->d_func()->putData(d->fullName(), pKey, translatePath(path).toUtf8(), pFlags, true);
01167 }
01168
01169 void KConfigGroup::writePathEntry(const QString& pKey, const QStringList &value, WriteConfigFlags pFlags)
01170 {
01171 writePathEntry(pKey.toUtf8().constData(), value, pFlags);
01172 }
01173
01174 void KConfigGroup::writePathEntry(const char *pKey, const QStringList &value, WriteConfigFlags pFlags)
01175 {
01176 Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
01177 Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
01178
01179 QList<QByteArray> list;
01180 foreach(const QString& path, value)
01181 list << translatePath(path).toUtf8();
01182
01183 config()->d_func()->putData(d->fullName(), pKey, KConfigGroupPrivate::serializeList(list), pFlags, true);
01184 }
01185
01186 void KConfigGroup::deleteEntry( const char *key, WriteConfigFlags flags)
01187 {
01188 Q_ASSERT_X(isValid(), "KConfigGroup::deleteEntry", "accessing an invalid group");
01189 Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteEntry", "deleting from a read-only group");
01190
01191 config()->d_func()->putData(d->fullName(), key, QByteArray(), flags);
01192 }
01193
01194 void KConfigGroup::deleteEntry( const QString& key, WriteConfigFlags flags)
01195 {
01196 deleteEntry(key.toUtf8().constData(), flags);
01197 }
01198
01199 void KConfigGroup::revertToDefault(const char *key)
01200 {
01201 Q_ASSERT_X(isValid(), "KConfigGroup::revertToDefault", "accessing an invalid group");
01202 Q_ASSERT_X(!d->bConst, "KConfigGroup::revertToDefault", "writing to a read-only group");
01203
01204 const QByteArray theDefault = config()->d_func()->lookupData(d->fullName(), key,
01205 KEntryMap::SearchDefaults|KEntryMap::SearchLocalized);
01206
01207 config()->d_func()->putData(d->fullName(), key, theDefault, KConfig::Normal);
01208 }
01209
01210 void KConfigGroup::revertToDefault(const QString &key)
01211 {
01212 revertToDefault(key.toUtf8().constData());
01213 }
01214
01215 bool KConfigGroup::hasDefault(const char *key) const
01216 {
01217 Q_ASSERT_X(isValid(), "KConfigGroup::hasDefault", "accessing an invalid group");
01218
01219 KEntryMap::SearchFlags flags = KEntryMap::SearchDefaults|KEntryMap::SearchLocalized;
01220
01221 return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
01222 }
01223
01224 bool KConfigGroup::hasDefault(const QString &key) const
01225 {
01226 return hasDefault(key.toUtf8().constData());
01227 }
01228
01229 bool KConfigGroup::hasKey(const char *key) const
01230 {
01231 Q_ASSERT_X(isValid(), "KConfigGroup::hasKey", "accessing an invalid group");
01232
01233 KEntryMap::SearchFlags flags = KEntryMap::SearchLocalized;
01234 if ( config()->readDefaults() )
01235 flags |= KEntryMap::SearchDefaults;
01236
01237 return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
01238 }
01239
01240 bool KConfigGroup::hasKey(const QString &key) const
01241 {
01242 return hasKey(key.toUtf8().constData());
01243 }
01244
01245 bool KConfigGroup::isImmutable() const
01246 {
01247 Q_ASSERT_X(isValid(), "KConfigGroup::isImmutable", "accessing an invalid group");
01248
01249 return d->bImmutable;
01250 }
01251
01252 QStringList KConfigGroup::groupList() const
01253 {
01254 Q_ASSERT_X(isValid(), "KConfigGroup::groupList", "accessing an invalid group");
01255
01256 return config()->d_func()->groupList(d->fullName());
01257 }
01258
01259 QStringList KConfigGroup::keyList() const
01260 {
01261 Q_ASSERT_X(isValid(), "KConfigGroup::keyList", "accessing an invalid group");
01262
01263 return entryMap().keys();
01264 }
01265
01266 void KConfigGroup::markAsClean()
01267 {
01268 Q_ASSERT_X(isValid(), "KConfigGroup::markAsClean", "accessing an invalid group");
01269
01270 config()->markAsClean();
01271 }
01272
01273 KConfigGroup::AccessMode KConfigGroup::accessMode() const
01274 {
01275 Q_ASSERT_X(isValid(), "KConfigGroup::accessMode", "accessing an invalid group");
01276
01277 return config()->accessMode();
01278 }
01279
01280 bool KConfigGroup::hasGroupImpl(const QByteArray & b) const
01281 {
01282 Q_ASSERT_X(isValid(), "KConfigGroup::hasGroupImpl", "accessing an invalid group");
01283
01284 return config()->hasGroup(d->fullName(b));
01285 }
01286
01287 void KConfigGroup::deleteGroupImpl(const QByteArray &b, WriteConfigFlags flags)
01288 {
01289 Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroupImpl", "accessing an invalid group");
01290 Q_ASSERT_X(!d->bConst,"KConfigGroup::deleteGroupImpl", "deleting from a read-only group");
01291
01292 config()->deleteGroup(d->fullName(b), flags);
01293 }
01294
01295 bool KConfigGroup::isGroupImmutableImpl(const QByteArray& b) const
01296 {
01297 Q_ASSERT_X(isValid(), "KConfigGroup::isGroupImmutableImpl", "accessing an invalid group");
01298
01299 if (!hasGroupImpl(b))
01300 return d->bImmutable;
01301
01302 return config()->isGroupImmutable(d->fullName(b));
01303 }
01304
01305 void KConfigGroup::copyTo(KConfigBase* other, WriteConfigFlags pFlags) const
01306 {
01307 Q_ASSERT_X(isValid(), "KConfigGroup::copyTo", "accessing an invalid group");
01308 Q_ASSERT(other != 0);
01309
01310 if (KConfigGroup *otherGroup = dynamic_cast<KConfigGroup*>(other)) {
01311 config()->d_func()->copyGroup(d->fullName(), otherGroup->d->fullName(), otherGroup, pFlags);
01312 } else if (KConfig* otherConfig = dynamic_cast<KConfig*>(other)) {
01313 KConfigGroup newGroup = otherConfig->group(d->fullName());
01314 otherConfig->d_func()->copyGroup(d->fullName(), d->fullName(), &newGroup, pFlags);
01315 } else {
01316 Q_ASSERT_X(false, "KConfigGroup::copyTo", "unknown type of KConfigBase");
01317 }
01318 }
01319
01320 void KConfigGroup::reparent(KConfigBase* parent, WriteConfigFlags pFlags)
01321 {
01322 Q_ASSERT_X(isValid(), "KConfigGroup::reparent", "accessing an invalid group");
01323 Q_ASSERT_X(!d->bConst, "KConfigGroup::reparent", "reparenting a read-only group");
01324 Q_ASSERT_X(!d->bImmutable, "KConfigGroup::reparent", "reparenting an immutable group");
01325 Q_ASSERT(parent != 0);
01326
01327 KConfigGroup oldGroup(*this);
01328
01329 d = KConfigGroupPrivate::create(parent, d->mName, false, false);
01330 oldGroup.copyTo(this, pFlags);
01331 oldGroup.deleteGroup();
01332 }