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