diff --git a/autotests/kconfig_compiler/CMakeLists.txt b/autotests/kconfig_compiler/CMakeLists.txt index 70b2dbb..8a6289f 100644 --- a/autotests/kconfig_compiler/CMakeLists.txt +++ b/autotests/kconfig_compiler/CMakeLists.txt @@ -1,251 +1,260 @@ # On Windows we have to generate the .h and .cpp inside ${CMAKE_BINARY_DIR}/bin because # otherwise QFINDTESTDATA will not be able to locate them. if(WIN32) set(KCFG_OUTPUT_DIR "${CMAKE_BINARY_DIR}/bin") else() set(KCFG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") endif() # make sure the generated headers can be found include_directories(${KCFG_OUTPUT_DIR}) include(${CMAKE_SOURCE_DIR}/KF5ConfigMacros.cmake) macro(GEN_KCFG_TEST_SOURCE _testName _srcs) KCONFIG_ADD_KCFG_FILES(${_srcs} ${_testName}.kcfgc ${ARGN}) endmacro() include(ECMMarkAsTest) ########### next target ############### set(test1_SRCS test1main.cpp ) gen_kcfg_test_source(test1 test1_SRCS) ecm_add_test(TEST_NAME test1 ${test1_SRCS}) target_link_libraries(test1 KF5::ConfigGui) ########### next target ############### set(test2_SRCS test2main.cpp ) gen_kcfg_test_source(test2 test2_SRCS) ecm_add_test(TEST_NAME test2 ${test2_SRCS}) target_link_libraries(test2 KF5::ConfigGui) ########### next target ############### set(test3_SRCS test3main.cpp ) gen_kcfg_test_source(test3 test3_SRCS) ecm_add_test(TEST_NAME test3 ${test3_SRCS}) target_link_libraries(test3 KF5::ConfigGui) ########### next target ############### set(test3a_SRCS test3amain.cpp ) gen_kcfg_test_source(test3a test3a_SRCS) ecm_add_test(TEST_NAME test3a ${test3a_SRCS}) target_link_libraries(test3a KF5::ConfigGui) ########### next target ############### set(test4_SRCS test4main.cpp ) gen_kcfg_test_source(test4 test4_SRCS) ecm_add_test(TEST_NAME test4 ${test4_SRCS}) target_link_libraries(test4 KF5::ConfigGui) ########### next target ############### set(test5_SRCS test5main.cpp ) gen_kcfg_test_source(test5 test5_SRCS) ecm_add_test(TEST_NAME test5 ${test5_SRCS}) target_link_libraries(test5 KF5::ConfigGui) ########### next target ############### set(test6_SRCS test6main.cpp ) gen_kcfg_test_source(test6 test6_SRCS) ecm_add_test(TEST_NAME test6 ${test6_SRCS}) target_link_libraries(test6 KF5::ConfigGui) ########### next target ############### set(test7_SRCS test7main.cpp ) gen_kcfg_test_source(test7 test7_SRCS) ecm_add_test(TEST_NAME test7 ${test7_SRCS}) target_link_libraries(test7 KF5::ConfigGui) ########### next target ############### set(test8_SRCS test8main.cpp ) gen_kcfg_test_source(test8a test8_SRCS) gen_kcfg_test_source(test8b test8_SRCS) gen_kcfg_test_source(test8c test8_SRCS) ecm_add_test(TEST_NAME test8 ${test8_SRCS}) target_link_libraries(test8 KF5::ConfigGui) ########### next target ############### set(test9_SRCS test9main.cpp ) gen_kcfg_test_source(test9 test9_SRCS) ecm_add_test(TEST_NAME test9 ${test9_SRCS}) target_link_libraries(test9 KF5::ConfigGui) ########### next target ############### set(test10_SRCS test10main.cpp ) gen_kcfg_test_source(test10 test10_SRCS) ecm_add_test(TEST_NAME test10 ${test10_SRCS}) target_link_libraries(test10 KF5::ConfigGui) ########### next target ############### set(test11_SRCS test11main.cpp ) gen_kcfg_test_source(test11 test11_SRCS) gen_kcfg_test_source(test11a test11_SRCS) ecm_add_test(TEST_NAME test11 ${test11_SRCS}) target_link_libraries(test11 KF5::ConfigGui) ########### next target ############### set(test12_SRCS test12main.cpp ) gen_kcfg_test_source(test12 test12_SRCS) ecm_add_test(TEST_NAME test12 ${test12_SRCS}) target_link_libraries(test12 KF5::ConfigGui) ########### next target ############### set(test13_SRCS test13main.cpp ) gen_kcfg_test_source(test13 test13_SRCS GENERATE_MOC) ecm_add_test(TEST_NAME test13 ${test13_SRCS}) target_link_libraries(test13 KF5::ConfigGui) ########### next target ############### set(test_dpointer_SRCS test_dpointer_main.cpp ) gen_kcfg_test_source(test_dpointer test_dpointer_SRCS) ecm_add_test(TEST_NAME test_dpointer ${test_dpointer_SRCS}) target_link_libraries(test_dpointer KF5::ConfigGui) ########### next target ############### set(test_signal_SRCS test_signal_main.cpp ) gen_kcfg_test_source(test_signal test_signal_SRCS GENERATE_MOC) ecm_add_test(TEST_NAME test_signal ${test_signal_SRCS}) target_link_libraries(test_signal KF5::ConfigGui) + +########### next target ############### + +set(test_notifiers_SRCS test_notifiers_main.cpp ) +gen_kcfg_test_source(test_notifiers test_notifiers_SRCS) +ecm_add_test(TEST_NAME test_notifiers ${test_notifiers_SRCS}) +target_link_libraries(test_notifiers KF5::ConfigGui) + + ########### next target ############### set(kconfigcompiler_test_signals_SRCS kconfigcompiler_test_signals.cpp) gen_kcfg_test_source(signals_test_singleton kconfigcompiler_test_signals_SRCS GENERATE_MOC) gen_kcfg_test_source(signals_test_no_singleton kconfigcompiler_test_signals_SRCS GENERATE_MOC) gen_kcfg_test_source(signals_test_singleton_dpointer kconfigcompiler_test_signals_SRCS GENERATE_MOC) gen_kcfg_test_source(signals_test_no_singleton_dpointer kconfigcompiler_test_signals_SRCS GENERATE_MOC) ecm_add_test(${kconfigcompiler_test_signals_SRCS} TEST_NAME kconfigcompiler-signals-test LINK_LIBRARIES Qt5::Test KF5::ConfigGui ) ########### next target ############### ecm_add_test(kconfigcompiler_test.cpp TEST_NAME kconfigcompiler-basic-test LINK_LIBRARIES Qt5::Test ) ########### next target ############### set(test_qcategory_SRCS test_qdebugcategorymain.cpp test_qdebugcategory_debug.cpp) gen_kcfg_test_source(test_qdebugcategory test_qcategory_SRCS) ecm_add_test(TEST_NAME test_qdebugcategory ${test_qcategory_SRCS}) target_link_libraries(test_qdebugcategory KF5::ConfigGui) ########### next target ############### set(test_translation_qt_SRCS test_translation_qt_main.cpp) gen_kcfg_test_source(test_translation_qt test_translation_qt_SRCS) ecm_add_test(TEST_NAME test_translation_qt ${test_translation_qt_SRCS}) target_link_libraries(test_translation_qt KF5::ConfigGui) ########### next target ############### set(test_translation_kde_SRCS test_translation_kde_main.cpp) gen_kcfg_test_source(test_translation_kde test_translation_kde_SRCS) ecm_add_test(TEST_NAME test_translation_kde ${test_translation_kde_SRCS}) target_link_libraries(test_translation_kde KF5::ConfigGui) ########### next target ############### set(test_translation_kde_domain_SRCS test_translation_kde_domain_main.cpp) gen_kcfg_test_source(test_translation_kde_domain test_translation_kde_domain_SRCS) ecm_add_test(TEST_NAME test_translation_kde_domain ${test_translation_kde_domain_SRCS}) target_link_libraries(test_translation_kde_domain KF5::ConfigGui) ########### next target ############### set(test_fileextensions_SRCS test_fileextensions_main.cxx) gen_kcfg_test_source(test_fileextensions test_fileextensions_SRCS) ecm_add_test(TEST_NAME test_fileextensions ${test_fileextensions_SRCS}) target_link_libraries(test_fileextensions KF5::ConfigGui) diff --git a/autotests/kconfig_compiler/kconfigcompiler_test.cpp b/autotests/kconfig_compiler/kconfigcompiler_test.cpp index 2485461..383745b 100644 --- a/autotests/kconfig_compiler/kconfigcompiler_test.cpp +++ b/autotests/kconfig_compiler/kconfigcompiler_test.cpp @@ -1,181 +1,182 @@ /* Tests for KConfig Compiler Copyright (c) 2005 by Duncan Mac-Vicar Copyright (c) 2009 by Pino Toscano ************************************************************************* * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * ************************************************************************* */ #include #include #include #include #include #include #include "kconfigcompiler_test.h" // QT5 TODO QTEST_GUILESS_MAIN(KConfigCompiler_Test) QTEST_MAIN(KConfigCompiler_Test) typedef const char *CompilerTestSet[]; static CompilerTestSet testCases = { "test1.cpp", "test1.h", "test2.cpp", "test2.h", "test3.cpp", "test3.h", "test3a.cpp", "test3a.h", "test4.cpp", "test4.h", "test5.cpp", "test5.h", "test6.cpp", "test6.h", "test7.cpp", "test7.h", "test8a.cpp", "test8a.h", "test8b.cpp", "test8b.h", "test8c.cpp", "test8c.h", "test9.h", "test9.cpp", "test10.h", "test10.cpp", "test11.h", "test11.cpp", "test11a.h", "test11a.cpp", "test12.h", "test12.cpp", "test13.h", "test13.cpp", "test_dpointer.cpp", "test_dpointer.h", "test_qdebugcategory.cpp", "test_qdebugcategory.h", "test_signal.cpp", "test_signal.h", + "test_notifiers.cpp", "test_notifiers.h", "test_translation_kde.cpp", "test_translation_kde.h", "test_translation_kde_domain.cpp", "test_translation_kde_domain.h", "test_translation_qt.cpp", "test_translation_qt.h", nullptr }; static CompilerTestSet testCasesToRun = { "test1", "test2", "test3", "test3a", "test4", "test5", "test6", "test7", "test8", "test9", "test10", "test11", "test12", "test13", "test_dpointer", "test_qdebugcategory", "test_signal", "test_translation_kde", "test_translation_kde_domain", "test_translation_qt", nullptr }; #if 0 static CompilerTestSet willFailCases = { // where is that QDir coming from? //"test9.cpp", NULL NULL }; #endif void KConfigCompiler_Test::initTestCase() { m_diffExe = QStandardPaths::findExecutable( QStringLiteral("diff") ); if (m_diffExe.isEmpty()) { qDebug() << "diff command not found, detailed info on comparison failure will not be available."; } } void KConfigCompiler_Test::testBaselineComparison_data() { QTest::addColumn("testName"); for (const char **it = testCases; *it; ++it) { QTest::newRow(*it) << QString::fromLatin1(*it); } } void KConfigCompiler_Test::testBaselineComparison() { QFETCH(QString, testName); QFile file(QFINDTESTDATA(testName)); QFile fileRef(QFINDTESTDATA(testName + QLatin1String(".ref"))); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() << "Failed to open" << file.fileName() << "(" << testName << ")"; QFAIL("Can't open file for comparison"); } if (!fileRef.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() << "Failed to open" << fileRef.fileName() << "(" << testName << ".ref )"; QFAIL("Can't open file for comparison"); } QString content = file.readAll(); QString contentRef = fileRef.readAll(); if (content != contentRef) { appendFileDiff(fileRef.fileName(), file.fileName()); } // use split('\n') to avoid // the whole output shown inline QCOMPARE(content.split('\n'), contentRef.split('\n')); QVERIFY(content == contentRef); } void KConfigCompiler_Test::testRunning_data() { QTest::addColumn("testName"); for (const char **it = testCasesToRun; *it; ++it) { QTest::newRow(*it) << QString::fromLatin1(*it); } } void KConfigCompiler_Test::testRunning() { QFETCH(QString, testName); #ifdef Q_OS_WIN testName += QStringLiteral(".exe"); #endif QString program = QFINDTESTDATA(testName); QVERIFY2(!program.isEmpty(), qPrintable(testName + QLatin1String(" must exist!"))); QVERIFY2(QFile::exists(program), qPrintable(program + QLatin1String(" must exist!"))); QProcess process; process.start(program, QStringList(), QIODevice::ReadOnly); if (process.waitForStarted()) { QVERIFY(process.waitForFinished()); } QCOMPARE((int)process.error(), (int)QProcess::UnknownError); QCOMPARE(process.exitCode(), 0); } void KConfigCompiler_Test::appendFileDiff(const QString &oldFile, const QString &newFile) { if (m_diffExe.isEmpty()) { return; } QStringList args; args << QStringLiteral("-u"); args << QFileInfo(oldFile).absoluteFilePath(); args << QFileInfo(newFile).absoluteFilePath(); QProcess process; process.start(m_diffExe, args, QIODevice::ReadOnly); process.waitForStarted(); process.waitForFinished(); if (process.exitCode() == 1) { QByteArray out = process.readAllStandardOutput(); qDebug() << '\n' << out; } } diff --git a/autotests/kconfig_compiler/test_notifiers.cpp.ref b/autotests/kconfig_compiler/test_notifiers.cpp.ref new file mode 100644 index 0000000..1049137 --- /dev/null +++ b/autotests/kconfig_compiler/test_notifiers.cpp.ref @@ -0,0 +1,34 @@ +// This file is generated by kconfig_compiler_kf5 from test_notifiers.kcfg. +// All changes you do to this file will be lost. + +#include "test_notifiers.h" + +TestNotifiers::TestNotifiers( int Number ) + : KConfigSkeleton( QStringLiteral( "test7rc" ) ) + , mParamNumber(Number) +{ + setCurrentGroup( QStringLiteral( "Foo" ) ); + + KConfigSkeleton::ItemColor *itemColor; + itemColor = new KConfigSkeleton::ItemColor( currentGroup(), QStringLiteral( "color #%1" ).arg( mParamNumber ), mColor, QColor( "red" ) ); + itemColor->setWriteFlags(KConfigBase::Notify); + addItem( itemColor, QStringLiteral( "Color" ) ); + + setCurrentGroup( QStringLiteral( "Bar%1" ).arg( mParamNumber ) ); + + KConfigSkeleton::ItemString *itemFooBar; + itemFooBar = new KConfigSkeleton::ItemString( currentGroup(), QStringLiteral( "foo bar" ), mFooBar ); + itemFooBar->setWriteFlags(KConfigBase::Notify); + addItem( itemFooBar, QStringLiteral( "FooBar" ) ); + KConfigSkeleton::ItemInt *itemAge; + itemAge = new KConfigSkeleton::ItemInt( currentGroup(), QStringLiteral( "Age" ), mAge, 35 ); + itemAge->setMinValue(8); + itemAge->setMaxValue(88); + itemAge->setWriteFlags(KConfigBase::Notify); + addItem( itemAge, QStringLiteral( "Age" ) ); +} + +TestNotifiers::~TestNotifiers() +{ +} + diff --git a/autotests/kconfig_compiler/test_notifiers.h.ref b/autotests/kconfig_compiler/test_notifiers.h.ref new file mode 100644 index 0000000..588427e --- /dev/null +++ b/autotests/kconfig_compiler/test_notifiers.h.ref @@ -0,0 +1,94 @@ +// This file is generated by kconfig_compiler_kf5 from test_notifiers.kcfg. +// All changes you do to this file will be lost. +#ifndef TESTNOTIFIERS_H +#define TESTNOTIFIERS_H + +#include +#include +#include + +class TestNotifiers : public KConfigSkeleton +{ + public: + + TestNotifiers( int Number ); + ~TestNotifiers(); + + /** + Set Block colors. + */ + void setColor( const QColor & v ) + { + if (!isImmutable( QStringLiteral( "Color" ) )) + mColor = v; + } + + /** + Get Block colors. + */ + QColor color() const + { + return mColor; + } + + /** + Set foo bar + */ + void setFooBar( const QString & v ) + { + if (!isImmutable( QStringLiteral( "FooBar" ) )) + mFooBar = v; + } + + /** + Get foo bar + */ + QString fooBar() const + { + return mFooBar; + } + + /** + Set Age + */ + void setAge( int v ) + { + if (v < 8) + { + qDebug() << "setAge: value " << v << " is less than the minimum value of 8"; + v = 8; + } + + if (v > 88) + { + qDebug() << "setAge: value " << v << " is greater than the maximum value of 88"; + v = 88; + } + + if (!isImmutable( QStringLiteral( "Age" ) )) + mAge = v; + } + + /** + Get Age + */ + int age() const + { + return mAge; + } + + protected: + int mParamNumber; + + // Foo + QColor mColor; + + // Bar$(Number) + QString mFooBar; + int mAge; + + private: +}; + +#endif + diff --git a/autotests/kconfig_compiler/test_notifiers.kcfg b/autotests/kconfig_compiler/test_notifiers.kcfg new file mode 100644 index 0000000..2f54f60 --- /dev/null +++ b/autotests/kconfig_compiler/test_notifiers.kcfg @@ -0,0 +1,25 @@ + + + + + + + + + + red + + + + + + 35 + 8 + 88 + + + + diff --git a/autotests/kconfig_compiler/test_notifiers.kcfgc b/autotests/kconfig_compiler/test_notifiers.kcfgc new file mode 100644 index 0000000..bfc85f3 --- /dev/null +++ b/autotests/kconfig_compiler/test_notifiers.kcfgc @@ -0,0 +1,8 @@ +# Code generation options for kconfig_compiler_kf5 +File=test_notifiers.kcfg +ClassName=TestNotifiers +Singleton=false +Mutators=true +GlobalEnums=true +ItemAccessors=false +Notifiers=true diff --git a/autotests/kconfig_compiler/test_notifiers_main.cpp b/autotests/kconfig_compiler/test_notifiers_main.cpp new file mode 100644 index 0000000..a4c6ba2 --- /dev/null +++ b/autotests/kconfig_compiler/test_notifiers_main.cpp @@ -0,0 +1,32 @@ +/* +Copyright (c) 2019 Kai Uwe Broulik + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "test_notifiers.h" +#include + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + Q_UNUSED(app); + TestNotifiers *t = new TestNotifiers(42); + delete t; + return 0; +} diff --git a/src/core/kcoreconfigskeleton.cpp b/src/core/kcoreconfigskeleton.cpp index 50f91e9..384efdb 100644 --- a/src/core/kcoreconfigskeleton.cpp +++ b/src/core/kcoreconfigskeleton.cpp @@ -1,1452 +1,1462 @@ /* This file is part of KOrganizer. Copyright (c) 2000,2001 Cornelius Schumacher Copyright (c) 2003 Waldo Bastian This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kcoreconfigskeleton.h" #include "kcoreconfigskeleton_p.h" #include static QString obscuredString(const QString &str) { QString result; const QChar *unicode = str.unicode(); for (int i = 0; i < str.length(); ++i) // yes, no typo. can't encode ' ' or '!' because // they're the unicode BOM. stupid scrambling. stupid. result += (unicode[ i ].unicode() <= 0x21) ? unicode[ i ] : QChar(0x1001F - unicode[ i ].unicode()); return result; } KConfigSkeletonItem::KConfigSkeletonItem(const QString &_group, const QString &_key) : mGroup(_group) , mKey(_key) , d(new KConfigSkeletonItemPrivate) { } KConfigSkeletonItem::~KConfigSkeletonItem() { delete d; } void KConfigSkeletonItem::setGroup(const QString &_group) { mGroup = _group; } QString KConfigSkeletonItem::group() const { return mGroup; } void KConfigSkeletonItem::setKey(const QString &_key) { mKey = _key; } QString KConfigSkeletonItem::key() const { return mKey; } void KConfigSkeletonItem::setName(const QString &_name) { mName = _name; } QString KConfigSkeletonItem::name() const { return mName; } void KConfigSkeletonItem::setLabel(const QString &l) { d->mLabel = l; } QString KConfigSkeletonItem::label() const { return d->mLabel; } void KConfigSkeletonItem::setToolTip(const QString &t) { d->mToolTip = t; } QString KConfigSkeletonItem::toolTip() const { return d->mToolTip; } void KConfigSkeletonItem::setWhatsThis(const QString &w) { d->mWhatsThis = w; } QString KConfigSkeletonItem::whatsThis() const { return d->mWhatsThis; } +void KConfigSkeletonItem::setWriteFlags(KConfigBase::WriteConfigFlags flags) +{ + d->mWriteFlags = flags; +} + +KConfigBase::WriteConfigFlags KConfigSkeletonItem::writeFlags() const +{ + return d->mWriteFlags; +} + QVariant KConfigSkeletonItem::minValue() const { return QVariant(); } QVariant KConfigSkeletonItem::maxValue() const { return QVariant(); } bool KConfigSkeletonItem::isImmutable() const { return d->mIsImmutable; } void KConfigSkeletonItem::readImmutability(const KConfigGroup &group) { d->mIsImmutable = group.isEntryImmutable(mKey); } KCoreConfigSkeleton::ItemString::ItemString(const QString &_group, const QString &_key, QString &reference, const QString &defaultValue, Type type) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue), mType(type) { } void KCoreConfigSkeleton::ItemString::writeConfig(KConfig *config) { if (mReference != mLoadedValue) { // WABA: Is this test needed? KConfigGroup cg(config, mGroup); if ((mDefault == mReference) && !cg.hasDefault(mKey)) { - cg.revertToDefault(mKey); + cg.revertToDefault(mKey, writeFlags()); } else if (mType == Path) { - cg.writePathEntry(mKey, mReference); + cg.writePathEntry(mKey, mReference, writeFlags()); } else if (mType == Password) { - cg.writeEntry(mKey, obscuredString(mReference)); + cg.writeEntry(mKey, obscuredString(mReference), writeFlags()); } else { - cg.writeEntry(mKey, mReference); + cg.writeEntry(mKey, mReference, writeFlags()); } mLoadedValue = mReference; } } void KCoreConfigSkeleton::ItemString::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); if (mType == Path) { mReference = cg.readPathEntry(mKey, mDefault); } else if (mType == Password) { QString val = cg.readEntry(mKey, obscuredString(mDefault)); mReference = obscuredString(val); } else { mReference = cg.readEntry(mKey, mDefault); } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemString::setProperty(const QVariant &p) { mReference = p.toString(); } bool KCoreConfigSkeleton::ItemString::isEqual(const QVariant &v) const { return mReference == v.toString(); } QVariant KCoreConfigSkeleton::ItemString::property() const { return QVariant(mReference); } KCoreConfigSkeleton::ItemPassword::ItemPassword(const QString &_group, const QString &_key, QString &reference, const QString &defaultValue) : ItemString(_group, _key, reference, defaultValue, Password) { } KCoreConfigSkeleton::ItemPath::ItemPath(const QString &_group, const QString &_key, QString &reference, const QString &defaultValue) : ItemString(_group, _key, reference, defaultValue, Path) { } KCoreConfigSkeleton::ItemUrl::ItemUrl(const QString &_group, const QString &_key, QUrl &reference, const QUrl &defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemUrl::writeConfig(KConfig *config) { if (mReference != mLoadedValue) { // WABA: Is this test needed? KConfigGroup cg(config, mGroup); if ((mDefault == mReference) && !cg.hasDefault(mKey)) { - cg.revertToDefault(mKey); + cg.revertToDefault(mKey, writeFlags()); } else { - cg.writeEntry(mKey, mReference.toString()); + cg.writeEntry(mKey, mReference.toString(), writeFlags()); } mLoadedValue = mReference; } } void KCoreConfigSkeleton::ItemUrl::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = QUrl(cg.readEntry(mKey, mDefault.toString())); mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemUrl::setProperty(const QVariant &p) { mReference = qvariant_cast(p); } bool KCoreConfigSkeleton::ItemUrl::isEqual(const QVariant &v) const { return mReference == qvariant_cast(v); } QVariant KCoreConfigSkeleton::ItemUrl::property() const { return qVariantFromValue(mReference); } KCoreConfigSkeleton::ItemProperty::ItemProperty(const QString &_group, const QString &_key, QVariant &reference, const QVariant &defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemProperty::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemProperty::setProperty(const QVariant &p) { mReference = p; } bool KCoreConfigSkeleton::ItemProperty::isEqual(const QVariant &v) const { //this might cause problems if the QVariants are not of default types return mReference == v; } QVariant KCoreConfigSkeleton::ItemProperty::property() const { return mReference; } KCoreConfigSkeleton::ItemBool::ItemBool(const QString &_group, const QString &_key, bool &reference, bool defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemBool::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemBool::setProperty(const QVariant &p) { mReference = p.toBool(); } bool KCoreConfigSkeleton::ItemBool::isEqual(const QVariant &v) const { return mReference == v.toBool(); } QVariant KCoreConfigSkeleton::ItemBool::property() const { return QVariant(mReference); } KCoreConfigSkeleton::ItemInt::ItemInt(const QString &_group, const QString &_key, qint32 &reference, qint32 defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) , mHasMin(false), mHasMax(false) { } void KCoreConfigSkeleton::ItemInt::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); if (mHasMin) { mReference = qMax(mReference, mMin); } if (mHasMax) { mReference = qMin(mReference, mMax); } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemInt::setProperty(const QVariant &p) { mReference = p.toInt(); } bool KCoreConfigSkeleton::ItemInt::isEqual(const QVariant &v) const { return mReference == v.toInt(); } QVariant KCoreConfigSkeleton::ItemInt::property() const { return QVariant(mReference); } QVariant KCoreConfigSkeleton::ItemInt::minValue() const { if (mHasMin) { return QVariant(mMin); } return QVariant(); } QVariant KCoreConfigSkeleton::ItemInt::maxValue() const { if (mHasMax) { return QVariant(mMax); } return QVariant(); } void KCoreConfigSkeleton::ItemInt::setMinValue(qint32 v) { mHasMin = true; mMin = v; } void KCoreConfigSkeleton::ItemInt::setMaxValue(qint32 v) { mHasMax = true; mMax = v; } KCoreConfigSkeleton::ItemLongLong::ItemLongLong(const QString &_group, const QString &_key, qint64 &reference, qint64 defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) , mHasMin(false), mHasMax(false) { } void KCoreConfigSkeleton::ItemLongLong::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); if (mHasMin) { mReference = qMax(mReference, mMin); } if (mHasMax) { mReference = qMin(mReference, mMax); } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemLongLong::setProperty(const QVariant &p) { mReference = p.toLongLong(); } bool KCoreConfigSkeleton::ItemLongLong::isEqual(const QVariant &v) const { return mReference == v.toLongLong(); } QVariant KCoreConfigSkeleton::ItemLongLong::property() const { return QVariant(mReference); } QVariant KCoreConfigSkeleton::ItemLongLong::minValue() const { if (mHasMin) { return QVariant(mMin); } return QVariant(); } QVariant KCoreConfigSkeleton::ItemLongLong::maxValue() const { if (mHasMax) { return QVariant(mMax); } return QVariant(); } void KCoreConfigSkeleton::ItemLongLong::setMinValue(qint64 v) { mHasMin = true; mMin = v; } void KCoreConfigSkeleton::ItemLongLong::setMaxValue(qint64 v) { mHasMax = true; mMax = v; } KCoreConfigSkeleton::ItemEnum::ItemEnum(const QString &_group, const QString &_key, qint32 &reference, const QList &choices, qint32 defaultValue) : ItemInt(_group, _key, reference, defaultValue), mChoices(choices) { } void KCoreConfigSkeleton::ItemEnum::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); if (!cg.hasKey(mKey)) { mReference = mDefault; } else { int i = 0; mReference = -1; QString tmp = cg.readEntry(mKey, QString()).toLower(); for (QList::ConstIterator it = mChoices.constBegin(); it != mChoices.constEnd(); ++it, ++i) { if ((*it).name.toLower() == tmp) { mReference = i; break; } } if (mReference == -1) { mReference = cg.readEntry(mKey, mDefault); } } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemEnum::writeConfig(KConfig *config) { if (mReference != mLoadedValue) { // WABA: Is this test needed? KConfigGroup cg(config, mGroup); if ((mDefault == mReference) && !cg.hasDefault(mKey)) { - cg.revertToDefault(mKey); + cg.revertToDefault(mKey, writeFlags()); } else if ((mReference >= 0) && (mReference < mChoices.count())) { - cg.writeEntry(mKey, mChoices[mReference].name); + cg.writeEntry(mKey, mChoices[mReference].name, writeFlags()); } else { - cg.writeEntry(mKey, mReference); + cg.writeEntry(mKey, mReference, writeFlags()); } mLoadedValue = mReference; } } QList KCoreConfigSkeleton::ItemEnum::choices() const { return mChoices; } QList KCoreConfigSkeleton::ItemEnum::choices2() const { return mChoices; } KCoreConfigSkeleton::ItemUInt::ItemUInt(const QString &_group, const QString &_key, quint32 &reference, quint32 defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) , mHasMin(false), mHasMax(false) { } void KCoreConfigSkeleton::ItemUInt::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); if (mHasMin) { mReference = qMax(mReference, mMin); } if (mHasMax) { mReference = qMin(mReference, mMax); } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemUInt::setProperty(const QVariant &p) { mReference = p.toUInt(); } bool KCoreConfigSkeleton::ItemUInt::isEqual(const QVariant &v) const { return mReference == v.toUInt(); } QVariant KCoreConfigSkeleton::ItemUInt::property() const { return QVariant(mReference); } QVariant KCoreConfigSkeleton::ItemUInt::minValue() const { if (mHasMin) { return QVariant(mMin); } return QVariant(); } QVariant KCoreConfigSkeleton::ItemUInt::maxValue() const { if (mHasMax) { return QVariant(mMax); } return QVariant(); } void KCoreConfigSkeleton::ItemUInt::setMinValue(quint32 v) { mHasMin = true; mMin = v; } void KCoreConfigSkeleton::ItemUInt::setMaxValue(quint32 v) { mHasMax = true; mMax = v; } KCoreConfigSkeleton::ItemULongLong::ItemULongLong(const QString &_group, const QString &_key, quint64 &reference, quint64 defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) , mHasMin(false), mHasMax(false) { } void KCoreConfigSkeleton::ItemULongLong::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); if (mHasMin) { mReference = qMax(mReference, mMin); } if (mHasMax) { mReference = qMin(mReference, mMax); } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemULongLong::setProperty(const QVariant &p) { mReference = p.toULongLong(); } bool KCoreConfigSkeleton::ItemULongLong::isEqual(const QVariant &v) const { return mReference == v.toULongLong(); } QVariant KCoreConfigSkeleton::ItemULongLong::property() const { return QVariant(mReference); } QVariant KCoreConfigSkeleton::ItemULongLong::minValue() const { if (mHasMin) { return QVariant(mMin); } return QVariant(); } QVariant KCoreConfigSkeleton::ItemULongLong::maxValue() const { if (mHasMax) { return QVariant(mMax); } return QVariant(); } void KCoreConfigSkeleton::ItemULongLong::setMinValue(quint64 v) { mHasMin = true; mMin = v; } void KCoreConfigSkeleton::ItemULongLong::setMaxValue(quint64 v) { mHasMax = true; mMax = v; } KCoreConfigSkeleton::ItemDouble::ItemDouble(const QString &_group, const QString &_key, double &reference, double defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) , mHasMin(false), mHasMax(false) { } void KCoreConfigSkeleton::ItemDouble::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); if (mHasMin) { mReference = qMax(mReference, mMin); } if (mHasMax) { mReference = qMin(mReference, mMax); } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemDouble::setProperty(const QVariant &p) { mReference = p.toDouble(); } bool KCoreConfigSkeleton::ItemDouble::isEqual(const QVariant &v) const { return mReference == v.toDouble(); } QVariant KCoreConfigSkeleton::ItemDouble::property() const { return QVariant(mReference); } QVariant KCoreConfigSkeleton::ItemDouble::minValue() const { if (mHasMin) { return QVariant(mMin); } return QVariant(); } QVariant KCoreConfigSkeleton::ItemDouble::maxValue() const { if (mHasMax) { return QVariant(mMax); } return QVariant(); } void KCoreConfigSkeleton::ItemDouble::setMinValue(double v) { mHasMin = true; mMin = v; } void KCoreConfigSkeleton::ItemDouble::setMaxValue(double v) { mHasMax = true; mMax = v; } KCoreConfigSkeleton::ItemRect::ItemRect(const QString &_group, const QString &_key, QRect &reference, const QRect &defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemRect::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemRect::setProperty(const QVariant &p) { mReference = p.toRect(); } bool KCoreConfigSkeleton::ItemRect::isEqual(const QVariant &v) const { return mReference == v.toRect(); } QVariant KCoreConfigSkeleton::ItemRect::property() const { return QVariant(mReference); } KCoreConfigSkeleton::ItemPoint::ItemPoint(const QString &_group, const QString &_key, QPoint &reference, const QPoint &defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemPoint::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemPoint::setProperty(const QVariant &p) { mReference = p.toPoint(); } bool KCoreConfigSkeleton::ItemPoint::isEqual(const QVariant &v) const { return mReference == v.toPoint(); } QVariant KCoreConfigSkeleton::ItemPoint::property() const { return QVariant(mReference); } KCoreConfigSkeleton::ItemSize::ItemSize(const QString &_group, const QString &_key, QSize &reference, const QSize &defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemSize::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemSize::setProperty(const QVariant &p) { mReference = p.toSize(); } bool KCoreConfigSkeleton::ItemSize::isEqual(const QVariant &v) const { return mReference == v.toSize(); } QVariant KCoreConfigSkeleton::ItemSize::property() const { return QVariant(mReference); } KCoreConfigSkeleton::ItemDateTime::ItemDateTime(const QString &_group, const QString &_key, QDateTime &reference, const QDateTime &defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemDateTime::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); mReference = cg.readEntry(mKey, mDefault); mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemDateTime::setProperty(const QVariant &p) { mReference = p.toDateTime(); } bool KCoreConfigSkeleton::ItemDateTime::isEqual(const QVariant &v) const { return mReference == v.toDateTime(); } QVariant KCoreConfigSkeleton::ItemDateTime::property() const { return QVariant(mReference); } KCoreConfigSkeleton::ItemStringList::ItemStringList(const QString &_group, const QString &_key, QStringList &reference, const QStringList &defaultValue) : KConfigSkeletonGenericItem(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemStringList::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); if (!cg.hasKey(mKey)) { mReference = mDefault; } else { mReference = cg.readEntry(mKey, mDefault); } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemStringList::setProperty(const QVariant &p) { mReference = p.toStringList(); } bool KCoreConfigSkeleton::ItemStringList::isEqual(const QVariant &v) const { return mReference == v.toStringList(); } QVariant KCoreConfigSkeleton::ItemStringList::property() const { return QVariant(mReference); } KCoreConfigSkeleton::ItemPathList::ItemPathList(const QString &_group, const QString &_key, QStringList &reference, const QStringList &defaultValue) : ItemStringList(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemPathList::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); if (!cg.hasKey(mKey)) { mReference = mDefault; } else { mReference = cg.readPathEntry(mKey, QStringList()); } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemPathList::writeConfig(KConfig *config) { if (mReference != mLoadedValue) { // WABA: Is this test needed? KConfigGroup cg(config, mGroup); if ((mDefault == mReference) && !cg.hasDefault(mKey)) { - cg.revertToDefault(mKey); + cg.revertToDefault(mKey, writeFlags()); } else { QStringList sl = mReference; - cg.writePathEntry(mKey, sl); + cg.writePathEntry(mKey, sl, writeFlags()); } mLoadedValue = mReference; } } KCoreConfigSkeleton::ItemUrlList::ItemUrlList(const QString &_group, const QString &_key, QList &reference, const QList &defaultValue) : KConfigSkeletonGenericItem >(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemUrlList::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); if (!cg.hasKey(mKey)) { mReference = mDefault; } else { QStringList strList; for (const QUrl &url : qAsConst(mDefault)) { strList.append(url.toString()); } mReference.clear(); const QStringList readList = cg.readEntry(mKey, strList); for (const QString &str : readList) { mReference.append(QUrl(str)); } } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemUrlList::writeConfig(KConfig *config) { if (mReference != mLoadedValue) { // WABA: Is this test needed? KConfigGroup cg(config, mGroup); if ((mDefault == mReference) && !cg.hasDefault(mKey)) { - cg.revertToDefault(mKey); + cg.revertToDefault(mKey, writeFlags()); } else { QStringList strList; for (const QUrl &url : qAsConst(mReference)) { strList.append(url.toString()); } - cg.writeEntry(mKey, strList); + cg.writeEntry(mKey, strList, writeFlags()); } mLoadedValue = mReference; } } void KCoreConfigSkeleton::ItemUrlList::setProperty(const QVariant &p) { mReference = qvariant_cast >(p); } bool KCoreConfigSkeleton::ItemUrlList::isEqual(const QVariant &v) const { return mReference == qvariant_cast >(v); } QVariant KCoreConfigSkeleton::ItemUrlList::property() const { return qVariantFromValue >(mReference); } KCoreConfigSkeleton::ItemIntList::ItemIntList(const QString &_group, const QString &_key, QList &reference, const QList &defaultValue) : KConfigSkeletonGenericItem >(_group, _key, reference, defaultValue) { } void KCoreConfigSkeleton::ItemIntList::readConfig(KConfig *config) { KConfigGroup cg(config, mGroup); if (!cg.hasKey(mKey)) { mReference = mDefault; } else { mReference = cg.readEntry(mKey, mDefault); } mLoadedValue = mReference; readImmutability(cg); } void KCoreConfigSkeleton::ItemIntList::setProperty(const QVariant &p) { mReference = qvariant_cast< QList >(p); } bool KCoreConfigSkeleton::ItemIntList::isEqual(const QVariant &v) const { return mReference == qvariant_cast< QList >(v); } QVariant KCoreConfigSkeleton::ItemIntList::property() const { return qVariantFromValue< QList >(mReference); } //static int kCoreConfigSkeletionDebugArea() { static int s_area = KDebug::registerArea("kdecore (KConfigSkeleton)"); return s_area; } KCoreConfigSkeleton::KCoreConfigSkeleton(const QString &configname, QObject *parent) : QObject(parent), d(new KCoreConfigSkeletonPrivate) { //qDebug() << "Creating KCoreConfigSkeleton (" << (void *)this << ")"; d->mConfig = KSharedConfig::openConfig(configname, KConfig::FullConfig); } KCoreConfigSkeleton::KCoreConfigSkeleton(KSharedConfig::Ptr pConfig, QObject *parent) : QObject(parent), d(new KCoreConfigSkeletonPrivate) { //qDebug() << "Creating KCoreConfigSkeleton (" << (void *)this << ")"; d->mConfig = pConfig; } KCoreConfigSkeleton::~KCoreConfigSkeleton() { delete d; } void KCoreConfigSkeleton::setCurrentGroup(const QString &group) { d->mCurrentGroup = group; } QString KCoreConfigSkeleton::currentGroup() const { return d->mCurrentGroup; } KConfig *KCoreConfigSkeleton::config() { return d->mConfig.data(); } const KConfig *KCoreConfigSkeleton::config() const { return d->mConfig.data(); } KSharedConfig::Ptr KCoreConfigSkeleton::sharedConfig() const { return d->mConfig; } void KCoreConfigSkeleton::setSharedConfig(KSharedConfig::Ptr pConfig) { d->mConfig = pConfig; } KConfigSkeletonItem::List KCoreConfigSkeleton::items() const { return d->mItems; } bool KCoreConfigSkeleton::useDefaults(bool b) { if (b == d->mUseDefaults) { return d->mUseDefaults; } d->mUseDefaults = b; KConfigSkeletonItem::List::ConstIterator it; for (it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it) { (*it)->swapDefault(); } usrUseDefaults(b); return !d->mUseDefaults; } void KCoreConfigSkeleton::setDefaults() { KConfigSkeletonItem::List::ConstIterator it; for (it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it) { (*it)->setDefault(); } usrSetDefaults(); } void KCoreConfigSkeleton::load() { d->mConfig->reparseConfiguration(); read(); } void KCoreConfigSkeleton::read() { KConfigSkeletonItem::List::ConstIterator it; for (it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it) { (*it)->readConfig(d->mConfig.data()); } usrRead(); } bool KCoreConfigSkeleton::save() { //qDebug(); KConfigSkeletonItem::List::ConstIterator it; for (it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it) { (*it)->writeConfig(d->mConfig.data()); } if (!usrSave()) { return false; } if (d->mConfig->isDirty()) { if (!d->mConfig->sync()) { return false; } emit configChanged(); } return true; } bool KCoreConfigSkeleton::usrUseDefaults(bool) { return false; } void KCoreConfigSkeleton::usrSetDefaults() { } #ifdef Q_CC_GNU #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif void KCoreConfigSkeleton::usrRead() { usrReadConfig(); } #ifdef Q_CC_GNU #pragma GCC diagnostic pop #endif void KCoreConfigSkeleton::usrReadConfig() { } #ifdef Q_CC_GNU #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif bool KCoreConfigSkeleton::usrSave() { return usrWriteConfig(); } #ifdef Q_CC_GNU #pragma GCC diagnostic pop #endif bool KCoreConfigSkeleton::usrWriteConfig() { return true; } void KCoreConfigSkeleton::addItem(KConfigSkeletonItem *item, const QString &name) { if (d->mItems.contains(item)) { if (item->name() == name || (name.isEmpty() && item->name() == item->key())) { // nothing to do -> it is already in our collection // and the name isn't changing return; } d->mItemDict.remove(item->name()); } else { d->mItems.append(item); } item->setName(name.isEmpty() ? item->key() : name); d->mItemDict.insert(item->name(), item); item->readDefault(d->mConfig.data()); item->readConfig(d->mConfig.data()); } void KCoreConfigSkeleton::removeItem(const QString &name) { KConfigSkeletonItem *item = d->mItemDict.value(name); if (item) { d->mItems.removeAll(item); d->mItemDict.remove(item->name()); delete item; } } void KCoreConfigSkeleton::clearItems() { KConfigSkeletonItem::List items = d->mItems; d->mItems.clear(); d->mItemDict.clear(); qDeleteAll(items); } KCoreConfigSkeleton::ItemString *KCoreConfigSkeleton::addItemString(const QString &name, QString &reference, const QString &defaultValue, const QString &key) { KCoreConfigSkeleton::ItemString *item; item = new KCoreConfigSkeleton::ItemString(d->mCurrentGroup, key.isEmpty() ? name : key, reference, defaultValue, KCoreConfigSkeleton::ItemString::Normal); addItem(item, name); return item; } KCoreConfigSkeleton::ItemPassword *KCoreConfigSkeleton::addItemPassword(const QString &name, QString &reference, const QString &defaultValue, const QString &key) { KCoreConfigSkeleton::ItemPassword *item; item = new KCoreConfigSkeleton::ItemPassword(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemPath *KCoreConfigSkeleton::addItemPath(const QString &name, QString &reference, const QString &defaultValue, const QString &key) { KCoreConfigSkeleton::ItemPath *item; item = new KCoreConfigSkeleton::ItemPath(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemProperty *KCoreConfigSkeleton::addItemProperty(const QString &name, QVariant &reference, const QVariant &defaultValue, const QString &key) { KCoreConfigSkeleton::ItemProperty *item; item = new KCoreConfigSkeleton::ItemProperty(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemBool *KCoreConfigSkeleton::addItemBool(const QString &name, bool &reference, bool defaultValue, const QString &key) { KCoreConfigSkeleton::ItemBool *item; item = new KCoreConfigSkeleton::ItemBool(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemInt *KCoreConfigSkeleton::addItemInt(const QString &name, qint32 &reference, qint32 defaultValue, const QString &key) { KCoreConfigSkeleton::ItemInt *item; item = new KCoreConfigSkeleton::ItemInt(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemUInt *KCoreConfigSkeleton::addItemUInt(const QString &name, quint32 &reference, quint32 defaultValue, const QString &key) { KCoreConfigSkeleton::ItemUInt *item; item = new KCoreConfigSkeleton::ItemUInt(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemLongLong *KCoreConfigSkeleton::addItemLongLong(const QString &name, qint64 &reference, qint64 defaultValue, const QString &key) { KCoreConfigSkeleton::ItemLongLong *item; item = new KCoreConfigSkeleton::ItemLongLong(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } #ifndef KDE_NO_DEPRECATED KCoreConfigSkeleton::ItemLongLong *KCoreConfigSkeleton::addItemInt64( const QString &name, qint64 &reference, qint64 defaultValue, const QString &key) { return addItemLongLong(name, reference, defaultValue, key); } #endif KCoreConfigSkeleton::ItemULongLong *KCoreConfigSkeleton::addItemULongLong(const QString &name, quint64 &reference, quint64 defaultValue, const QString &key) { KCoreConfigSkeleton::ItemULongLong *item; item = new KCoreConfigSkeleton::ItemULongLong(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } #ifndef KDE_NO_DEPRECATED KCoreConfigSkeleton::ItemULongLong *KCoreConfigSkeleton::addItemUInt64( const QString &name, quint64 &reference, quint64 defaultValue, const QString &key) { return addItemULongLong(name, reference, defaultValue, key); } #endif KCoreConfigSkeleton::ItemDouble *KCoreConfigSkeleton::addItemDouble(const QString &name, double &reference, double defaultValue, const QString &key) { KCoreConfigSkeleton::ItemDouble *item; item = new KCoreConfigSkeleton::ItemDouble(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemRect *KCoreConfigSkeleton::addItemRect(const QString &name, QRect &reference, const QRect &defaultValue, const QString &key) { KCoreConfigSkeleton::ItemRect *item; item = new KCoreConfigSkeleton::ItemRect(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemPoint *KCoreConfigSkeleton::addItemPoint(const QString &name, QPoint &reference, const QPoint &defaultValue, const QString &key) { KCoreConfigSkeleton::ItemPoint *item; item = new KCoreConfigSkeleton::ItemPoint(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemSize *KCoreConfigSkeleton::addItemSize(const QString &name, QSize &reference, const QSize &defaultValue, const QString &key) { KCoreConfigSkeleton::ItemSize *item; item = new KCoreConfigSkeleton::ItemSize(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemDateTime *KCoreConfigSkeleton::addItemDateTime(const QString &name, QDateTime &reference, const QDateTime &defaultValue, const QString &key) { KCoreConfigSkeleton::ItemDateTime *item; item = new KCoreConfigSkeleton::ItemDateTime(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemStringList *KCoreConfigSkeleton::addItemStringList(const QString &name, QStringList &reference, const QStringList &defaultValue, const QString &key) { KCoreConfigSkeleton::ItemStringList *item; item = new KCoreConfigSkeleton::ItemStringList(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } KCoreConfigSkeleton::ItemIntList *KCoreConfigSkeleton::addItemIntList(const QString &name, QList &reference, const QList &defaultValue, const QString &key) { KCoreConfigSkeleton::ItemIntList *item; item = new KCoreConfigSkeleton::ItemIntList(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue); addItem(item, name); return item; } bool KCoreConfigSkeleton::isImmutable(const QString &name) const { KConfigSkeletonItem *item = findItem(name); return !item || item->isImmutable(); } KConfigSkeletonItem *KCoreConfigSkeleton::findItem(const QString &name) const { return d->mItemDict.value(name); } KConfigCompilerSignallingItem::KConfigCompilerSignallingItem(KConfigSkeletonItem* item, QObject* object, KConfigCompilerSignallingItem::NotifyFunction targetFunction, quint64 userData) : KConfigSkeletonItem(item->group(), item->key()), mItem(item), mTargetFunction(targetFunction), mObject(object), mUserData(userData) { Q_ASSERT(mTargetFunction); Q_ASSERT(mItem); Q_ASSERT(mObject); } KConfigCompilerSignallingItem::~KConfigCompilerSignallingItem() { } bool KConfigCompilerSignallingItem::isEqual(const QVariant& p) const { return mItem->isEqual(p); } QVariant KConfigCompilerSignallingItem::property() const { return mItem->property(); } void KConfigCompilerSignallingItem::readConfig(KConfig* c) { QVariant oldValue = mItem->property(); mItem->readConfig(c); //readConfig() changes mIsImmutable, update it here as well KConfigGroup cg(c, mGroup ); readImmutability(cg); if (!mItem->isEqual(oldValue)) { invokeNotifyFunction(); } } void KConfigCompilerSignallingItem::readDefault(KConfig* c) { mItem->readDefault(c); //readDefault() changes mIsImmutable, update it here as well KConfigGroup cg(c, mGroup ); readImmutability(cg); } void KConfigCompilerSignallingItem::writeConfig(KConfig* c) { mItem->writeConfig(c); } void KConfigCompilerSignallingItem::setDefault() { QVariant oldValue = mItem->property(); mItem->setDefault(); if (!mItem->isEqual(oldValue)) { invokeNotifyFunction(); } } void KConfigCompilerSignallingItem::setProperty(const QVariant& p) { if (!mItem->isEqual(p)) { mItem->setProperty(p); invokeNotifyFunction(); } } void KConfigCompilerSignallingItem::swapDefault() { QVariant oldValue = mItem->property(); mItem->swapDefault(); if (!mItem->isEqual(oldValue)) { invokeNotifyFunction(); } } diff --git a/src/core/kcoreconfigskeleton.h b/src/core/kcoreconfigskeleton.h index b384129..771d8cc 100644 --- a/src/core/kcoreconfigskeleton.h +++ b/src/core/kcoreconfigskeleton.h @@ -1,1493 +1,1507 @@ /* * This file is part of KDE. * * Copyright (c) 2001,2002,2003 Cornelius Schumacher * Copyright (c) 2003 Waldo Bastian * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KCORECONFIGSKELETON_H #define KCORECONFIGSKELETON_H #include #include #include #include #include #include #include #include #include class KCoreConfigSkeletonPrivate; class KConfigSkeletonItemPrivate; /** * \class KConfigSkeletonItem kcoreconfigskeleton.h * * @short Class for storing a preferences setting * @author Cornelius Schumacher * @see KCoreConfigSkeleton * * This class represents one preferences setting as used by @ref KCoreConfigSkeleton. * Subclasses of KConfigSkeletonItem implement storage functions for a certain type of * setting. Normally you don't have to use this class directly. Use the special * addItem() functions of KCoreConfigSkeleton instead. If you subclass this class you will * have to register instances with the function KCoreConfigSkeleton::addItem(). */ class KCONFIGCORE_EXPORT KConfigSkeletonItem { public: typedef QList < KConfigSkeletonItem * >List; typedef QHash < QString, KConfigSkeletonItem * > Dict; typedef QHash < QString, KConfigSkeletonItem * >::Iterator DictIterator; /** * Constructor. * * @param _group Config file group. * @param _key Config file key. */ KConfigSkeletonItem(const QString &_group, const QString &_key); /** * Destructor. */ virtual ~KConfigSkeletonItem(); /** * Set config file group. */ void setGroup(const QString &_group); /** * Return config file group. */ QString group() const; /** * Set config file key. */ void setKey(const QString &_key); /** * Return config file key. */ QString key() const; /** * Set internal name of entry. */ void setName(const QString &_name); /** * Return internal name of entry. */ QString name() const; /** Set label providing a translated one-line description of the item. */ void setLabel(const QString &l); /** Return label of item. See setLabel(). */ QString label() const; /** Set ToolTip description of item. @since 4.2 */ void setToolTip(const QString &t); /** Return ToolTip description of item. See setToolTip(). @since 4.2 */ QString toolTip() const; /** Set WhatsThis description of item. */ void setWhatsThis(const QString &w); /** Return WhatsThis description of item. See setWhatsThis(). */ QString whatsThis() const; + /** + The write flags to be used when writing configuration. + @since 5.58 + */ + void setWriteFlags(KConfigBase::WriteConfigFlags flags); + + /** + Return write flags to be used when writing configuration. + They should be passed to every call of writeEntry() and revertToDefault(). + @since 5.58 + */ + KConfigBase::WriteConfigFlags writeFlags() const; + /** * This function is called by @ref KCoreConfigSkeleton to read the value for this setting * from a config file. */ virtual void readConfig(KConfig *) = 0; /** * This function is called by @ref KCoreConfigSkeleton to write the value of this setting * to a config file. + * Make sure to pass writeFlags() to every call of writeEntry() and revertToDefault(). */ virtual void writeConfig(KConfig *) = 0; /** * Read global default value. */ virtual void readDefault(KConfig *) = 0; /** * Set item to @p p */ virtual void setProperty(const QVariant &p) = 0; /** * Check whether the item is equal to p. * * Use this function to compare items that use custom types, * because QVariant::operator== will not work for those. * * @param p QVariant to compare to * @return true if the item is equal to p, false otherwise */ virtual bool isEqual(const QVariant &p) const = 0; /** * Return item as property */ virtual QVariant property() const = 0; /** * Return minimum value of item or invalid if not specified */ virtual QVariant minValue() const; /** * Return maximum value of item or invalid if not specified */ virtual QVariant maxValue() const; /** * Sets the current value to the default value. */ virtual void setDefault() = 0; /** * Exchanges the current value with the default value * Used by KCoreConfigSkeleton::useDefaults(bool); */ virtual void swapDefault() = 0; /** * Return if the entry can be modified. */ bool isImmutable() const; protected: /** * sets mIsImmutable to true if mKey in config is immutable * @param group KConfigGroup to check if mKey is immutable in */ void readImmutability(const KConfigGroup &group); QString mGroup; ///< The group name for this item QString mKey; ///< The config key for this item QString mName; ///< The name of this item private: KConfigSkeletonItemPrivate *const d; }; /** * \class KConfigSkeletonGenericItem kcoreconfigskeleton.h */ template < typename T > class KConfigSkeletonGenericItem: public KConfigSkeletonItem { public: /** @copydoc KConfigSkeletonItem(const QString&, const QString&) @param reference The initial value to hold in the item @param defaultValue The default value for the item */ KConfigSkeletonGenericItem(const QString &_group, const QString &_key, T &reference, T defaultValue) : KConfigSkeletonItem(_group, _key), mReference(reference), mDefault(defaultValue), mLoadedValue(defaultValue) { } /** * Set value of this KConfigSkeletonItem. */ void setValue(const T &v) { mReference = v; } /** * Return value of this KConfigSkeletonItem. */ T &value() { return mReference; } /** * Return const value of this KConfigSkeletonItem. */ const T &value() const { return mReference; } /** Set default value for this item. */ virtual void setDefaultValue(const T &v) { mDefault = v; } /** Set the value for this item to the default value */ void setDefault() override { mReference = mDefault; } /** @copydoc KConfigSkeletonItem::writeConfig(KConfig *) */ void writeConfig(KConfig *config) override { if (mReference != mLoadedValue) { // Is this needed? KConfigGroup cg(config, mGroup); if ((mDefault == mReference) && !cg.hasDefault(mKey)) { - cg.revertToDefault(mKey); + cg.revertToDefault(mKey, writeFlags()); } else { - cg.writeEntry(mKey, mReference); + cg.writeEntry(mKey, mReference, writeFlags()); } mLoadedValue = mReference; } } /** @copydoc KConfigSkeletonItem::readDefault(KConfig*) */ void readDefault(KConfig *config) override { config->setReadDefaults(true); readConfig(config); config->setReadDefaults(false); mDefault = mReference; } /** @copydoc KConfigSkeletonItem::swapDefault() */ void swapDefault() override { T tmp = mReference; mReference = mDefault; mDefault = tmp; } protected: T &mReference; ///< Stores the value for this item T mDefault; ///< The default value for this item T mLoadedValue; }; /** * \class KConfigSkeletonChangeNotifyingItem kcoreconfigskeleton.h * * @author Alex Richardson * @see KConfigSkeletonItem * * * This class wraps a @ref KConfigSkeletonItem and invokes a function whenever the value changes. * That function must take one quint64 parameter. Whenever the property value of the wrapped KConfigSkeletonItem * changes this function will be invoked with the stored user data passed in the constructor. * It does not call a function with the new value since this class is designed solely for the kconfig_compiler generated * code and is therefore probably not suited for any other usecases. */ class KCONFIGCORE_EXPORT KConfigCompilerSignallingItem : public KConfigSkeletonItem { public: typedef void (QObject::* NotifyFunction)(quint64 arg); /** * Constructor. * * @param item the KConfigSkeletonItem to wrap * @param targetFunction the method to invoke whenever the value of @p item changes * @param object The object on which the method is invoked. * @param userData This data will be passed to @p targetFunction on every property change */ KConfigCompilerSignallingItem(KConfigSkeletonItem *item, QObject* object, NotifyFunction targetFunction, quint64 userData); ~KConfigCompilerSignallingItem() override; void readConfig(KConfig *) override; void writeConfig(KConfig *) override; void readDefault(KConfig *) override; void setProperty(const QVariant &p) override; bool isEqual(const QVariant &p) const override; QVariant property() const override; void setDefault() override; void swapDefault() override; private: inline void invokeNotifyFunction() { // call the pointer to member function using the strange ->* operator (mObject->*mTargetFunction)(mUserData); } private: QScopedPointer mItem; NotifyFunction mTargetFunction; QObject* mObject; quint64 mUserData; }; /** * \class KCoreConfigSkeleton kcoreconfigskeleton.h * * @short Class for handling preferences settings for an application. * @author Cornelius Schumacher * @see KConfigSkeletonItem * * This class provides an interface to preferences settings. Preferences items * can be registered by the addItem() function corresponding to the data type of * the setting. KCoreConfigSkeleton then handles reading and writing of config files and * setting of default values. * * Normally you will subclass KCoreConfigSkeleton, add data members for the preferences * settings and register the members in the constructor of the subclass. * * Example: * \code * class MyPrefs : public KCoreConfigSkeleton * { * public: * MyPrefs() * { * setCurrentGroup("MyGroup"); * addItemBool("MySetting1", mMyBool, false); * addItemPoint("MySetting2", mMyPoint, QPoint(100, 200)); * * setCurrentGroup("MyOtherGroup"); * addItemDouble("MySetting3", mMyDouble, 3.14); * } * * bool mMyBool; * QPoint mMyPoint; * double mMyDouble; * } * \endcode * * It might be convenient in many cases to make this subclass of KCoreConfigSkeleton a * singleton for global access from all over the application without passing * references to the KCoreConfigSkeleton object around. * * You can write the data to the configuration file by calling @ref save() * and read the data from the configuration file by calling @ref readConfig(). * If you want to watch for config changes, use @ref configChanged() signal. * * If you have items, which are not covered by the existing addItem() functions * you can add customized code for reading, writing and default setting by * implementing the functions @ref usrUseDefaults(), @ref usrRead() and * @ref usrSave(). * * Internally preferences settings are stored in instances of subclasses of * @ref KConfigSkeletonItem. You can also add KConfigSkeletonItem subclasses * for your own types and call the generic @ref addItem() to register them. * * In many cases you don't have to write the specific KCoreConfigSkeleton * subclasses yourself, but you can use \ref kconfig_compiler to automatically * generate the C++ code from an XML description of the configuration options. * * Use KConfigSkeleton if you need GUI types as well. */ class KCONFIGCORE_EXPORT KCoreConfigSkeleton : public QObject { Q_OBJECT public: /** * Class for handling a string preferences item. */ class KCONFIGCORE_EXPORT ItemString: public KConfigSkeletonGenericItem < QString > { public: enum Type { Normal, Password, Path }; /** @enum Type The type of string that is held in this item @var ItemString::Type ItemString::Normal A normal string @var ItemString::Type ItemString::Password A password string @var ItemString::Type ItemString::Path A path to a file or directory */ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem @param type The type of string held by the item */ ItemString(const QString &_group, const QString &_key, QString &reference, const QString &defaultValue = QLatin1String(""), // NOT QString() !! Type type = Normal); /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */ void writeConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() const */ QVariant property() const override; private: Type mType; }; /** * Class for handling a password preferences item. */ class KCONFIGCORE_EXPORT ItemPassword: public ItemString { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemPassword(const QString &_group, const QString &_key, QString &reference, const QString &defaultValue = QLatin1String("")); // NOT QString() !! }; /** * Class for handling a path preferences item. */ class KCONFIGCORE_EXPORT ItemPath: public ItemString { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemPath(const QString &_group, const QString &_key, QString &reference, const QString &defaultValue = QString()); }; /** * Class for handling a url preferences item. */ class KCONFIGCORE_EXPORT ItemUrl: public KConfigSkeletonGenericItem < QUrl > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemUrl(const QString &_group, const QString &_key, QUrl &reference, const QUrl &defaultValue = QUrl()); /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */ void writeConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() const */ QVariant property() const override; }; /** * Class for handling a QVariant preferences item. */ class KCONFIGCORE_EXPORT ItemProperty: public KConfigSkeletonGenericItem < QVariant > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemProperty(const QString &_group, const QString &_key, QVariant &reference, const QVariant &defaultValue = QVariant()); void readConfig(KConfig *config) override; void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() const */ QVariant property() const override; }; /** * Class for handling a bool preferences item. */ class KCONFIGCORE_EXPORT ItemBool: public KConfigSkeletonGenericItem < bool > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemBool(const QString &_group, const QString &_key, bool &reference, bool defaultValue = true); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() const */ QVariant property() const override; }; /** * Class for handling a 32-bit integer preferences item. */ class KCONFIGCORE_EXPORT ItemInt: public KConfigSkeletonGenericItem < qint32 > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemInt(const QString &_group, const QString &_key, qint32 &reference, qint32 defaultValue = 0); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; /** Get the minimum value that is allowed to be stored in this item */ QVariant minValue() const override; /** Get the maximum value this is allowed to be stored in this item */ QVariant maxValue() const override; /** Set the minimum value for the item @sa minValue() */ void setMinValue(qint32); /** Set the maximum value for the item @sa maxValue */ void setMaxValue(qint32); private: bool mHasMin : 1; bool mHasMax : 1; qint32 mMin; qint32 mMax; }; /** * Class for handling a 64-bit integer preferences item. */ class KCONFIGCORE_EXPORT ItemLongLong: public KConfigSkeletonGenericItem < qint64 > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemLongLong(const QString &_group, const QString &_key, qint64 &reference, qint64 defaultValue = 0); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; /** @copydoc ItemInt::minValue() */ QVariant minValue() const override; /** @copydoc ItemInt::maxValue() */ QVariant maxValue() const override; /** @copydoc ItemInt::setMinValue(qint32) */ void setMinValue(qint64); /** @copydoc ItemInt::setMaxValue(qint32) */ void setMaxValue(qint64); private: bool mHasMin : 1; bool mHasMax : 1; qint64 mMin; qint64 mMax; }; #ifndef KDE_NO_DEPRECATED typedef KCONFIGCORE_DEPRECATED ItemLongLong ItemInt64; #endif /** * Class for handling enums. */ class KCONFIGCORE_EXPORT ItemEnum: public ItemInt { public: struct Choice { QString name; QString label; QString toolTip; QString whatsThis; }; /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem @param choices The list of enums that can be stored in this item */ ItemEnum(const QString &_group, const QString &_key, qint32 &reference, const QList &choices, qint32 defaultValue = 0); QList choices() const; /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */ void writeConfig(KConfig *config) override; // Source compatibility with 4.x typedef Choice Choice2; QList choices2() const; private: QList mChoices; }; /** * Class for handling an unsigned 32-bit integer preferences item. */ class KCONFIGCORE_EXPORT ItemUInt: public KConfigSkeletonGenericItem < quint32 > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemUInt(const QString &_group, const QString &_key, quint32 &reference, quint32 defaultValue = 0); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; /** @copydoc ItemInt::minValue() */ QVariant minValue() const override; /** @copydoc ItemInt::maxValue() */ QVariant maxValue() const override; /** @copydoc ItemInt::setMinValue(qint32) */ void setMinValue(quint32); /** @copydoc ItemInt::setMaxValue(qint32) */ void setMaxValue(quint32); private: bool mHasMin : 1; bool mHasMax : 1; quint32 mMin; quint32 mMax; }; /** * Class for handling unsigned 64-bit integer preferences item. */ class KCONFIGCORE_EXPORT ItemULongLong: public KConfigSkeletonGenericItem < quint64 > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemULongLong(const QString &_group, const QString &_key, quint64 &reference, quint64 defaultValue = 0); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; /** @copydoc ItemInt::minValue() */ QVariant minValue() const override; /** @copydoc ItemInt::maxValue() */ QVariant maxValue() const override; /** @copydoc ItemInt::setMinValue(qint32) */ void setMinValue(quint64); /** @copydoc ItemInt::setMaxValue(qint32) */ void setMaxValue(quint64); private: bool mHasMin : 1; bool mHasMax : 1; quint64 mMin; quint64 mMax; }; #ifndef KDE_NO_DEPRECATED typedef KCONFIGCORE_DEPRECATED ItemULongLong ItemUInt64; #endif /** * Class for handling a floating point preference item. */ class KCONFIGCORE_EXPORT ItemDouble: public KConfigSkeletonGenericItem < double > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemDouble(const QString &_group, const QString &_key, double &reference, double defaultValue = 0); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; /** @copydoc ItemInt::minValue() */ QVariant minValue() const override; /** @copydoc ItemInt::maxValue() */ QVariant maxValue() const override; /** @copydoc ItemInt::setMinValue() */ void setMinValue(double); /** @copydoc ItemInt::setMaxValue() */ void setMaxValue(double); private: bool mHasMin : 1; bool mHasMax : 1; double mMin; double mMax; }; /** * Class for handling a QRect preferences item. */ class KCONFIGCORE_EXPORT ItemRect: public KConfigSkeletonGenericItem < QRect > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemRect(const QString &_group, const QString &_key, QRect &reference, const QRect &defaultValue = QRect()); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; }; /** * Class for handling a QPoint preferences item. */ class KCONFIGCORE_EXPORT ItemPoint: public KConfigSkeletonGenericItem < QPoint > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemPoint(const QString &_group, const QString &_key, QPoint &reference, const QPoint &defaultValue = QPoint()); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; }; /** * Class for handling a QSize preferences item. */ class KCONFIGCORE_EXPORT ItemSize: public KConfigSkeletonGenericItem < QSize > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemSize(const QString &_group, const QString &_key, QSize &reference, const QSize &defaultValue = QSize()); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; }; /** * Class for handling a QDateTime preferences item. */ class KCONFIGCORE_EXPORT ItemDateTime: public KConfigSkeletonGenericItem < QDateTime > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemDateTime(const QString &_group, const QString &_key, QDateTime &reference, const QDateTime &defaultValue = QDateTime()); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; }; /** * Class for handling a string list preferences item. */ class KCONFIGCORE_EXPORT ItemStringList: public KConfigSkeletonGenericItem < QStringList > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemStringList(const QString &_group, const QString &_key, QStringList &reference, const QStringList &defaultValue = QStringList()); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; }; /** * Class for handling a path list preferences item. */ class KCONFIGCORE_EXPORT ItemPathList: public ItemStringList { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemPathList(const QString &_group, const QString &_key, QStringList &reference, const QStringList &defaultValue = QStringList()); /** @copydoc KConfigSkeletonItem::readConfig */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::writeConfig */ void writeConfig(KConfig *config) override; }; /** * Class for handling a url list preferences item. */ class KCONFIGCORE_EXPORT ItemUrlList: public KConfigSkeletonGenericItem < QList > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemUrlList(const QString &_group, const QString &_key, QList &reference, const QList &defaultValue = QList()); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */ void writeConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; }; /** * Class for handling an integer list preferences item. */ class KCONFIGCORE_EXPORT ItemIntList: public KConfigSkeletonGenericItem < QList < int > > { public: /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */ ItemIntList(const QString &_group, const QString &_key, QList < int > &reference, const QList < int > &defaultValue = QList < int >()); /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */ void readConfig(KConfig *config) override; /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */ void setProperty(const QVariant &p) override; /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */ bool isEqual(const QVariant &p) const override; /** @copydoc KConfigSkeletonItem::property() */ QVariant property() const override; }; public: /** * Constructor. * * @param configname name of config file. If no name is given, the default * config file as returned by KSharedConfig::openConfig() is used * @param parent the parent object (see QObject documentation) */ explicit KCoreConfigSkeleton(const QString &configname = QString(), QObject *parent = nullptr); /** * Constructor. * * @param config configuration object to use * @param parent the parent object (see QObject documentation) */ explicit KCoreConfigSkeleton(KSharedConfig::Ptr config, QObject *parent = nullptr); /** * Destructor */ virtual ~KCoreConfigSkeleton(); /** * Set all registered items to their default values. * This method calls usrSetDefaults() after setting the defaults for the * registered items. You can override usrSetDefaults() in derived classes * if you have special requirements. * If you need more fine-grained control of setting the default values of * the registered items you can override setDefaults() in a derived class. */ virtual void setDefaults(); /** * Read preferences from config file. All registered items are set to the * values read from disk. * This method calls usrRead() after reading the settings of the * registered items from the KConfig. You can override usrRead() * in derived classes if you have special requirements. */ void load(); #ifndef KCONFIGCORE_NO_DEPRECATED /** * @deprecated since 5.0, call load() instead (to reload from disk) or just read() * if the underlying KConfig object is already up-to-date. */ KCONFIGCORE_DEPRECATED void readConfig() { load(); } #endif /** * Read preferences from the KConfig object. * This method assumes that the KConfig object was previously loaded, * i.e. it uses the in-memory values from KConfig without reloading from disk. * * This method calls usrRead() after reading the settings of the * registered items from the KConfig. You can override usrRead() * in derived classes if you have special requirements. * @since 5.0 */ void read(); /** * Set the config file group for subsequent addItem() calls. It is valid * until setCurrentGroup() is called with a new argument. Call this before * you add any items. The default value is "No Group". */ void setCurrentGroup(const QString &group); /** * Returns the current group used for addItem() calls. */ QString currentGroup() const; /** * Register a custom @ref KConfigSkeletonItem with a given name. * * If the name parameter is null, take the name from KConfigSkeletonItem::key(). * Note that all names must be unique but that multiple entries can have * the same key if they reside in different groups. * * KCoreConfigSkeleton takes ownership of the KConfigSkeletonItem. */ void addItem(KConfigSkeletonItem *, const QString &name = QString()); /** * Register an item of type QString. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemString *addItemString(const QString &name, QString &reference, const QString &defaultValue = QLatin1String(""), // NOT QString() !! const QString &key = QString()); /** * Register a password item of type QString. The string value is written * encrypted to the config file. Note that the current encryption scheme * is very weak. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemPassword *addItemPassword(const QString &name, QString &reference, const QString &defaultValue = QLatin1String(""), const QString &key = QString()); /** * Register a path item of type QString. The string value is interpreted * as a path. This means, dollar expension is activated for this value, so * that e.g. $HOME gets expanded. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemPath *addItemPath(const QString &name, QString &reference, const QString &defaultValue = QLatin1String(""), const QString &key = QString()); /** * Register a property item of type QVariant. Note that only the following * QVariant types are allowed: String, StringList, Font, Point, Rect, Size, * Color, Int, UInt, Bool, Double, DateTime and Date. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemProperty *addItemProperty(const QString &name, QVariant &reference, const QVariant &defaultValue = QVariant(), const QString &key = QString()); /** * Register an item of type bool. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemBool *addItemBool(const QString &name, bool &reference, bool defaultValue = false, const QString &key = QString()); /** * Register an item of type qint32. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemInt *addItemInt(const QString &name, qint32 &reference, qint32 defaultValue = 0, const QString &key = QString()); /** * Register an item of type quint32. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemUInt *addItemUInt(const QString &name, quint32 &reference, quint32 defaultValue = 0, const QString &key = QString()); /** * Register an item of type qint64. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemLongLong *addItemLongLong(const QString &name, qint64 &reference, qint64 defaultValue = 0, const QString &key = QString()); /** * @deprecated * Use addItemLongLong(). */ #ifndef KDE_NO_DEPRECATED KCONFIGCORE_DEPRECATED ItemLongLong *addItemInt64(const QString &name, qint64 &reference, qint64 defaultValue = 0, const QString &key = QString()); #endif /** * Register an item of type quint64 * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemULongLong *addItemULongLong(const QString &name, quint64 &reference, quint64 defaultValue = 0, const QString &key = QString()); /** * @deprecated * Use addItemULongLong(). */ #ifndef KDE_NO_DEPRECATED KCONFIGCORE_DEPRECATED ItemULongLong *addItemUInt64(const QString &name, quint64 &reference, quint64 defaultValue = 0, const QString &key = QString()); #endif /** * Register an item of type double. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemDouble *addItemDouble(const QString &name, double &reference, double defaultValue = 0.0, const QString &key = QString()); /** * Register an item of type QRect. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemRect *addItemRect(const QString &name, QRect &reference, const QRect &defaultValue = QRect(), const QString &key = QString()); /** * Register an item of type QPoint. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemPoint *addItemPoint(const QString &name, QPoint &reference, const QPoint &defaultValue = QPoint(), const QString &key = QString()); /** * Register an item of type QSize. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemSize *addItemSize(const QString &name, QSize &reference, const QSize &defaultValue = QSize(), const QString &key = QString()); /** * Register an item of type QDateTime. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemDateTime *addItemDateTime(const QString &name, QDateTime &reference, const QDateTime &defaultValue = QDateTime(), const QString &key = QString()); /** * Register an item of type QStringList. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemStringList *addItemStringList(const QString &name, QStringList &reference, const QStringList &defaultValue = QStringList(), const QString &key = QString()); /** * Register an item of type QList. * * @param name Name used to identify this setting. Names must be unique. * @param reference Pointer to the variable, which is set by readConfig() * calls and read by save() calls. * @param defaultValue Default value, which is used when the config file * does not yet contain the key of this item. * @param key Key used in config file. If key is null, name is used as key. * @return The created item */ ItemIntList *addItemIntList(const QString &name, QList < int > &reference, const QList < int > &defaultValue = QList < int >(), const QString &key = QString()); /** * Return the @ref KConfig object used for reading and writing the settings. */ KConfig *config(); /** * Return the @ref KConfig object used for reading and writing the settings. */ const KConfig *config() const; /** * Return the @ref KConfig object used for reading and writing the settings. * @since 5.0 */ KSharedConfig::Ptr sharedConfig() const; /** * Set the @ref KSharedConfig object used for reading and writing the settings. */ void setSharedConfig(KSharedConfig::Ptr pConfig); /** * Return list of items managed by this KCoreConfigSkeleton object. */ KConfigSkeletonItem::List items() const; /** * Removes and deletes an item by name * @param name the name of the item to remove */ void removeItem(const QString &name); /** * Removes and deletes all items */ void clearItems(); /** * Return whether a certain item is immutable * @since 4.4 */ bool isImmutable(const QString &name) const; /** * Lookup item by name * @since 4.4 */ KConfigSkeletonItem *findItem(const QString &name) const; /** * Specify whether this object should reflect the actual values or the * default values. * This method is implemented by usrUseDefaults(), which can be overridden * in derived classes if you have special requirements and can call * usrUseDefaults() directly. * If you don't have control whether useDefaults() or usrUseDefaults() is * called override useDefaults() directly. * @param b true to make this object reflect the default values, * false to make it reflect the actual values. * @return The state prior to this call */ virtual bool useDefaults(bool b); public Q_SLOTS: /** * Write preferences to config file. The values of all registered items are * written to disk. * This method calls usrSave() after writing the settings from the * registered items to the KConfig. You can override usrSave() * in derived classes if you have special requirements. */ bool save(); #ifndef KCONFIGCORE_NO_DEPRECATED /** * @deprecated since 5.0, call save() instead. */ KCONFIGCORE_DEPRECATED void writeConfig() { save(); } #endif Q_SIGNALS: /** * This signal is emitted when the configuration change. */ void configChanged(); protected: /** * Implemented by subclasses that use special defaults. * It replaces the default values with the actual values and * vice versa. Called from @ref useDefaults() * @param b true to make this object reflect the default values, * false to make it reflect the actual values. * @return The state prior to this call */ virtual bool usrUseDefaults(bool b); /** * Perform the actual setting of default values. * Override in derived classes to set special default values. * Called from @ref setDefaults() */ virtual void usrSetDefaults(); /** * Perform the actual reading of the configuration file. * Override in derived classes to read special config values. * Called from @ref read() */ virtual void usrRead(); /** * Perform the actual writing of the configuration file. * Override in derived classes to write special config values. * Called from @ref writeConfig() */ virtual bool usrSave(); /** * @deprecated since 5.0, override usrRead instead. This method is still called from usrRead * for compatibility. */ KCONFIGCORE_DEPRECATED virtual void usrReadConfig(); /** * @deprecated since 5.0, override usrSave instead. This method is still called from usrSave * for compatibility. */ KCONFIGCORE_DEPRECATED virtual bool usrWriteConfig(); private: KCoreConfigSkeletonPrivate *const d; friend class KConfigSkeleton; }; #endif diff --git a/src/core/kcoreconfigskeleton_p.h b/src/core/kcoreconfigskeleton_p.h index 88a41d8..41005c6 100644 --- a/src/core/kcoreconfigskeleton_p.h +++ b/src/core/kcoreconfigskeleton_p.h @@ -1,63 +1,65 @@ /* This file is part of KOrganizer. Copyright (c) 2000,2001 Cornelius Schumacher Copyright (c) 2003 Waldo Bastian This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KCORECONFIGSKELETON_P_H #define KCORECONFIGSKELETON_P_H #include "kcoreconfigskeleton.h" class KCoreConfigSkeletonPrivate { public: KCoreConfigSkeletonPrivate() : mCurrentGroup(QStringLiteral("No Group")), mUseDefaults(false) {} ~KCoreConfigSkeletonPrivate() { KConfigSkeletonItem::List::ConstIterator it; for (it = mItems.constBegin(); it != mItems.constEnd(); ++it) { delete *it; } } QString mCurrentGroup; KSharedConfig::Ptr mConfig; // pointer to KConfig object KConfigSkeletonItem::List mItems; KConfigSkeletonItem::Dict mItemDict; bool mUseDefaults; }; class KConfigSkeletonItemPrivate { public: KConfigSkeletonItemPrivate() : mIsImmutable(true) + , mWriteFlags(KConfigBase::Normal) {} bool mIsImmutable; ///< Indicates this item is immutable + KConfigBase::WriteConfigFlags mWriteFlags; ///< The flags to pass to calls of writeEntry() and revertToDefault() QString mLabel; ///< The label for this item QString mToolTip; ///< The ToolTip text for this item QString mWhatsThis; ///< The What's This text for this item }; #endif diff --git a/src/kconfig_compiler/kconfig_compiler.cpp b/src/kconfig_compiler/kconfig_compiler.cpp index b467a20..abb8e11 100644 --- a/src/kconfig_compiler/kconfig_compiler.cpp +++ b/src/kconfig_compiler/kconfig_compiler.cpp @@ -1,2695 +1,2703 @@ /* This file is part of KDE. Copyright (c) 2003 Cornelius Schumacher Copyright (c) 2003 Waldo Bastian Copyright (c) 2003 Zack Rusin Copyright (c) 2006 Michaël Larouche Copyright (c) 2008 Allen Winter This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // Compiling this file with this flag is just crazy #undef QT_NO_CAST_FROM_ASCII #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../kconfig_version.h" namespace { QTextStream cout(stdout); QTextStream cerr(stderr); } QStringList allNames; QRegExp *validNameRegexp; QString This; QString Const; /** Configuration Compiler Configuration */ class CfgConfig { public: CfgConfig(const QString &codegenFilename) { // Configure the compiler with some settings QSettings codegenConfig(codegenFilename, QSettings::IniFormat); nameSpace = codegenConfig.value(QStringLiteral("NameSpace")).toString(); className = codegenConfig.value(QStringLiteral("ClassName")).toString(); if (className.isEmpty()) { cerr << "Class name missing" << endl; exit(1); } inherits = codegenConfig.value(QStringLiteral("Inherits")).toString(); if (inherits.isEmpty()) { inherits = QStringLiteral("KConfigSkeleton"); } visibility = codegenConfig.value(QStringLiteral("Visibility")).toString(); if (!visibility.isEmpty()) { visibility += ' '; } forceStringFilename = codegenConfig.value(QStringLiteral("ForceStringFilename"), false).toBool(); singleton = codegenConfig.value(QStringLiteral("Singleton"), false).toBool(); staticAccessors = singleton; customAddons = codegenConfig.value(QStringLiteral("CustomAdditions"), false).toBool(); memberVariables = codegenConfig.value(QStringLiteral("MemberVariables")).toString(); dpointer = (memberVariables == QLatin1String("dpointer")); headerIncludes = codegenConfig.value(QStringLiteral("IncludeFiles"), QStringList()).toStringList(); sourceIncludes = codegenConfig.value(QStringLiteral("SourceIncludeFiles"), QStringList()).toStringList(); mutators = codegenConfig.value(QStringLiteral("Mutators"), QStringList()).toStringList(); allMutators = ((mutators.count() == 1) && (mutators.at(0).toLower() == QLatin1String("true"))); itemAccessors = codegenConfig.value(QStringLiteral("ItemAccessors"), false).toBool(); setUserTexts = codegenConfig.value(QStringLiteral("SetUserTexts"), false).toBool(); defaultGetters = codegenConfig.value(QStringLiteral("DefaultValueGetters"), QStringList()).toStringList(); allDefaultGetters = (defaultGetters.count() == 1) && (defaultGetters.at(0).toLower() == QLatin1String("true")); + notifiers = codegenConfig.value(QStringLiteral("Notifiers"), QStringList()).toStringList(); + allNotifiers = ((notifiers.count() == 1) && (notifiers.at(0).toLower() == QLatin1String("true"))); globalEnums = codegenConfig.value(QStringLiteral("GlobalEnums"), false).toBool(); useEnumTypes = codegenConfig.value(QStringLiteral("UseEnumTypes"), false).toBool(); const QString trString = codegenConfig.value(QStringLiteral("TranslationSystem")).toString().toLower(); generateProperties = codegenConfig.value(QStringLiteral("GenerateProperties"), false).toBool(); if (trString == QLatin1String("kde")) { translationSystem = KdeTranslation; translationDomain = codegenConfig.value(QStringLiteral("TranslationDomain")).toString(); } else { if (!trString.isEmpty() && trString != QLatin1String("qt")) { cerr << "Unknown translation system, falling back to Qt tr()" << endl; } translationSystem = QtTranslation; } qCategoryLoggingName = codegenConfig.value(QStringLiteral("CategoryLoggingName"), QString()).toString(); headerExtension = codegenConfig.value(QStringLiteral("HeaderExtension"), QStringLiteral("h")).toString(); sourceExtension = codegenConfig.value(QStringLiteral("SourceExtension"), QStringLiteral("cpp")).toString(); } public: enum TranslationSystem { QtTranslation, KdeTranslation }; // These are read from the .kcfgc configuration file QString nameSpace; // The namespace for the class to be generated QString className; // The class name to be generated QString inherits; // The class the generated class inherits (if empty, from KConfigSkeleton) QString visibility; bool forceStringFilename; bool singleton; // The class will be a singleton bool staticAccessors; // provide or not static accessors bool customAddons; QString memberVariables; QStringList headerIncludes; QStringList sourceIncludes; QStringList mutators; QStringList defaultGetters; + QStringList notifiers; QString qCategoryLoggingName; QString headerExtension; QString sourceExtension; bool allMutators; bool setUserTexts; bool allDefaultGetters; bool dpointer; bool globalEnums; bool useEnumTypes; bool itemAccessors; + bool allNotifiers; TranslationSystem translationSystem; QString translationDomain; bool generateProperties; }; struct SignalArguments { QString type; QString variableName; }; class Signal { public: Signal() : modify(false) {} QString name; QString label; QList arguments; bool modify; }; class CfgEntry { public: struct Choice { QString name; QString context; QString label; QString toolTip; QString whatsThis; }; class Choices { public: Choices() {} Choices(const QList &d, const QString &n, const QString &p) : prefix(p), choices(d), mName(n) { int i = n.indexOf(QLatin1String("::")); if (i >= 0) { mExternalQual = n.left(i + 2); } } QString prefix; QList choices; const QString &name() const { return mName; } const QString &externalQualifier() const { return mExternalQual; } bool external() const { return !mExternalQual.isEmpty(); } private: QString mName; QString mExternalQual; }; CfgEntry(const QString &group, const QString &type, const QString &key, const QString &name, const QString &labelContext, const QString &label, const QString &toolTipContext, const QString &toolTip, const QString &whatsThisContext, const QString &whatsThis, const QString &code, const QString &defaultValue, const Choices &choices, const QList &signalList, bool hidden) : mGroup(group), mType(type), mKey(key), mName(name), mLabelContext(labelContext), mLabel(label), mToolTipContext(toolTipContext), mToolTip(toolTip), mWhatsThisContext(whatsThisContext), mWhatsThis(whatsThis), mCode(code), mDefaultValue(defaultValue), mChoices(choices), mSignalList(signalList), mParamMax(0), mHidden(hidden) { } void setGroup(const QString &group) { mGroup = group; } QString group() const { return mGroup; } void setType(const QString &type) { mType = type; } QString type() const { return mType; } void setKey(const QString &key) { mKey = key; } QString key() const { return mKey; } void setName(const QString &name) { mName = name; } QString name() const { return mName; } void setLabelContext(const QString &labelContext) { mLabelContext = labelContext; } QString labelContext() const { return mLabelContext; } void setLabel(const QString &label) { mLabel = label; } QString label() const { return mLabel; } void setToolTipContext(const QString &toolTipContext) { mToolTipContext = toolTipContext; } QString toolTipContext() const { return mToolTipContext; } void setToolTip(const QString &toolTip) { mToolTip = toolTip; } QString toolTip() const { return mToolTip; } void setWhatsThisContext(const QString &whatsThisContext) { mWhatsThisContext = whatsThisContext; } QString whatsThisContext() const { return mWhatsThisContext; } void setWhatsThis(const QString &whatsThis) { mWhatsThis = whatsThis; } QString whatsThis() const { return mWhatsThis; } void setDefaultValue(const QString &d) { mDefaultValue = d; } QString defaultValue() const { return mDefaultValue; } void setCode(const QString &d) { mCode = d; } QString code() const { return mCode; } void setMinValue(const QString &d) { mMin = d; } QString minValue() const { return mMin; } void setMaxValue(const QString &d) { mMax = d; } QString maxValue() const { return mMax; } void setParam(const QString &d) { mParam = d; } QString param() const { return mParam; } void setParamName(const QString &d) { mParamName = d; } QString paramName() const { return mParamName; } void setParamType(const QString &d) { mParamType = d; } QString paramType() const { return mParamType; } void setChoices(const QList &d, const QString &n, const QString &p) { mChoices = Choices(d, n, p); } Choices choices() const { return mChoices; } void setParamValues(const QStringList &d) { mParamValues = d; } QStringList paramValues() const { return mParamValues; } void setParamDefaultValues(const QStringList &d) { mParamDefaultValues = d; } QString paramDefaultValue(int i) const { return mParamDefaultValues[i]; } void setParamMax(int d) { mParamMax = d; } int paramMax() const { return mParamMax; } void setSignalList(const QList &value) { mSignalList = value; } QList signalList() const { return mSignalList; } bool hidden() const { return mHidden; } void dump() const { cerr << "" << endl; cerr << " group: " << mGroup << endl; cerr << " type: " << mType << endl; cerr << " key: " << mKey << endl; cerr << " name: " << mName << endl; cerr << " label context: " << mLabelContext << endl; cerr << " label: " << mLabel << endl; // whatsthis cerr << " code: " << mCode << endl; // cerr << " values: " << mValues.join(":") << endl; if (!param().isEmpty()) { cerr << " param name: " << mParamName << endl; cerr << " param type: " << mParamType << endl; cerr << " paramvalues: " << mParamValues.join(QChar::fromLatin1(':')) << endl; } cerr << " default: " << mDefaultValue << endl; cerr << " hidden: " << mHidden << endl; cerr << " min: " << mMin << endl; cerr << " max: " << mMax << endl; cerr << "" << endl; } private: QString mGroup; QString mType; QString mKey; QString mName; QString mLabelContext; QString mLabel; QString mToolTipContext; QString mToolTip; QString mWhatsThisContext; QString mWhatsThis; QString mCode; QString mDefaultValue; QString mParam; QString mParamName; QString mParamType; Choices mChoices; QList mSignalList; QStringList mParamValues; QStringList mParamDefaultValues; int mParamMax; bool mHidden; QString mMin; QString mMax; }; class Param { public: QString name; QString type; }; // returns the name of an member variable // use itemPath to know the full path // like using d-> in case of dpointer static QString varName(const QString &n, const CfgConfig &cfg) { QString result; if (!cfg.dpointer) { result = QChar::fromLatin1('m') + n; result[1] = result[1].toUpper(); } else { result = n; result[0] = result[0].toLower(); } return result; } static QString varPath(const QString &n, const CfgConfig &cfg) { QString result; if (cfg.dpointer) { result = "d->" + varName(n, cfg); } else { result = varName(n, cfg); } return result; } static QString enumName(const QString &n) { QString result = QLatin1String("Enum") + n; result[4] = result[4].toUpper(); return result; } static QString enumName(const QString &n, const CfgEntry::Choices &c) { QString result = c.name(); if (result.isEmpty()) { result = QLatin1String("Enum") + n; result[4] = result[4].toUpper(); } return result; } static QString enumType(const CfgEntry *e, bool globalEnums) { QString result = e->choices().name(); if (result.isEmpty()) { result = QLatin1String("Enum") + e->name(); if (!globalEnums) { result += QLatin1String("::type"); } result[4] = result[4].toUpper(); } return result; } static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c) { QString result = c.name(); if (result.isEmpty()) { result = QLatin1String("Enum") + n + QLatin1String("::"); result[4] = result[4].toUpper(); } else if (c.external()) { result = c.externalQualifier(); } else { result.clear(); } return result; } static QString setFunction(const QString &n, const QString &className = QString()) { QString result = QLatin1String("set") + n; result[3] = result[3].toUpper(); if (!className.isEmpty()) { result = className + QLatin1String("::") + result; } return result; } static QString changeSignalName(const QString &n) { return n+QStringLiteral("Changed"); } static QString getDefaultFunction(const QString &n, const QString &className = QString()) { QString result = QLatin1String("default") + n + QLatin1String("Value"); result[7] = result[7].toUpper(); if (!className.isEmpty()) { result = className + QLatin1String("::") + result; } return result; } static QString getFunction(const QString &n, const QString &className = QString()) { QString result = n; result[0] = result[0].toLower(); if (!className.isEmpty()) { result = className + QLatin1String("::") + result; } return result; } static void addQuotes(QString &s) { if (!s.startsWith(QLatin1Char('"'))) { s.prepend(QLatin1Char('"')); } if (!s.endsWith(QLatin1Char('"'))) { s.append(QLatin1Char('"')); } } static QString quoteString(const QString &s) { QString r = s; r.replace(QLatin1Char('\\'), QLatin1String("\\\\")); r.replace(QLatin1Char('\"'), QLatin1String("\\\"")); r.remove(QLatin1Char('\r')); r.replace(QLatin1Char('\n'), QLatin1String("\\n\"\n\"")); return QLatin1Char('\"') + r + QLatin1Char('\"'); } static QString literalString(const QString &s) { bool isAscii = true; for (int i = s.length(); i--;) if (s[i].unicode() > 127) { isAscii = false; } if (isAscii) { return QLatin1String("QStringLiteral( ") + quoteString(s) + QLatin1String(" )"); } else { return QLatin1String("QString::fromUtf8( ") + quoteString(s) + QLatin1String(" )"); } } static QString dumpNode(const QDomNode &node) { QString msg; QTextStream s(&msg, QIODevice::WriteOnly); node.save(s, 0); msg = msg.simplified(); if (msg.length() > 40) { return msg.left(37) + QLatin1String("..."); } return msg; } static QString filenameOnly(const QString &path) { int i = path.lastIndexOf(QRegExp(QStringLiteral("[/\\]"))); if (i >= 0) { return path.mid(i + 1); } return path; } static QString signalEnumName(const QString &signalName) { QString result; result = QLatin1String("signal") + signalName; result[6] = result[6].toUpper(); return result; } static void preProcessDefault(QString &defaultValue, const QString &name, const QString &type, const CfgEntry::Choices &choices, QString &code, const CfgConfig &cfg) { if (type == QLatin1String("String") && !defaultValue.isEmpty()) { defaultValue = literalString(defaultValue); } else if (type == QLatin1String("Path") && !defaultValue.isEmpty()) { defaultValue = literalString(defaultValue); } else if (type == QLatin1String("Url") && !defaultValue.isEmpty()) { // Use fromUserInput in order to support absolute paths and absolute urls, like KDE4's KUrl(QString) did. defaultValue = QLatin1String("QUrl::fromUserInput( ") + literalString(defaultValue) + QLatin1Char(')'); } else if ((type == QLatin1String("UrlList") || type == QLatin1String("StringList") || type == QLatin1String("PathList")) && !defaultValue.isEmpty()) { QTextStream cpp(&code, QIODevice::WriteOnly | QIODevice::Append); if (!code.isEmpty()) { cpp << endl; } if (type == QLatin1String("UrlList")) { cpp << " QList default" << name << ";" << endl; } else { cpp << " QStringList default" << name << ";" << endl; } const QStringList defaults = defaultValue.split(QLatin1Char(',')); QStringList::ConstIterator it; for (it = defaults.constBegin(); it != defaults.constEnd(); ++it) { cpp << " default" << name << ".append( "; if (type == QLatin1String("UrlList")) { cpp << "QUrl::fromUserInput("; } cpp << "QString::fromUtf8( \"" << *it << "\" ) "; if (type == QLatin1String("UrlList")) { cpp << ") "; } cpp << ");" << endl; } defaultValue = QLatin1String("default") + name; } else if (type == QLatin1String("Color") && !defaultValue.isEmpty()) { QRegExp colorRe(QStringLiteral("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?")); if (colorRe.exactMatch(defaultValue)) { defaultValue = QLatin1String("QColor( ") + defaultValue + QLatin1String(" )"); } else { defaultValue = QLatin1String("QColor( \"") + defaultValue + QLatin1String("\" )"); } } else if (type == QLatin1String("Enum")) { QList::ConstIterator it; for (it = choices.choices.constBegin(); it != choices.choices.constEnd(); ++it) { if ((*it).name == defaultValue) { if (cfg.globalEnums && choices.name().isEmpty()) { defaultValue.prepend(choices.prefix); } else { defaultValue.prepend(enumTypeQualifier(name, choices) + choices.prefix); } break; } } } else if (type == QLatin1String("IntList")) { QTextStream cpp(&code, QIODevice::WriteOnly | QIODevice::Append); if (!code.isEmpty()) { cpp << endl; } cpp << " QList default" << name << ";" << endl; if (!defaultValue.isEmpty()) { const QStringList defaults = defaultValue.split(QLatin1Char(',')); QStringList::ConstIterator it; for (it = defaults.constBegin(); it != defaults.constEnd(); ++it) { cpp << " default" << name << ".append( " << *it << " );" << endl; } } defaultValue = QLatin1String("default") + name; } } CfgEntry *parseEntry(const QString &group, const QDomElement &element, const CfgConfig &cfg) { bool defaultCode = false; QString type = element.attribute(QStringLiteral("type")); QString name = element.attribute(QStringLiteral("name")); QString key = element.attribute(QStringLiteral("key")); QString hidden = element.attribute(QStringLiteral("hidden")); QString labelContext; QString label; QString toolTipContext; QString toolTip; QString whatsThisContext; QString whatsThis; QString defaultValue; QString code; QString param; QString paramName; QString paramType; CfgEntry::Choices choices; QList signalList; QStringList paramValues; QStringList paramDefaultValues; QString minValue; QString maxValue; int paramMax = 0; for (QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) { QString tag = e.tagName(); if (tag == QLatin1String("label")) { label = e.text(); labelContext = e.attribute(QStringLiteral("context")); } else if (tag == QLatin1String("tooltip")) { toolTip = e.text(); toolTipContext = e.attribute(QStringLiteral("context")); } else if (tag == QLatin1String("whatsthis")) { whatsThis = e.text(); whatsThisContext = e.attribute(QStringLiteral("context")); } else if (tag == QLatin1String("min")) { minValue = e.text(); } else if (tag == QLatin1String("max")) { maxValue = e.text(); } else if (tag == QLatin1String("code")) { code = e.text(); } else if (tag == QLatin1String("parameter")) { param = e.attribute(QStringLiteral("name")); paramType = e.attribute(QStringLiteral("type")); if (param.isEmpty()) { cerr << "Parameter must have a name: " << dumpNode(e) << endl; return nullptr; } if (paramType.isEmpty()) { cerr << "Parameter must have a type: " << dumpNode(e) << endl; return nullptr; } if ((paramType == QLatin1String("Int")) || (paramType == QLatin1String("UInt"))) { bool ok; paramMax = e.attribute(QStringLiteral("max")).toInt(&ok); if (!ok) { cerr << "Integer parameter must have a maximum (e.g. max=\"0\"): " << dumpNode(e) << endl; return nullptr; } } else if (paramType == QLatin1String("Enum")) { for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) { if (e2.tagName() == QLatin1String("values")) { for (QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement()) { if (e3.tagName() == QLatin1String("value")) { paramValues.append(e3.text()); } } break; } } if (paramValues.isEmpty()) { cerr << "No values specified for parameter '" << param << "'." << endl; return nullptr; } paramMax = paramValues.count() - 1; } else { cerr << "Parameter '" << param << "' has type " << paramType << " but must be of type int, uint or Enum." << endl; return nullptr; } } else if (tag == QLatin1String("default")) { if (e.attribute(QStringLiteral("param")).isEmpty()) { defaultValue = e.text(); if (e.attribute(QStringLiteral("code")) == QLatin1String("true")) { defaultCode = true; } } } else if (tag == QLatin1String("choices")) { QString name = e.attribute(QStringLiteral("name")); QString prefix = e.attribute(QStringLiteral("prefix")); QList chlist; for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) { if (e2.tagName() == QLatin1String("choice")) { CfgEntry::Choice choice; choice.name = e2.attribute(QStringLiteral("name")); if (choice.name.isEmpty()) { cerr << "Tag requires attribute 'name'." << endl; } for (QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement()) { if (e3.tagName() == QLatin1String("label")) { choice.label = e3.text(); choice.context = e3.attribute(QStringLiteral("context")); } if (e3.tagName() == QLatin1String("tooltip")) { choice.toolTip = e3.text(); choice.context = e3.attribute(QStringLiteral("context")); } if (e3.tagName() == QLatin1String("whatsthis")) { choice.whatsThis = e3.text(); choice.context = e3.attribute(QStringLiteral("context")); } } chlist.append(choice); } } choices = CfgEntry::Choices(chlist, name, prefix); } else if (tag == QLatin1String("emit")) { Signal signal; signal.name = e.attribute(QStringLiteral("signal")); signalList.append(signal); } } if (cfg.generateProperties && (cfg.allMutators || cfg.mutators.contains(name))) { Signal s; s.name = changeSignalName(name); s.modify = true; signalList.append(s); } bool nameIsEmpty = name.isEmpty(); if (nameIsEmpty && key.isEmpty()) { cerr << "Entry must have a name or a key: " << dumpNode(element) << endl; return nullptr; } if (key.isEmpty()) { key = name; } if (nameIsEmpty) { name = key; name.remove(' '); } else if (name.contains(' ')) { cout << "Entry '" << name << "' contains spaces! elements can not contain spaces!" << endl; name.remove(' '); } if (name.contains(QStringLiteral("$("))) { if (param.isEmpty()) { cerr << "Name may not be parameterized: " << name << endl; return nullptr; } } else { if (!param.isEmpty()) { cerr << "Name must contain '$(" << param << ")': " << name << endl; return nullptr; } } if (label.isEmpty()) { label = key; } if (type.isEmpty()) { type = QStringLiteral("String"); // XXX : implicit type might be bad } if (!param.isEmpty()) { // Adjust name paramName = name; name.remove("$(" + param + ')'); // Lookup defaults for indexed entries for (int i = 0; i <= paramMax; i++) { paramDefaultValues.append(QString()); } for (QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) { QString tag = e.tagName(); if (tag == QLatin1String("default")) { QString index = e.attribute(QStringLiteral("param")); if (index.isEmpty()) { continue; } bool ok; int i = index.toInt(&ok); if (!ok) { i = paramValues.indexOf(index); if (i == -1) { cerr << "Index '" << index << "' for default value is unknown." << endl; return nullptr; } } if ((i < 0) || (i > paramMax)) { cerr << "Index '" << i << "' for default value is out of range [0, " << paramMax << "]." << endl; return nullptr; } QString tmpDefaultValue = e.text(); if (e.attribute(QStringLiteral("code")) != QLatin1String("true")) { preProcessDefault(tmpDefaultValue, name, type, choices, code, cfg); } paramDefaultValues[i] = tmpDefaultValue; } } } if (!validNameRegexp->exactMatch(name)) { if (nameIsEmpty) cerr << "The key '" << key << "' can not be used as name for the entry because " "it is not a valid name. You need to specify a valid name for this entry." << endl; else { cerr << "The name '" << name << "' is not a valid name for an entry." << endl; } return nullptr; } if (allNames.contains(name)) { if (nameIsEmpty) cerr << "The key '" << key << "' can not be used as name for the entry because " "it does not result in a unique name. You need to specify a unique name for this entry." << endl; else { cerr << "The name '" << name << "' is not unique." << endl; } return nullptr; } allNames.append(name); if (!defaultCode) { preProcessDefault(defaultValue, name, type, choices, code, cfg); } CfgEntry *result = new CfgEntry(group, type, key, name, labelContext, label, toolTipContext, toolTip, whatsThisContext, whatsThis, code, defaultValue, choices, signalList, hidden == QLatin1String("true")); if (!param.isEmpty()) { result->setParam(param); result->setParamName(paramName); result->setParamType(paramType); result->setParamValues(paramValues); result->setParamDefaultValues(paramDefaultValues); result->setParamMax(paramMax); } result->setMinValue(minValue); result->setMaxValue(maxValue); return result; } static bool isUnsigned(const QString &type) { if (type == QLatin1String("UInt")) { return true; } if (type == QLatin1String("ULongLong")) { return true; } return false; } /** Return parameter declaration for given type. */ QString param(const QString &t) { const QString type = t.toLower(); if (type == QLatin1String("string")) { return QStringLiteral("const QString &"); } else if (type == QLatin1String("stringlist")) { return QStringLiteral("const QStringList &"); } else if (type == QLatin1String("font")) { return QStringLiteral("const QFont &"); } else if (type == QLatin1String("rect")) { return QStringLiteral("const QRect &"); } else if (type == QLatin1String("size")) { return QStringLiteral("const QSize &"); } else if (type == QLatin1String("color")) { return QStringLiteral("const QColor &"); } else if (type == QLatin1String("point")) { return QStringLiteral("const QPoint &"); } else if (type == QLatin1String("int")) { return QStringLiteral("int"); } else if (type == QLatin1String("uint")) { return QStringLiteral("uint"); } else if (type == QLatin1String("bool")) { return QStringLiteral("bool"); } else if (type == QLatin1String("double")) { return QStringLiteral("double"); } else if (type == QLatin1String("datetime")) { return QStringLiteral("const QDateTime &"); } else if (type == QLatin1String("longlong")) { return QStringLiteral("qint64"); } else if (type == QLatin1String("ulonglong")) { return QStringLiteral("quint64"); } else if (type == QLatin1String("intlist")) { return QStringLiteral("const QList &"); } else if (type == QLatin1String("enum")) { return QStringLiteral("int"); } else if (type == QLatin1String("path")) { return QStringLiteral("const QString &"); } else if (type == QLatin1String("pathlist")) { return QStringLiteral("const QStringList &"); } else if (type == QLatin1String("password")) { return QStringLiteral("const QString &"); } else if (type == QLatin1String("url")) { return QStringLiteral("const QUrl &"); } else if (type == QLatin1String("urllist")) { return QStringLiteral("const QList &"); } else { cerr << "kconfig_compiler_kf5 does not support type \"" << type << "\"" << endl; return QStringLiteral("QString"); //For now, but an assert would be better } } /** Actual C++ storage type for given type. */ QString cppType(const QString &t) { const QString type = t.toLower(); if (type == QLatin1String("string")) { return QStringLiteral("QString"); } else if (type == QLatin1String("stringlist")) { return QStringLiteral("QStringList"); } else if (type == QLatin1String("font")) { return QStringLiteral("QFont"); } else if (type == QLatin1String("rect")) { return QStringLiteral("QRect"); } else if (type == QLatin1String("size")) { return QStringLiteral("QSize"); } else if (type == QLatin1String("color")) { return QStringLiteral("QColor"); } else if (type == QLatin1String("point")) { return QStringLiteral("QPoint"); } else if (type == QLatin1String("int")) { return QStringLiteral("int"); } else if (type == QLatin1String("uint")) { return QStringLiteral("uint"); } else if (type == QLatin1String("bool")) { return QStringLiteral("bool"); } else if (type == QLatin1String("double")) { return QStringLiteral("double"); } else if (type == QLatin1String("datetime")) { return QStringLiteral("QDateTime"); } else if (type == QLatin1String("longlong")) { return QStringLiteral("qint64"); } else if (type == QLatin1String("ulonglong")) { return QStringLiteral("quint64"); } else if (type == QLatin1String("intlist")) { return QStringLiteral("QList"); } else if (type == QLatin1String("enum")) { return QStringLiteral("int"); } else if (type == QLatin1String("path")) { return QStringLiteral("QString"); } else if (type == QLatin1String("pathlist")) { return QStringLiteral("QStringList"); } else if (type == QLatin1String("password")) { return QStringLiteral("QString"); } else if (type == QLatin1String("url")) { return QStringLiteral("QUrl"); } else if (type == QLatin1String("urllist")) { return QStringLiteral("QList"); } else { cerr << "kconfig_compiler_kf5 does not support type \"" << type << "\"" << endl; return QStringLiteral("QString"); //For now, but an assert would be better } } QString defaultValue(const QString &t) { const QString type = t.toLower(); if (type == QLatin1String("string")) { return QStringLiteral("\"\""); // Use empty string, not null string! } else if (type == QLatin1String("stringlist")) { return QStringLiteral("QStringList()"); } else if (type == QLatin1String("font")) { return QStringLiteral("QFont()"); } else if (type == QLatin1String("rect")) { return QStringLiteral("QRect()"); } else if (type == QLatin1String("size")) { return QStringLiteral("QSize()"); } else if (type == QLatin1String("color")) { return QStringLiteral("QColor(128, 128, 128)"); } else if (type == QLatin1String("point")) { return QStringLiteral("QPoint()"); } else if (type == QLatin1String("int")) { return QStringLiteral("0"); } else if (type == QLatin1String("uint")) { return QStringLiteral("0"); } else if (type == QLatin1String("bool")) { return QStringLiteral("false"); } else if (type == QLatin1String("double")) { return QStringLiteral("0.0"); } else if (type == QLatin1String("datetime")) { return QStringLiteral("QDateTime()"); } else if (type == QLatin1String("longlong")) { return QStringLiteral("0"); } else if (type == QLatin1String("ulonglong")) { return QStringLiteral("0"); } else if (type == QLatin1String("intlist")) { return QStringLiteral("QList()"); } else if (type == QLatin1String("enum")) { return QStringLiteral("0"); } else if (type == QLatin1String("path")) { return QStringLiteral("\"\""); // Use empty string, not null string! } else if (type == QLatin1String("pathlist")) { return QStringLiteral("QStringList()"); } else if (type == QLatin1String("password")) { return QStringLiteral("\"\""); // Use empty string, not null string! } else if (type == QLatin1String("url")) { return QStringLiteral("QUrl()"); } else if (type == QLatin1String("urllist")) { return QStringLiteral("QList()"); } else { cerr << "Error, kconfig_compiler_kf5 does not support the \"" << type << "\" type!" << endl; return QStringLiteral("QString"); //For now, but an assert would be better } } QString itemType(const QString &type) { QString t; t = type; t.replace(0, 1, t.left(1).toUpper()); return t; } static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg) { if (cfg.itemAccessors) { return QString(); } QString type; if (!e->signalList().isEmpty()) { type = QStringLiteral("KConfigCompilerSignallingItem"); } else { type = cfg.inherits + "::Item" + itemType(e->type()); } QString fCap = e->name(); fCap[0] = fCap[0].toUpper(); return " " + type + " *item" + fCap + ( (!e->param().isEmpty())?(QStringLiteral("[%1]").arg(e->paramMax()+1)) : QString()) + ";\n"; } // returns the name of an item variable // use itemPath to know the full path // like using d-> in case of dpointer static QString itemVar(const CfgEntry *e, const CfgConfig &cfg) { QString result; if (cfg.itemAccessors) { if (!cfg.dpointer) { result = 'm' + e->name() + "Item"; result[1] = result[1].toUpper(); } else { result = e->name() + "Item"; result[0] = result[0].toLower(); } } else { result = "item" + e->name(); result[4] = result[4].toUpper(); } return result; } static QString itemPath(const CfgEntry *e, const CfgConfig &cfg) { QString result; if (cfg.dpointer) { result = "d->" + itemVar(e, cfg); } else { result = itemVar(e, cfg); } return result; } QString newItem(const CfgEntry* entry, const QString &key, const QString& defaultValue, const CfgConfig &cfg, const QString ¶m = QString()) { QList sigs = entry->signalList(); QString t; if (!sigs.isEmpty()) { t += QLatin1String("new KConfigCompilerSignallingItem("); } t += "new "+ cfg.inherits + "::Item" + itemType(entry->type()) + "( currentGroup(), " + key + ", " + varPath( entry->name(), cfg ) + param; if (entry->type() == QLatin1String("Enum")) { t += ", values" + entry->name(); } if (!defaultValue.isEmpty()) { t += QLatin1String(", ") + defaultValue; } t += QLatin1String(" )"); if (!sigs.isEmpty()) { t += QLatin1String(", this, notifyFunction, "); //append the signal flags for (int i = 0; i < sigs.size(); ++i) { if (i != 0) t += QLatin1String(" | "); t += signalEnumName(sigs[i].name); } t += QLatin1String(")"); } t += QLatin1String(";"); return t; } QString paramString(const QString &s, const CfgEntry *e, int i) { QString result = s; QString needle = "$(" + e->param() + ')'; if (result.contains(needle)) { QString tmp; if (e->paramType() == QLatin1String("Enum")) { tmp = e->paramValues().at(i); } else { tmp = QString::number(i); } result.replace(needle, tmp); } return result; } QString paramString(const QString &group, const QList ¶meters) { QString paramString = group; QString arguments; int i = 1; for (QList::ConstIterator it = parameters.constBegin(); it != parameters.constEnd(); ++it) { if (paramString.contains("$(" + (*it).name + ')')) { QString tmp; tmp.sprintf("%%%d", i++); paramString.replace("$(" + (*it).name + ')', tmp); arguments += ".arg( mParam" + (*it).name + " )"; } } if (arguments.isEmpty()) { return "QStringLiteral( \"" + group + "\" )"; } return "QStringLiteral( \"" + paramString + "\" )" + arguments; } QString translatedString(const CfgConfig &cfg, const QString &string, const QString &context = QString(), const QString ¶m = QString(), const QString ¶mValue = QString()) { QString result; switch (cfg.translationSystem) { case CfgConfig::QtTranslation: if (!context.isEmpty()) { result += "/*: " + context + " */ QCoreApplication::translate(\""; } else { result += QLatin1String("QCoreApplication::translate(\""); } result += cfg.className + "\", "; break; case CfgConfig::KdeTranslation: if (!cfg.translationDomain.isEmpty() && !context.isEmpty()) { result += "i18ndc(" + quoteString(cfg.translationDomain) + ", " + quoteString(context) + ", "; } else if (!cfg.translationDomain.isEmpty()) { result += "i18nd(" + quoteString(cfg.translationDomain) + ", "; } else if (!context.isEmpty()) { result += "i18nc(" + quoteString(context) + ", "; } else { result += QLatin1String("i18n("); } break; } if (!param.isEmpty()) { QString resolvedString = string; resolvedString.replace("$(" + param + ')', paramValue); result += quoteString(resolvedString); } else { result += quoteString(string); } result += ')'; return result; } /* int i is the value of the parameter */ QString userTextsFunctions(CfgEntry *e, const CfgConfig &cfg, QString itemVarStr = QString(), const QString &i = QString()) { QString txt; if (itemVarStr.isNull()) { itemVarStr = itemPath(e, cfg); } if (!e->label().isEmpty()) { txt += " " + itemVarStr + "->setLabel( "; txt += translatedString(cfg, e->label(), e->labelContext(), e->param(), i); txt += QLatin1String(" );\n"); } if (!e->toolTip().isEmpty()) { txt += " " + itemVarStr + "->setToolTip( "; txt += translatedString(cfg, e->toolTip(), e->toolTipContext(), e->param(), i); txt += QLatin1String(" );\n"); } if (!e->whatsThis().isEmpty()) { txt += " " + itemVarStr + "->setWhatsThis( "; txt += translatedString(cfg, e->whatsThis(), e->whatsThisContext(), e->param(), i); txt += QLatin1String(" );\n"); } return txt; } // returns the member accesor implementation // which should go in the h file if inline // or the cpp file if not inline QString memberAccessorBody(CfgEntry *e, bool globalEnums, const CfgConfig &cfg) { QString result; QTextStream out(&result, QIODevice::WriteOnly); QString n = e->name(); QString t = e->type(); bool useEnumType = cfg.useEnumTypes && t == QLatin1String("Enum"); out << "return "; if (useEnumType) { out << "static_cast<" << enumType(e, globalEnums) << ">("; } out << This << varPath(n, cfg); if (!e->param().isEmpty()) { out << "[i]"; } if (useEnumType) { out << ")"; } out << ";" << endl; return result; } // returns the member mutator implementation // which should go in the h file if inline // or the cpp file if not inline void addDebugMethod(QTextStream &out, const CfgConfig &cfg, const QString &n) { if (cfg.qCategoryLoggingName.isEmpty()) { out << " qDebug() << \"" << setFunction(n); } else { out << " qCDebug(" << cfg.qCategoryLoggingName << ") << \"" << setFunction(n); } } QString memberMutatorBody(CfgEntry *e, const CfgConfig &cfg) { QString result; QTextStream out(&result, QIODevice::WriteOnly); QString n = e->name(); QString t = e->type(); if (!e->minValue().isEmpty()) { if (e->minValue() != QLatin1String("0") || !isUnsigned(t)) { // skip writing "if uint<0" (#187579) out << "if (v < " << e->minValue() << ")" << endl; out << "{" << endl; addDebugMethod(out, cfg, n); out << ": value \" << v << \" is less than the minimum value of "; out << e->minValue() << "\";" << endl; out << " v = " << e->minValue() << ";" << endl; out << "}" << endl; } } if (!e->maxValue().isEmpty()) { out << endl << "if (v > " << e->maxValue() << ")" << endl; out << "{" << endl; addDebugMethod(out, cfg, n); out << ": value \" << v << \" is greater than the maximum value of "; out << e->maxValue() << "\";" << endl; out << " v = " << e->maxValue() << ";" << endl; out << "}" << endl << endl; } const QString varExpression = This + varPath(n, cfg) + (e->param().isEmpty() ? QString() : QStringLiteral("[i]")); const bool hasBody = !e->signalList().empty() || cfg.generateProperties; out << "if ("; if (hasBody) { out << "v != " << varExpression << " && "; } out << "!" << This << "isImmutable( QStringLiteral( \""; if (!e->param().isEmpty()) { out << e->paramName().replace("$(" + e->param() + ")", QLatin1String("%1")) << "\" ).arg( "; if (e->paramType() == QLatin1String("Enum")) { out << "QLatin1String( "; if (cfg.globalEnums) { out << enumName(e->param()) << "ToString[i]"; } else { out << enumName(e->param()) << "::enumToString[i]"; } out << " )"; } else { out << "i"; } out << " )"; } else { out << n << "\" )"; } out << " ))" << (hasBody ? " {" : "") << endl; out << " " << varExpression << " = v;" << endl; const auto listSignal = e->signalList(); for (const Signal &signal : listSignal) { if (signal.modify) { out << " Q_EMIT " << This << signal.name << "();" << endl; } else { out << " " << This << varPath(QStringLiteral("settingsChanged"), cfg) << " |= " << signalEnumName(signal.name) << ";" << endl; } } if (hasBody) { out << "}" << endl; } return result; } // returns the member get default implementation // which should go in the h file if inline // or the cpp file if not inline QString memberGetDefaultBody(CfgEntry *e) { QString result = e->code(); QTextStream out(&result, QIODevice::WriteOnly); out << endl; if (!e->param().isEmpty()) { out << " switch (i) {" << endl; for (int i = 0; i <= e->paramMax(); ++i) { if (!e->paramDefaultValue(i).isEmpty()) { out << " case " << i << ": return " << e->paramDefaultValue(i) << ';' << endl; } } out << " default:" << endl; out << " return " << e->defaultValue().replace("$(" + e->param() + ')', QLatin1String("i")) << ';' << endl; out << " }" << endl; } else { out << " return " << e->defaultValue() << ';'; } return result; } // returns the item accesor implementation // which should go in the h file if inline // or the cpp file if not inline QString itemAccessorBody(CfgEntry *e, const CfgConfig &cfg) { QString result; QTextStream out(&result, QIODevice::WriteOnly); out << "return " << itemPath(e, cfg); if (!e->param().isEmpty()) { out << "[i]"; } out << ";" << endl; return result; } //indents text adding X spaces per line QString indent(QString text, int spaces) { QString result; QTextStream out(&result, QIODevice::WriteOnly); QTextStream in(&text, QIODevice::ReadOnly); QString currLine; while (!in.atEnd()) { currLine = in.readLine(); if (!currLine.isEmpty()) for (int i = 0; i < spaces; i++) { out << " "; } out << currLine << endl; } return result; } // adds as many 'namespace foo {' lines to p_out as // there are namespaces in p_ns void beginNamespaces(const QString &p_ns, QTextStream &p_out) { if (!p_ns.isEmpty()) { const QStringList nameSpaces = p_ns.split(QStringLiteral("::")); for (const QString &ns : nameSpaces) { p_out << "namespace " << ns << " {" << endl; } p_out << endl; } } // adds as many '}' lines to p_out as // there are namespaces in p_ns void endNamespaces(const QString &p_ns, QTextStream &p_out) { if (!p_ns.isEmpty()) { const int namespaceCount = p_ns.count(QStringLiteral("::")) + 1; for (int i = 0; i < namespaceCount; ++i) { p_out << "}" << endl; } p_out << endl; } } int main(int argc, char **argv) { QCoreApplication app(argc, argv); app.setApplicationName(QStringLiteral("kconfig_compiler")); app.setApplicationVersion(QStringLiteral(KCONFIG_VERSION_STRING)); validNameRegexp = new QRegExp(QStringLiteral("[a-zA-Z_][a-zA-Z0-9_]*")); QString inputFilename, codegenFilename; QCommandLineParser parser; parser.addPositionalArgument(QStringLiteral("file.kcfg"), QStringLiteral("Input kcfg XML file")); parser.addPositionalArgument(QStringLiteral("file.kcfgc"), QStringLiteral("Code generation options file")); QCommandLineOption targetDirectoryOption(QStringList() << QStringLiteral("d") << QStringLiteral("directory"), QCoreApplication::translate("main", "Directory to generate files in [.]"), QCoreApplication::translate("main", "directory"), QStringLiteral(".")); parser.addOption(targetDirectoryOption); QCommandLineOption licenseOption (QStringList() << QStringLiteral("l") << QStringLiteral("license"), QCoreApplication::translate("main", "Display software license.")); parser.addOption (licenseOption); parser.addVersionOption(); parser.addHelpOption(); parser.process(app); if (parser.isSet(licenseOption)) { cout << "Copyright 2003 Cornelius Schumacher, Waldo Bastian, Zack Rusin," << endl; cout << " Reinhold Kainhofer, Duncan Mac-Vicar P., Harald Fernengel" << endl; cout << "This program comes with ABSOLUTELY NO WARRANTY." << endl; cout << "You may redistribute copies of this program" << endl; cout << "under the terms of the GNU Library Public License." << endl; cout << "For more information about these matters, see the file named COPYING." << endl; return 0; } const QStringList args = parser.positionalArguments(); if (args.count() < 2) { cerr << "Too few arguments." << endl; return 1; } if (args.count() > 2) { cerr << "Too many arguments." << endl; return 1; } inputFilename = args.at(0); codegenFilename = args.at(1); QString baseDir = parser.value(targetDirectoryOption); #ifdef Q_OS_WIN if (!baseDir.endsWith('/') && !baseDir.endsWith('\\')) #else if (!baseDir.endsWith('/')) #endif baseDir.append("/"); if (!codegenFilename.endsWith(QLatin1String(".kcfgc"))) { cerr << "Codegen options file must have extension .kcfgc" << endl; return 1; } QString baseName = QFileInfo(codegenFilename).fileName(); baseName = baseName.left(baseName.length() - 6); CfgConfig cfg = CfgConfig(codegenFilename); QFile input(inputFilename); QDomDocument doc; QString errorMsg; int errorRow; int errorCol; if (!doc.setContent(&input, &errorMsg, &errorRow, &errorCol)) { cerr << "Unable to load document." << endl; cerr << "Parse error in " << inputFilename << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl; return 1; } QDomElement cfgElement = doc.documentElement(); if (cfgElement.isNull()) { cerr << "No document in kcfg file" << endl; return 1; } QString cfgFileName; bool cfgFileNameArg = false; QList parameters; QList signalList; QStringList includes; QList entries; for (QDomElement e = cfgElement.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) { QString tag = e.tagName(); if (tag == QLatin1String("include")) { QString includeFile = e.text(); if (!includeFile.isEmpty()) { includes.append(includeFile); } } else if (tag == QLatin1String("kcfgfile")) { cfgFileName = e.attribute(QStringLiteral("name")); cfgFileNameArg = e.attribute(QStringLiteral("arg")).toLower() == QLatin1String("true"); for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) { if (e2.tagName() == QLatin1String("parameter")) { Param p; p.name = e2.attribute(QStringLiteral("name")); p.type = e2.attribute(QStringLiteral("type")); if (p.type.isEmpty()) { p.type = QStringLiteral("String"); } parameters.append(p); } } } else if (tag == QLatin1String("group")) { QString group = e.attribute(QStringLiteral("name")); if (group.isEmpty()) { cerr << "Group without name" << endl; return 1; } for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) { if (e2.tagName() != QLatin1String("entry")) { continue; } CfgEntry *entry = parseEntry(group, e2, cfg); if (entry) { entries.append(entry); } else { cerr << "Can not parse entry." << endl; return 1; } } } else if (tag == QLatin1String("signal")) { QString signalName = e.attribute(QStringLiteral("name")); if (signalName.isEmpty()) { cerr << "Signal without name." << endl; return 1; } Signal theSignal; theSignal.name = signalName; for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) { if (e2.tagName() == QLatin1String("argument")) { SignalArguments argument; argument.type = e2.attribute(QStringLiteral("type")); if (argument.type.isEmpty()) { cerr << "Signal argument without type." << endl; return 1; } argument.variableName = e2.text(); theSignal.arguments.append(argument); } else if (e2.tagName() == QLatin1String("label")) { theSignal.label = e2.text(); } } signalList.append(theSignal); } } if (cfg.className.isEmpty()) { cerr << "Class name missing" << endl; return 1; } if (cfg.singleton && !parameters.isEmpty()) { cerr << "Singleton class can not have parameters" << endl; return 1; } if (!cfgFileName.isEmpty() && cfgFileNameArg) { cerr << "Having both a fixed filename and a filename as argument is not possible." << endl; return 1; } if (entries.isEmpty()) { cerr << "No entries." << endl; } #if 0 CfgEntry *cfg; for (cfg = entries.first(); cfg; cfg = entries.next()) { cfg->dump(); } #endif QString headerFileName = baseName + '.' + cfg.headerExtension; QString implementationFileName = baseName + '.' + cfg.sourceExtension; QString mocFileName = baseName + ".moc"; QString cppPreamble; // code to be inserted at the beginnin of the cpp file, e.g. initialization of static values QFile header(baseDir + headerFileName); if (!header.open(QIODevice::WriteOnly)) { cerr << "Can not open '" << baseDir << headerFileName << "for writing." << endl; return 1; } QTextStream h(&header); h.setCodec("utf-8"); h << "// This file is generated by kconfig_compiler_kf5 from " << QFileInfo(inputFilename).fileName() << "." << endl; h << "// All changes you do to this file will be lost." << endl; h << "#ifndef " << (!cfg.nameSpace.isEmpty() ? QString(QString(cfg.nameSpace).replace(QLatin1String("::"), QLatin1String("_")).toUpper() + '_') : QLatin1String("")) << cfg.className.toUpper() << "_H" << endl; h << "#define " << (!cfg.nameSpace.isEmpty() ? QString(QString(cfg.nameSpace).replace(QLatin1String("::"), QLatin1String("_")).toUpper() + '_') : QLatin1String("")) << cfg.className.toUpper() << "_H" << endl << endl; // Includes QStringList::ConstIterator it; for (it = cfg.headerIncludes.constBegin(); it != cfg.headerIncludes.constEnd(); ++it) { if ((*it).startsWith('"')) { h << "#include " << *it << endl; } else { h << "#include <" << *it << ">" << endl; } } if (!cfg.headerIncludes.isEmpty()) { h << endl; } if (!cfg.singleton && parameters.isEmpty()) { h << "#include " << endl; } if (cfg.inherits == QLatin1String("KCoreConfigSkeleton")) { h << "#include " << endl; } else { h << "#include " << endl; } h << "#include " << endl; h << "#include " << endl << endl; // Includes for (it = includes.constBegin(); it != includes.constEnd(); ++it) { if ((*it).startsWith('"')) { h << "#include " << *it << endl; } else { h << "#include <" << *it << ">" << endl; } } beginNamespaces(cfg.nameSpace, h); // Private class declaration if (cfg.dpointer) { h << "class " << cfg.className << "Private;" << endl << endl; } // Class declaration header h << "class " << cfg.visibility << cfg.className << " : public " << cfg.inherits << endl; h << "{" << endl; // Add Q_OBJECT macro if the config need signals. if (!signalList.isEmpty() || cfg.generateProperties) { h << " Q_OBJECT" << endl; } h << " public:" << endl; // enums QList::ConstIterator itEntry; for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { const CfgEntry::Choices &choices = (*itEntry)->choices(); const QList chlist = choices.choices; if (!chlist.isEmpty()) { QStringList values; QList::ConstIterator itChoice; for (itChoice = chlist.constBegin(); itChoice != chlist.constEnd(); ++itChoice) { values.append(choices.prefix + (*itChoice).name); } if (choices.name().isEmpty()) { if (cfg.globalEnums) { h << " enum " << enumName((*itEntry)->name(), (*itEntry)->choices()) << " { " << values.join(QStringLiteral(", ")) << " };" << endl; } else { // Create an automatically named enum h << " class " << enumName((*itEntry)->name(), (*itEntry)->choices()) << endl; h << " {" << endl; h << " public:" << endl; h << " enum type { " << values.join(QStringLiteral(", ")) << ", COUNT };" << endl; h << " };" << endl; } } else if (!choices.external()) { // Create a named enum h << " enum " << enumName((*itEntry)->name(), (*itEntry)->choices()) << " { " << values.join(QStringLiteral(", ")) << " };" << endl; } } const QStringList values = (*itEntry)->paramValues(); if (!values.isEmpty()) { if (cfg.globalEnums) { // ### FIXME!! // make the following string table an index-based string search! // ### h << " enum " << enumName((*itEntry)->param()) << " { " << values.join(QStringLiteral(", ")) << " };" << endl; h << " static const char* const " << enumName((*itEntry)->param()) << "ToString[];" << endl; cppPreamble += "const char* const " + cfg.className + "::" + enumName((*itEntry)->param()) + "ToString[] = { \"" + values.join(QStringLiteral("\", \"")) + "\" };\n"; } else { h << " class " << enumName((*itEntry)->param()) << endl; h << " {" << endl; h << " public:" << endl; h << " enum type { " << values.join(QStringLiteral(", ")) << ", COUNT };" << endl; h << " static const char* const enumToString[];" << endl; h << " };" << endl; cppPreamble += "const char* const " + cfg.className + "::" + enumName((*itEntry)->param()) + "::enumToString[] = { \"" + values.join(QStringLiteral("\", \"")) + "\" };\n"; } } } h << endl; // Constructor or singleton accessor if (!cfg.singleton) { h << " " << cfg.className << "("; if (cfgFileNameArg) { if (cfg.forceStringFilename) h << " const QString &cfgfilename" << (parameters.isEmpty() ? " = QString()" : ", "); else h << " KSharedConfig::Ptr config" << (parameters.isEmpty() ? " = KSharedConfig::openConfig()" : ", "); } for (QList::ConstIterator it = parameters.constBegin(); it != parameters.constEnd(); ++it) { if (it != parameters.constBegin()) { h << ","; } h << " " << param((*it).type) << " " << (*it).name; } h << " );" << endl; } else { h << " static " << cfg.className << " *self();" << endl; if (cfgFileNameArg) { h << " static void instance(const QString& cfgfilename);" << endl; h << " static void instance(KSharedConfig::Ptr config);" << endl; } } // Destructor h << " ~" << cfg.className << "();" << endl << endl; // global variables if (cfg.staticAccessors) { This = QStringLiteral("self()->"); } else { Const = QStringLiteral(" const"); } for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { QString n = (*itEntry)->name(); QString t = (*itEntry)->type(); // Manipulator if (cfg.allMutators || cfg.mutators.contains(n)) { h << " /**" << endl; h << " Set " << (*itEntry)->label() << endl; h << " */" << endl; if (cfg.staticAccessors) { h << " static" << endl; } h << " void " << setFunction(n) << "( "; if (!(*itEntry)->param().isEmpty()) { h << cppType((*itEntry)->paramType()) << " i, "; } if (cfg.useEnumTypes && t == QLatin1String("Enum")) { h << enumType(*itEntry, cfg.globalEnums); } else { h << param(t); } h << " v )"; // function body inline only if not using dpointer // for BC mode if (!cfg.dpointer) { h << endl << " {" << endl; h << indent(memberMutatorBody(*itEntry, cfg), 6); h << " }" << endl; } else { h << ";" << endl; } } h << endl; QString returnType; if (cfg.useEnumTypes && t == QLatin1String("Enum")) { returnType = enumType(*itEntry, cfg.globalEnums); } else { returnType = cppType(t); } if (cfg.generateProperties) { h << " Q_PROPERTY(" << returnType << ' ' << n; h << " READ " << n; if (cfg.allMutators || cfg.mutators.contains(n)) { const QString signal = changeSignalName(n); h << " WRITE " << setFunction(n); h << " NOTIFY " << signal; //If we have the modified signal, we'll also need //the changed signal as well Signal s; s.name = signal; s.modify = true; signalList.append(s); } else { h << " CONSTANT"; } h << ")" << endl; } // Accessor h << " /**" << endl; h << " Get " << (*itEntry)->label() << endl; h << " */" << endl; if (cfg.staticAccessors) { h << " static" << endl; } h << " "; h << returnType; h << " " << getFunction(n) << "("; if (!(*itEntry)->param().isEmpty()) { h << " " << cppType((*itEntry)->paramType()) << " i "; } h << ")" << Const; // function body inline only if not using dpointer // for BC mode if (!cfg.dpointer) { h << endl << " {" << endl; h << indent(memberAccessorBody(*itEntry, cfg.globalEnums, cfg), 6); h << " }" << endl; } else { h << ";" << endl; } // Default value Accessor if ((cfg.allDefaultGetters || cfg.defaultGetters.contains(n)) && !(*itEntry)->defaultValue().isEmpty()) { h << endl; h << " /**" << endl; h << " Get " << (*itEntry)->label() << " default value" << endl; h << " */" << endl; if (cfg.staticAccessors) { h << " static" << endl; } h << " "; if (cfg.useEnumTypes && t == QLatin1String("Enum")) { h << enumType(*itEntry, cfg.globalEnums); } else { h << cppType(t); } h << " " << getDefaultFunction(n) << "("; if (!(*itEntry)->param().isEmpty()) { h << " " << cppType((*itEntry)->paramType()) << " i "; } h << ")" << Const << endl; h << " {" << endl; h << " return "; if (cfg.useEnumTypes && t == QLatin1String("Enum")) { h << "static_cast<" << enumType(*itEntry, cfg.globalEnums) << ">("; } h << getDefaultFunction(n) << "_helper("; if (!(*itEntry)->param().isEmpty()) { h << " i "; } h << ")"; if (cfg.useEnumTypes && t == QLatin1String("Enum")) { h << ")"; } h << ";" << endl; h << " }" << endl; } // Item accessor if (cfg.itemAccessors) { h << endl; h << " /**" << endl; h << " Get Item object corresponding to " << n << "()" << endl; h << " */" << endl; h << " Item" << itemType((*itEntry)->type()) << " *" << getFunction(n) << "Item("; if (!(*itEntry)->param().isEmpty()) { h << " " << cppType((*itEntry)->paramType()) << " i "; } h << ")"; if (!cfg.dpointer) { h << endl << " {" << endl; h << indent(itemAccessorBody((*itEntry), cfg), 6); h << " }" << endl; } else { h << ";" << endl; } } h << endl; } // Signal definition. const bool hasSignals = !signalList.isEmpty(); bool hasNonModifySignals = false; if (hasSignals) { h << "\n enum {" << endl; unsigned val = 1; QList::ConstIterator it, itEnd = signalList.constEnd(); for (it = signalList.constBegin(); it != itEnd; val <<= 1) { hasNonModifySignals |= !it->modify; if (!val) { cerr << "Too many signals to create unique bit masks" << endl; exit(1); } Signal signal = *it; h << " " << signalEnumName(signal.name) << " = 0x" << hex << val; if (++it != itEnd) { h << ","; } h << endl; } h << " };" << dec << endl << endl; h << " Q_SIGNALS:"; for (const Signal &signal : qAsConst(signalList)) { h << endl; if (!signal.label.isEmpty()) { h << " /**" << endl; h << " " << signal.label << endl; h << " */" << endl; } h << " void " << signal.name << "("; QList::ConstIterator it, itEnd = signal.arguments.constEnd(); for (it = signal.arguments.constBegin(); it != itEnd;) { SignalArguments argument = *it; QString type = param(argument.type); if (cfg.useEnumTypes && argument.type == QLatin1String("Enum")) { for (int i = 0, end = entries.count(); i < end; ++i) { if (entries[i]->name() == argument.variableName) { type = enumType(entries[i], cfg.globalEnums); break; } } } h << type << " " << argument.variableName; if (++it != itEnd) { h << ", "; } } h << ");" << endl; } h << endl; h << " private:" << endl; h << " void itemChanged(quint64 flags);" << endl; h << endl; } h << " protected:" << endl; // Private constructor for singleton if (cfg.singleton) { h << " " << cfg.className << "("; if (cfgFileNameArg) { h << "KSharedConfig::Ptr config"; } h << ");" << endl; h << " friend class " << cfg.className << "Helper;" << endl << endl; } if (hasNonModifySignals) { h << " bool usrSave() override;" << endl; } // Member variables if (!cfg.memberVariables.isEmpty() && cfg.memberVariables != QLatin1String("private") && cfg.memberVariables != QLatin1String("dpointer")) { h << " " << cfg.memberVariables << ":" << endl; } // Class Parameters for (QList::ConstIterator it = parameters.constBegin(); it != parameters.constEnd(); ++it) { h << " " << cppType((*it).type) << " mParam" << (*it).name << ";" << endl; } if (cfg.memberVariables != QLatin1String("dpointer")) { QString group; for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { if ((*itEntry)->group() != group) { group = (*itEntry)->group(); h << endl; h << " // " << group << endl; } h << " " << cppType((*itEntry)->type()) << " " << varName((*itEntry)->name(), cfg); if (!(*itEntry)->param().isEmpty()) { h << QStringLiteral("[%1]").arg((*itEntry)->paramMax() + 1); } h << ";" << endl; if (cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name())) { h << " "; if (cfg.staticAccessors) { h << "static "; } h << cppType((*itEntry)->type()) << " " << getDefaultFunction((*itEntry)->name()) << "_helper("; if (!(*itEntry)->param().isEmpty()) { h << " " << cppType((*itEntry)->paramType()) << " i "; } h << ")" << Const << ";" << endl; } } h << endl << " private:" << endl; if (cfg.itemAccessors) { for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { h << " Item" << itemType((*itEntry)->type()) << " *" << itemVar(*itEntry, cfg); if (!(*itEntry)->param().isEmpty()) { h << QStringLiteral("[%1]").arg((*itEntry)->paramMax() + 1); } h << ";" << endl; } } if (hasNonModifySignals) { h << " uint " << varName(QStringLiteral("settingsChanged"), cfg) << ";" << endl; } } else { // use a private class for both member variables and items h << " private:" << endl; for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { if (cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name())) { h << " "; if (cfg.staticAccessors) { h << "static "; } h << cppType((*itEntry)->type()) << " " << getDefaultFunction((*itEntry)->name()) << "_helper("; if (!(*itEntry)->param().isEmpty()) { h << " " << cppType((*itEntry)->paramType()) << " i "; } h << ")" << Const << ";" << endl; } } h << " " + cfg.className + "Private *d;" << endl; } if (cfg.customAddons) { h << " // Include custom additions" << endl; h << " #include \"" << filenameOnly(baseName) << "_addons." << cfg.headerExtension << '"' << endl; } h << "};" << endl << endl; endNamespaces(cfg.nameSpace, h); h << "#endif" << endl << endl; header.close(); QFile implementation(baseDir + implementationFileName); if (!implementation.open(QIODevice::WriteOnly)) { cerr << "Can not open '" << implementationFileName << "for writing." << endl; return 1; } QTextStream cpp(&implementation); cpp.setCodec("utf-8"); cpp << "// This file is generated by kconfig_compiler_kf5 from " << QFileInfo(inputFilename).fileName() << "." << endl; cpp << "// All changes you do to this file will be lost." << endl << endl; cpp << "#include \"" << headerFileName << "\"" << endl << endl; for (it = cfg.sourceIncludes.constBegin(); it != cfg.sourceIncludes.constEnd(); ++it) { if ((*it).startsWith('"')) { cpp << "#include " << *it << endl; } else { cpp << "#include <" << *it << ">" << endl; } } if (!cfg.sourceIncludes.isEmpty()) { cpp << endl; } if (cfg.setUserTexts && cfg.translationSystem == CfgConfig::KdeTranslation) { cpp << "#include " << endl << endl; } // Header required by singleton implementation if (cfg.singleton) { cpp << "#include " << endl << "#include " << endl << endl; } if (cfg.singleton && cfgFileNameArg) { cpp << "#include " << endl << endl; } if (!cfg.nameSpace.isEmpty()) { cpp << "using namespace " << cfg.nameSpace << ";" << endl << endl; } QString group; // private class implementation if (cfg.dpointer) { beginNamespaces(cfg.nameSpace, cpp); cpp << "class " << cfg.className << "Private" << endl; cpp << "{" << endl; cpp << " public:" << endl; for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { if ((*itEntry)->group() != group) { group = (*itEntry)->group(); cpp << endl; cpp << " // " << group << endl; } cpp << " " << cppType((*itEntry)->type()) << " " << varName((*itEntry)->name(), cfg); if (!(*itEntry)->param().isEmpty()) { cpp << QStringLiteral("[%1]").arg((*itEntry)->paramMax() + 1); } cpp << ";" << endl; } cpp << endl << " // items" << endl; for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { const QString declType = (*itEntry)->signalList().isEmpty() ? QString(cfg.inherits + "::Item" + itemType((*itEntry)->type())) : QStringLiteral("KConfigCompilerSignallingItem"); cpp << " " << declType << " *" << itemVar( *itEntry, cfg ); if (!(*itEntry)->param().isEmpty()) { cpp << QStringLiteral("[%1]").arg((*itEntry)->paramMax() + 1); } cpp << ";" << endl; } if (hasNonModifySignals) { cpp << " uint " << varName(QStringLiteral("settingsChanged"), cfg) << ";" << endl; } cpp << "};" << endl << endl; endNamespaces(cfg.nameSpace, cpp); } // Singleton implementation if (cfg.singleton) { beginNamespaces(cfg.nameSpace, cpp); cpp << "class " << cfg.className << "Helper" << endl; cpp << '{' << endl; cpp << " public:" << endl; cpp << " " << cfg.className << "Helper() : q(nullptr) {}" << endl; cpp << " ~" << cfg.className << "Helper() { delete q; }" << endl; cpp << " " << cfg.className << "Helper(const " << cfg.className << "Helper&) = delete;" << endl; cpp << " " << cfg.className << "Helper& operator=(const " << cfg.className << "Helper&) = delete;" << endl; cpp << " " << cfg.className << " *q;" << endl; cpp << "};" << endl; endNamespaces(cfg.nameSpace, cpp); cpp << "Q_GLOBAL_STATIC(" << cfg.className << "Helper, s_global" << cfg.className << ")" << endl; cpp << cfg.className << " *" << cfg.className << "::self()" << endl; cpp << "{" << endl; if (cfgFileNameArg) { cpp << " if (!s_global" << cfg.className << "()->q)" << endl; cpp << " qFatal(\"you need to call " << cfg.className << "::instance before using\");" << endl; } else { cpp << " if (!s_global" << cfg.className << "()->q) {" << endl; cpp << " new " << cfg.className << ';' << endl; cpp << " s_global" << cfg.className << "()->q->read();" << endl; cpp << " }" << endl << endl; } cpp << " return s_global" << cfg.className << "()->q;" << endl; cpp << "}" << endl << endl; if (cfgFileNameArg) { auto instance = [&cfg, &cpp] (const QString &type, const QString arg, bool wrap) { cpp << "void " << cfg.className << "::instance(" << type << " " << arg << ")" << endl; cpp << "{" << endl; cpp << " if (s_global" << cfg.className << "()->q) {" << endl; cpp << " qDebug() << \"" << cfg.className << "::instance called after the first use - ignoring\";" << endl; cpp << " return;" << endl; cpp << " }" << endl; cpp << " new " << cfg.className << "("; if (wrap) { cpp << "KSharedConfig::openConfig(" << arg << ")"; } else { cpp << arg; } cpp << ");" << endl; cpp << " s_global" << cfg.className << "()->q->read();" << endl; cpp << "}" << endl << endl; }; instance(QStringLiteral("const QString&"), QStringLiteral("cfgfilename"), true); instance(QStringLiteral("KSharedConfig::Ptr"), QStringLiteral("config"), false); } } if (!cppPreamble.isEmpty()) { cpp << cppPreamble << endl; } // Constructor cpp << cfg.className << "::" << cfg.className << "( "; if (cfgFileNameArg) { if (! cfg.forceStringFilename) { cpp << " KSharedConfig::Ptr config"; } else { cpp << " const QString& config"; } cpp << (parameters.isEmpty() ? " " : ", "); } for (QList::ConstIterator it = parameters.constBegin(); it != parameters.constEnd(); ++it) { if (it != parameters.constBegin()) { cpp << ","; } cpp << " " << param((*it).type) << " " << (*it).name; } cpp << " )" << endl; cpp << " : " << cfg.inherits << "("; if (!cfgFileName.isEmpty()) { cpp << " QStringLiteral( \"" << cfgFileName << "\" "; } if (cfgFileNameArg) { cpp << " config "; } if (!cfgFileName.isEmpty()) { cpp << ") "; } cpp << ")" << endl; // Store parameters for (QList::ConstIterator it = parameters.constBegin(); it != parameters.constEnd(); ++it) { cpp << " , mParam" << (*it).name << "(" << (*it).name << ")" << endl; } if (hasNonModifySignals && !cfg.dpointer) { cpp << " , " << varName(QStringLiteral("settingsChanged"), cfg) << "(0)" << endl; } cpp << "{" << endl; if (cfg.dpointer) { cpp << " d = new " + cfg.className + "Private;" << endl; if (hasNonModifySignals) { cpp << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " = 0;" << endl; } } // Needed in case the singleton class is used as baseclass for // another singleton. if (cfg.singleton) { cpp << " Q_ASSERT(!s_global" << cfg.className << "()->q);" << endl; cpp << " s_global" << cfg.className << "()->q = this;" << endl; } group.clear(); if (hasSignals) { // this cast to base-class pointer-to-member is valid C++ // http://stackoverflow.com/questions/4272909/is-it-safe-to-upcast-a-method-pointer-and-use-it-with-base-class-pointer/ cpp << " KConfigCompilerSignallingItem::NotifyFunction notifyFunction =" << " static_cast(&" << cfg.className << "::itemChanged);" << endl << endl; } for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { if ((*itEntry)->group() != group) { if (!group.isEmpty()) { cpp << endl; } group = (*itEntry)->group(); cpp << " setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl; } QString key = paramString((*itEntry)->key(), parameters); if (!(*itEntry)->code().isEmpty()) { cpp << (*itEntry)->code() << endl; } if ((*itEntry)->type() == QLatin1String("Enum")) { cpp << " QList<" + cfg.inherits + "::ItemEnum::Choice> values" << (*itEntry)->name() << ";" << endl; const QList choices = (*itEntry)->choices().choices; QList::ConstIterator it; for (it = choices.constBegin(); it != choices.constEnd(); ++it) { cpp << " {" << endl; cpp << " " + cfg.inherits + "::ItemEnum::Choice choice;" << endl; cpp << " choice.name = QStringLiteral(\"" << (*it).name << "\");" << endl; if (cfg.setUserTexts) { if (!(*it).label.isEmpty()) { cpp << " choice.label = " << translatedString(cfg, (*it).label, (*it).context) << ";" << endl; } if (!(*it).toolTip.isEmpty()) { cpp << " choice.toolTip = " << translatedString(cfg, (*it).toolTip, (*it).context) << ";" << endl; } if (!(*it).whatsThis.isEmpty()) { cpp << " choice.whatsThis = " << translatedString(cfg, (*it).whatsThis, (*it).context) << ";" << endl; } } cpp << " values" << (*itEntry)->name() << ".append( choice );" << endl; cpp << " }" << endl; } } if (!cfg.dpointer) { cpp << itemDeclaration(*itEntry, cfg); } if ((*itEntry)->param().isEmpty()) { // Normal case cpp << " " << itemPath(*itEntry, cfg) << " = " << newItem((*itEntry), key, (*itEntry)->defaultValue(), cfg) << endl; if (!(*itEntry)->minValue().isEmpty()) { cpp << " " << itemPath(*itEntry, cfg) << "->setMinValue(" << (*itEntry)->minValue() << ");" << endl; } if (!(*itEntry)->maxValue().isEmpty()) { cpp << " " << itemPath(*itEntry, cfg) << "->setMaxValue(" << (*itEntry)->maxValue() << ");" << endl; } if (cfg.setUserTexts) { cpp << userTextsFunctions((*itEntry), cfg); } + if (cfg.allNotifiers || cfg.notifiers.contains((*itEntry)->name())) { + cpp << " " << itemPath(*itEntry, cfg) << "->setWriteFlags(KConfigBase::Notify);" << endl; + } + cpp << " addItem( " << itemPath(*itEntry, cfg); QString quotedName = (*itEntry)->name(); addQuotes(quotedName); if (quotedName != key) { cpp << ", QStringLiteral( \"" << (*itEntry)->name() << "\" )"; } cpp << " );" << endl; } else { // Indexed for (int i = 0; i <= (*itEntry)->paramMax(); i++) { QString defaultStr; QString itemVarStr(itemPath(*itEntry, cfg) + QStringLiteral("[%1]").arg(i)); if (!(*itEntry)->paramDefaultValue(i).isEmpty()) { defaultStr = (*itEntry)->paramDefaultValue(i); } else if (!(*itEntry)->defaultValue().isEmpty()) { defaultStr = paramString((*itEntry)->defaultValue(), (*itEntry), i); } else { defaultStr = defaultValue((*itEntry)->type()); } cpp << " " << itemVarStr << " = " << newItem((*itEntry), paramString(key, *itEntry, i), defaultStr, cfg, QStringLiteral("[%1]").arg(i)) << endl; if (cfg.setUserTexts) { cpp << userTextsFunctions(*itEntry, cfg, itemVarStr, (*itEntry)->paramName()); } // Make mutators for enum parameters work by adding them with $(..) replaced by the // param name. The check for isImmutable in the set* functions doesn't have the param // name available, just the corresponding enum value (int), so we need to store the // param names in a separate static list!. cpp << " addItem( " << itemVarStr << ", QStringLiteral( \""; if ((*itEntry)->paramType() == QLatin1String("Enum")) { cpp << (*itEntry)->paramName().replace("$(" + (*itEntry)->param() + ')', QLatin1String("%1")).arg((*itEntry)->paramValues()[i]); } else { cpp << (*itEntry)->paramName().replace("$(" + (*itEntry)->param() + ')', QLatin1String("%1")).arg(i); } cpp << "\" ) );" << endl; } } } cpp << "}" << endl << endl; if (cfg.dpointer) { // setters and getters go in Cpp if in dpointer mode for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { QString n = (*itEntry)->name(); QString t = (*itEntry)->type(); // Manipulator if (cfg.allMutators || cfg.mutators.contains(n)) { cpp << "void " << setFunction(n, cfg.className) << "( "; if (!(*itEntry)->param().isEmpty()) { cpp << cppType((*itEntry)->paramType()) << " i, "; } if (cfg.useEnumTypes && t == QLatin1String("Enum")) { cpp << enumType(*itEntry, cfg.globalEnums); } else { cpp << param(t); } cpp << " v )" << endl; // function body inline only if not using dpointer // for BC mode cpp << "{" << endl; cpp << indent(memberMutatorBody(*itEntry, cfg), 6); cpp << "}" << endl << endl; } // Accessor if (cfg.useEnumTypes && t == QLatin1String("Enum")) { cpp << enumType(*itEntry, cfg.globalEnums); } else { cpp << cppType(t); } cpp << " " << getFunction(n, cfg.className) << "("; if (!(*itEntry)->param().isEmpty()) { cpp << " " << cppType((*itEntry)->paramType()) << " i "; } cpp << ")" << Const << endl; // function body inline only if not using dpointer // for BC mode cpp << "{" << endl; cpp << indent(memberAccessorBody(*itEntry, cfg.globalEnums, cfg), 2); cpp << "}" << endl << endl; // Default value Accessor -- written by the loop below // Item accessor if (cfg.itemAccessors) { cpp << endl; cpp << cfg.inherits + "::Item" << itemType((*itEntry)->type()) << " *" << getFunction(n, cfg.className) << "Item("; if (!(*itEntry)->param().isEmpty()) { cpp << " " << cppType((*itEntry)->paramType()) << " i "; } cpp << ")" << endl; cpp << "{" << endl; cpp << indent(itemAccessorBody(*itEntry, cfg), 2); cpp << "}" << endl; } cpp << endl; } } // default value getters always go in Cpp for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { QString n = (*itEntry)->name(); QString t = (*itEntry)->type(); // Default value Accessor, as "helper" function if ((cfg.allDefaultGetters || cfg.defaultGetters.contains(n)) && !(*itEntry)->defaultValue().isEmpty()) { cpp << cppType(t) << " " << getDefaultFunction(n, cfg.className) << "_helper("; if (!(*itEntry)->param().isEmpty()) { cpp << " " << cppType((*itEntry)->paramType()) << " i "; } cpp << ")" << Const << endl; cpp << "{" << endl; cpp << memberGetDefaultBody(*itEntry) << endl; cpp << "}" << endl << endl; } } // Destructor cpp << cfg.className << "::~" << cfg.className << "()" << endl; cpp << "{" << endl; if (cfg.dpointer) { cpp << " delete d;" << endl; } if (cfg.singleton) { cpp << " s_global" << cfg.className << "()->q = nullptr;" << endl; } cpp << "}" << endl << endl; if (hasNonModifySignals) { cpp << "bool " << cfg.className << "::" << "usrSave()" << endl; cpp << "{" << endl; cpp << " const bool res = " << cfg.inherits << "::usrSave();" << endl; cpp << " if (!res) return false;" << endl << endl; for (const Signal &signal : qAsConst(signalList)) { if (signal.modify) { continue; } cpp << " if ( " << varPath(QStringLiteral("settingsChanged"), cfg) << " & " << signalEnumName(signal.name) << " )" << endl; cpp << " Q_EMIT " << signal.name << "("; QList::ConstIterator it, itEnd = signal.arguments.constEnd(); for (it = signal.arguments.constBegin(); it != itEnd;) { SignalArguments argument = *it; bool cast = false; if (cfg.useEnumTypes && argument.type == QLatin1String("Enum")) { for (int i = 0, end = entries.count(); i < end; ++i) { if (entries[i]->name() == argument.variableName) { cpp << "static_cast<" << enumType(entries[i], cfg.globalEnums) << ">("; cast = true; break; } } } cpp << varPath(argument.variableName, cfg); if (cast) { cpp << ")"; } if (++it != itEnd) { cpp << ", "; } } cpp << ");" << endl; } cpp << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " = 0;" << endl; cpp << " return true;" << endl; cpp << "}" << endl; } if (hasSignals) { cpp << endl; cpp << "void " << cfg.className << "::" << "itemChanged(quint64 flags) {" << endl; if (hasNonModifySignals) cpp << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " |= flags;" << endl; if (!signalList.isEmpty()) cpp << endl; for (const Signal &signal : qAsConst(signalList)) { if (signal.modify) { cpp << " if ( flags & " << signalEnumName(signal.name) << " ) {" << endl; cpp << " Q_EMIT " << signal.name << "();" << endl; cpp << " }" << endl; } } cpp << "}" << endl; } if (hasSignals || cfg.generateProperties) { // Add includemoc if they are signals defined. cpp << endl; cpp << "#include \"" << mocFileName << "\"" << endl; cpp << endl; } // clear entries list qDeleteAll(entries); implementation.close(); }