diff --git a/autotests/kconfigskeletontest.h b/autotests/kconfigskeletontest.h --- a/autotests/kconfigskeletontest.h +++ b/autotests/kconfigskeletontest.h @@ -15,14 +15,17 @@ private Q_SLOTS: void initTestCase(); + void cleanupTestCase(); void init(); void cleanup(); void testSimple(); void testDefaults(); void testRemoveItem(); void testClear(); void testKConfigDirty(); void testSaveRead(); + void testDefaultFromFile(); + void testSetValueToOverridenDefaultCppValue(); private: KConfigSkeleton *s; diff --git a/autotests/kconfigskeletontest.cpp b/autotests/kconfigskeletontest.cpp --- a/autotests/kconfigskeletontest.cpp +++ b/autotests/kconfigskeletontest.cpp @@ -22,6 +22,16 @@ #define WRITE_SETTING3 QFont("helvetica",14) #define WRITE_SETTING4 QString("KDE") +static inline QString kdeGlobalsPath() +{ + return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/kdeglobals"; +} + +static inline QString kdeSystemGlobalsPath() +{ + return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/system.kdeglobals"; +} + void KConfigSkeletonTest::initTestCase() { QStandardPaths::setTestModeEnabled(true); @@ -53,6 +63,16 @@ delete s; } +void KConfigSkeletonTest::cleanupTestCase() +{ + if (QFile::exists(kdeGlobalsPath())) { + QVERIFY(QFile::remove(kdeGlobalsPath())); + } + if (QFile::exists(kdeSystemGlobalsPath())) { + QVERIFY(QFile::remove(kdeSystemGlobalsPath())); + } +} + void KConfigSkeletonTest::testSimple() { mMyBool = WRITE_SETTING1; @@ -166,3 +186,68 @@ s->read(); QCOMPARE(mMyBool, false); } + +void KConfigSkeletonTest::testDefaultFromFile() +{ + // This test ensures we don't override default value when this one came from a file + // system.kdeglobals is a global file and can provide default + + // Add global as value for testDefault in system.kdeglobals. + // This value will became the new default + KConfig glob(QStringLiteral("system.kdeglobals")); + KConfigGroup generalGlob(&glob, "General"); + generalGlob.writeEntry("testDefault", "global"); + QVERIFY(glob.sync()); + + QString value; + s->load(); + s->setCurrentGroup(QStringLiteral("General")); + auto item = s->addItemString(QStringLiteral("testDefault"), value, QStringLiteral("defaultcpp")); + s->save(); + s->load(); + // Expected value at this point is default value and default value came from system.kdeglobals -> "global" + QCOMPARE(item->value(), QStringLiteral("global")); + + // Set value to a custom value + item->setValue(QStringLiteral("custom")); + s->save(); + s->load(); + // Expected value is now our custom value + QCOMPARE(item->value(), QStringLiteral("custom")); + + // Reset to defaults + s->setDefaults(); + s->save(); + s->load(); + // Default value is still global + QCOMPARE(item->value(), QStringLiteral("global")); + + // Change default value + generalGlob.writeEntry("testDefault", "globalv2"); + QVERIFY(glob.sync()); + + // expect globalv2 as default value and we don't expect global to be wrote on kconfigskeletontestrc + s->load(); + + // Add item to force readDefault + s->addItemString(QStringLiteral("testDefault"), value, QStringLiteral("defaultcpp")); + QCOMPARE(item->value(), QStringLiteral("globalv2")); +} + +void KConfigSkeletonTest::testSetValueToOverridenDefaultCppValue() +{ + // ensure we don't have any regression if we set value to cpp default value and we have a system default + KConfig glob(QStringLiteral("system.kdeglobals")); + KConfigGroup generalGlob(&glob, "General"); + generalGlob.writeEntry("testRegression", "global"); + QVERIFY(glob.sync()); + + QString value; + s->load(); + s->setCurrentGroup(QStringLiteral("General")); + auto item = s->addItemString(QStringLiteral("testRegression"), value, QStringLiteral("defaultcpp")); + item->setValue("defaultcpp"); + s->save(); + s->load(); + QCOMPARE(item->value(), QStringLiteral("defaultcpp")); +} diff --git a/autotests/kconfigtest.h b/autotests/kconfigtest.h --- a/autotests/kconfigtest.h +++ b/autotests/kconfigtest.h @@ -74,6 +74,7 @@ void testThreads(); void testKdeglobalsVsDefault(); + void testDefaultFromFile(); // should be last void testSyncOnExit(); diff --git a/autotests/kconfigtest.cpp b/autotests/kconfigtest.cpp --- a/autotests/kconfigtest.cpp +++ b/autotests/kconfigtest.cpp @@ -1976,3 +1976,46 @@ local.reparseConfiguration(); QCOMPARE(generalLocal.readEntry("testRestore", "defaultcpp"), "defaultcpp"); } + +void KConfigTest::testDefaultFromFile() +{ + // Add "configdefault" value to testKeyDefault in system.kdekdeglobals (this file provide default value) + KConfig glob(QStringLiteral("system.kdeglobals")); + KConfigGroup generalGlob(&glob, "General"); + generalGlob.writeEntry("testKeyDefault", "configdefault"); + QVERIFY(glob.sync()); + + const char *localFile = TEST_SUBDIR "testdefaultfromfilerc"; + KConfig local(QStringLiteral(TEST_SUBDIR "testdefaultfromfilerc")); + KConfigGroup generalLocal(&local, "General"); + // Check if we get global and not the default value from cpp (defaultcpp) when reading data from restorerc + QCOMPARE(generalLocal.readEntry("testKeyDefault", "defaultcpp"), "configdefault"); + + // Write configdefault to local file + generalLocal.writeEntry("testKeyDefault", "configdefault"); + QVERIFY(local.sync()); + local.reparseConfiguration(); + // We expect to get configdefault value and configdefault not wrote to local file (file will not exist) + QCOMPARE(generalLocal.readEntry("testKeyDefault", "defaultcpp"), "configdefault"); + QVERIFY(!QFile::exists(localFile)); + + // Write a custom value, we expect this value to be wrote to local file + generalLocal.writeEntry("testKeyDefault", "custom"); + QVERIFY(local.sync()); + local.reparseConfiguration(); + QCOMPARE(generalLocal.readEntry("testKeyDefault", "defaultcpp"), "custom"); + const QList lines = readLines(localFile); + Q_ASSERT(lines.contains("testKeyDefault=custom\n")); + + // Revert to default, we expect to get default value from file + generalLocal.revertToDefault("testKeyDefault"); + QVERIFY(local.sync()); + local.reparseConfiguration(); + QCOMPARE(generalLocal.readEntry("testKeyDefault", "defaultcpp"), "configdefault"); + + // Now we change default value from system.globals to ensure new one is used + generalGlob.writeEntry("testKeyDefault", "configdefault-new"); + QVERIFY(generalGlob.sync()); + local.reparseConfiguration(); + QCOMPARE(generalLocal.readEntry("testKeyDefault", "defaultcpp"), "configdefault-new"); +} diff --git a/src/core/kconfigdata.cpp b/src/core/kconfigdata.cpp --- a/src/core/kconfigdata.cpp +++ b/src/core/kconfigdata.cpp @@ -214,9 +214,13 @@ QString KEntryMap::getEntry(const QByteArray &group, const QByteArray &key, const QString &defaultValue, KEntryMap::SearchFlags flags, bool *expand) const { - const ConstIterator it = findEntry(group, key, flags); + ConstIterator it = findEntry(group, key, flags); QString theValue = defaultValue; + // If entry is deleted fallback to default one + if (it != constEnd() && it->bDeleted) { + it = findEntry(group, key, flags | KEntryMap::SearchDefaults); + } if (it != constEnd() && !it->bDeleted) { if (!it->mValue.isNull()) { const QByteArray data = it->mValue; @@ -310,17 +314,7 @@ return false; } - KEntryKey defaultKey(entry.key()); - defaultKey.bDefault = true; - //qDebug() << "looking up default entry with key=" << defaultKey; - const ConstIterator defaultEntry = constFind(defaultKey); - if (defaultEntry != constEnd()) { - Q_ASSERT(defaultEntry.key().bDefault); - //qDebug() << "found, update entry"; - *entry = *defaultEntry; // copy default value, for subsequent lookups - } else { - entry->mValue = QByteArray(); - } + entry->mValue = QByteArray(); entry->bNotify = entry->bNotify || (options & EntryNotify); entry->bDirty = true; entry->bReverted = true; // skip it when writing out to disk diff --git a/src/core/kcoreconfigskeleton.h b/src/core/kcoreconfigskeleton.h --- a/src/core/kcoreconfigskeleton.h +++ b/src/core/kcoreconfigskeleton.h @@ -371,7 +371,7 @@ { if (mReference != mLoadedValue) { // Is this needed? KConfigGroup cg = configGroup(config); - if ((mDefault == mReference) && !cg.hasDefault(mKey)) { + if (mDefault == mReference) { cg.revertToDefault(mKey, writeFlags()); } else { cg.writeEntry(mKey, mReference, writeFlags()); diff --git a/src/core/kcoreconfigskeleton.cpp b/src/core/kcoreconfigskeleton.cpp --- a/src/core/kcoreconfigskeleton.cpp +++ b/src/core/kcoreconfigskeleton.cpp @@ -279,7 +279,7 @@ { if (mReference != mLoadedValue) { // WABA: Is this test needed? KConfigGroup cg = configGroup(config); - if ((mDefault == mReference) && !cg.hasDefault(mKey)) { + if (mDefault == mReference) { cg.revertToDefault(mKey, writeFlags()); } else if (mType == Path) { cg.writePathEntry(mKey, mReference, writeFlags()); @@ -350,7 +350,7 @@ { if (mReference != mLoadedValue) { // WABA: Is this test needed? KConfigGroup cg = configGroup(config); - if ((mDefault == mReference) && !cg.hasDefault(mKey)) { + if (mDefault == mReference) { cg.revertToDefault(mKey, writeFlags()); } else { cg.writeEntry(mKey, mReference.toString(), writeFlags()); @@ -628,7 +628,7 @@ { if (mReference != mLoadedValue) { // WABA: Is this test needed? KConfigGroup cg = configGroup(config); - if ((mDefault == mReference) && !cg.hasDefault(mKey)) { + if (mDefault == mReference) { cg.revertToDefault(mKey, writeFlags()); } else if ((mReference >= 0) && (mReference < mChoices.count())) { cg.writeEntry(mKey, valueForChoice(mChoices.at(mReference).name), writeFlags()); @@ -1028,7 +1028,7 @@ { if (mReference != mLoadedValue) { // WABA: Is this test needed? KConfigGroup cg = configGroup(config); - if ((mDefault == mReference) && !cg.hasDefault(mKey)) { + if (mDefault == mReference) { cg.revertToDefault(mKey, writeFlags()); } else { QStringList sl = mReference; @@ -1070,7 +1070,7 @@ { if (mReference != mLoadedValue) { // WABA: Is this test needed? KConfigGroup cg = configGroup(config); - if ((mDefault == mReference) && !cg.hasDefault(mKey)) { + if (mDefault == mReference) { cg.revertToDefault(mKey, writeFlags()); } else { QStringList strList; diff --git a/src/gui/kwindowconfig.cpp b/src/gui/kwindowconfig.cpp --- a/src/gui/kwindowconfig.cpp +++ b/src/gui/kwindowconfig.cpp @@ -37,7 +37,7 @@ config.writeEntry(hString, sizeToSave.height(), options); } } - if ((isMaximized == false) && !config.hasDefault(screenMaximizedString)) { + if (isMaximized == false) { config.revertToDefault(screenMaximizedString); } else { config.writeEntry(screenMaximizedString, isMaximized, options);