File indexing completed on 2024-05-12 03:54:30
0001 /* 0002 This file is part of the KDE libraries 0003 0004 SPDX-FileCopyrightText: 2003 Cornelius Schumacher <schumacher@kde.org> 0005 SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org> 0006 SPDX-FileCopyrightText: 2003 Zack Rusin <zack@kde.org> 0007 SPDX-FileCopyrightText: 2006 MichaĆ«l Larouche <michael.larouche@kdemail.net> 0008 SPDX-FileCopyrightText: 2008 Allen Winter <winter@kde.org> 0009 SPDX-FileCopyrightText: 2020 Tomaz Cananbrava <tcanabrava@kde.org> 0010 0011 SPDX-License-Identifier: LGPL-2.0-or-later 0012 */ 0013 0014 #include "KConfigSourceGenerator.h" 0015 0016 #include <QRegularExpression> 0017 0018 KConfigSourceGenerator::KConfigSourceGenerator(const QString &inputFile, const QString &baseDir, const KConfigParameters &cfg, ParseResult &parseResult) 0019 : KConfigCodeGeneratorBase(inputFile, baseDir, baseDir + cfg.baseName + QLatin1String(".cpp"), cfg, parseResult) 0020 { 0021 } 0022 0023 void KConfigSourceGenerator::start() 0024 { 0025 KConfigCodeGeneratorBase::start(); 0026 stream() << '\n'; 0027 createHeaders(); 0028 0029 if (!cfg().nameSpace.isEmpty()) { 0030 stream() << "using namespace " << cfg().nameSpace << ";"; 0031 stream() << "\n\n"; 0032 } 0033 0034 createPrivateDPointerImplementation(); 0035 createSingletonImplementation(); 0036 createPreamble(); 0037 doConstructor(); 0038 doGetterSetterDPointerMode(); 0039 createDefaultValueGetterSetter(); 0040 createDestructor(); 0041 createNonModifyingSignalsHelper(); 0042 createSignalFlagsHandler(); 0043 includeMoc(); 0044 } 0045 0046 void KConfigSourceGenerator::createHeaders() 0047 { 0048 QString headerName = cfg().baseName + QLatin1Char('.') + cfg().headerExtension; 0049 0050 // TODO: Make addQuotes return a string instead of replacing it inplace. 0051 addQuotes(headerName); 0052 0053 addHeaders({headerName}); 0054 stream() << '\n'; 0055 0056 addHeaders(cfg().sourceIncludes); 0057 if (cfg().setUserTexts && cfg().translationSystem == KConfigParameters::KdeTranslation) { 0058 addHeaders({QStringLiteral("klocalizedstring.h")}); 0059 stream() << '\n'; 0060 } 0061 0062 // Header required by singleton implementation 0063 if (cfg().singleton) { 0064 addHeaders({QStringLiteral("qglobal.h"), QStringLiteral("QFile")}); 0065 0066 // HACK: Add single line to fix test. 0067 if (cfg().singleton && parseResult.cfgFileNameArg) { 0068 stream() << '\n'; 0069 } 0070 } 0071 0072 if (cfg().singleton && parseResult.cfgFileNameArg) { 0073 addHeaders({QStringLiteral("QDebug")}); 0074 } 0075 0076 if (cfg().dpointer && parseResult.hasNonModifySignals) { 0077 addHeaders({QStringLiteral("QSet")}); 0078 } 0079 0080 if (cfg().singleton) { 0081 stream() << '\n'; 0082 } 0083 } 0084 0085 void KConfigSourceGenerator::createPrivateDPointerImplementation() 0086 { 0087 // private class implementation 0088 if (!cfg().dpointer) { 0089 return; 0090 } 0091 0092 QString group; 0093 beginNamespaces(); 0094 stream() << "class " << cfg().className << "Private\n"; 0095 stream() << "{\n"; 0096 stream() << " public:\n"; 0097 0098 // Create Members 0099 for (const auto *entry : std::as_const(parseResult.entries)) { 0100 if (entry->group != group) { 0101 group = entry->group; 0102 stream() << '\n'; 0103 stream() << " // " << group << '\n'; 0104 } 0105 stream() << " " << cppType(entry->type) << " " << varName(entry->name, cfg()); 0106 if (!entry->param.isEmpty()) { 0107 stream() << QStringLiteral("[%1]").arg(entry->paramMax + 1); 0108 } 0109 stream() << ";\n"; 0110 } 0111 stream() << "\n // items\n"; 0112 0113 // Create Items. 0114 for (const auto *entry : std::as_const(parseResult.entries)) { 0115 const QString declType = entry->signalList.isEmpty() ? QString(cfg().inherits + QStringLiteral("::Item") + itemType(entry->type)) 0116 : QStringLiteral("KConfigCompilerSignallingItem"); 0117 0118 stream() << " " << declType << " *" << itemVar(entry, cfg()); 0119 if (!entry->param.isEmpty()) { 0120 stream() << QStringLiteral("[%1]").arg(entry->paramMax + 1); 0121 } 0122 stream() << ";\n"; 0123 } 0124 0125 if (parseResult.hasNonModifySignals) { 0126 stream() << " QSet<quint64> " << varName(QStringLiteral("settingsChanged"), cfg()) << ";\n"; 0127 } 0128 0129 stream() << "};\n\n"; 0130 endNamespaces(); 0131 } 0132 0133 void KConfigSourceGenerator::createSingletonImplementation() 0134 { 0135 // Singleton implementation 0136 if (!cfg().singleton) { 0137 return; 0138 } 0139 0140 beginNamespaces(); 0141 stream() << "class " << cfg().className << "Helper\n"; 0142 stream() << '{' << '\n'; 0143 stream() << " public:\n"; 0144 stream() << " " << cfg().className << "Helper() : q(nullptr) {}\n"; 0145 stream() << " ~" << cfg().className << "Helper() { delete q; q = nullptr; }\n"; 0146 stream() << " " << cfg().className << "Helper(const " << cfg().className << "Helper&) = delete;\n"; 0147 stream() << " " << cfg().className << "Helper& operator=(const " << cfg().className << "Helper&) = delete;\n"; 0148 stream() << " " << cfg().className << " *q;\n"; 0149 stream() << "};\n"; 0150 endNamespaces(); 0151 0152 stream() << "Q_GLOBAL_STATIC(" << cfg().className << "Helper, s_global" << cfg().className << ")\n"; 0153 0154 stream() << cfg().className << " *" << cfg().className << "::self()\n"; 0155 stream() << "{\n"; 0156 if (parseResult.cfgFileNameArg) { 0157 stream() << " if (!s_global" << cfg().className << "()->q)\n"; 0158 stream() << " qFatal(\"you need to call " << cfg().className << "::instance before using\");\n"; 0159 } else { 0160 stream() << " if (!s_global" << cfg().className << "()->q) {\n"; 0161 stream() << " new " << cfg().className << ';' << '\n'; 0162 stream() << " s_global" << cfg().className << "()->q->read();\n"; 0163 stream() << " }\n\n"; 0164 } 0165 stream() << " return s_global" << cfg().className << "()->q;\n"; 0166 stream() << "}\n\n"; 0167 0168 if (parseResult.cfgFileNameArg) { 0169 auto instance = [this](const QString &type, const QString &arg, bool isString) { 0170 stream() << "void " << cfg().className << "::instance(" << type << " " << arg << ")\n"; 0171 stream() << "{\n"; 0172 stream() << " if (s_global" << cfg().className << "()->q) {\n"; 0173 stream() << " qDebug() << \"" << cfg().className << "::instance called after the first use - ignoring\";\n"; 0174 stream() << " return;\n"; 0175 stream() << " }\n"; 0176 stream() << " new " << cfg().className << "("; 0177 if (parseResult.cfgStateConfig) { 0178 stream() << "KSharedConfig::openStateConfig(" << arg << ")"; 0179 } else if (isString) { 0180 stream() << "KSharedConfig::openConfig(" << arg << ")"; 0181 } else { 0182 stream() << "std::move(" << arg << ")"; 0183 } 0184 stream() << ");\n"; 0185 stream() << " s_global" << cfg().className << "()->q->read();\n"; 0186 stream() << "}\n\n"; 0187 }; 0188 instance(QStringLiteral("const QString&"), QStringLiteral("cfgfilename"), true); 0189 instance(QStringLiteral("KSharedConfig::Ptr"), QStringLiteral("config"), false); 0190 } 0191 } 0192 0193 void KConfigSourceGenerator::createPreamble() 0194 { 0195 QString cppPreamble; 0196 for (const auto *entry : std::as_const(parseResult.entries)) { 0197 if (entry->paramValues.isEmpty()) { 0198 continue; 0199 } 0200 0201 cppPreamble += QStringLiteral("const char* const ") + cfg().className + QStringLiteral("::") + enumName(entry->param); 0202 cppPreamble += cfg().globalEnums 0203 ? QStringLiteral("ToString[] = { \"") + entry->paramValues.join(QStringLiteral("\", \"")) + QStringLiteral("\" };\n") 0204 : QStringLiteral("::enumToString[] = { \"") + entry->paramValues.join(QStringLiteral("\", \"")) + QStringLiteral("\" };\n"); 0205 } 0206 0207 if (!cppPreamble.isEmpty()) { 0208 stream() << cppPreamble << '\n'; 0209 } 0210 } 0211 0212 void KConfigSourceGenerator::createConstructorParameterList() 0213 { 0214 if (parseResult.cfgFileNameArg) { 0215 if (!cfg().forceStringFilename) { 0216 stream() << " KSharedConfig::Ptr config"; 0217 } else { 0218 stream() << " const QString& config"; 0219 } 0220 stream() << (parseResult.parameters.isEmpty() ? "" : ","); 0221 } 0222 0223 for (auto it = parseResult.parameters.cbegin(); it != parseResult.parameters.cend(); ++it) { 0224 if (it != parseResult.parameters.cbegin()) { 0225 stream() << ","; 0226 } 0227 stream() << " " << param((*it).type) << " " << (*it).name; 0228 } 0229 0230 if (cfg().parentInConstructor) { 0231 if (parseResult.cfgFileNameArg || !parseResult.parameters.isEmpty()) { 0232 stream() << ","; 0233 } 0234 stream() << " QObject *parent"; 0235 } 0236 } 0237 0238 void KConfigSourceGenerator::createParentConstructorCall() 0239 { 0240 stream() << cfg().inherits << "("; 0241 if (parseResult.cfgStateConfig) { 0242 stream() << " KSharedConfig::openStateConfig(QStringLiteral( \"" << parseResult.cfgFileName << "\") "; 0243 } else if (!parseResult.cfgFileName.isEmpty()) { 0244 stream() << " QStringLiteral( \"" << parseResult.cfgFileName << "\" "; 0245 } 0246 if (parseResult.cfgFileNameArg) { 0247 if (!cfg().forceStringFilename) { 0248 stream() << " std::move( config ) "; 0249 } else { 0250 stream() << " config "; 0251 } 0252 } 0253 if (!parseResult.cfgFileName.isEmpty()) { 0254 stream() << ") "; 0255 } 0256 stream() << ")\n"; 0257 } 0258 0259 void KConfigSourceGenerator::createInitializerList() 0260 { 0261 for (const auto ¶meter : std::as_const(parseResult.parameters)) { 0262 stream() << " , mParam" << parameter.name << "(" << parameter.name << ")\n"; 0263 } 0264 } 0265 0266 void KConfigSourceGenerator::createEnums(const CfgEntry *entry) 0267 { 0268 if (entry->type != QLatin1String("Enum")) { 0269 return; 0270 } 0271 stream() << " QList<" << cfg().inherits << "::ItemEnum::Choice> values" << entry->name << ";\n"; 0272 0273 for (const auto &choice : std::as_const(entry->choices.choices)) { 0274 stream() << " {\n"; 0275 stream() << " " << cfg().inherits << "::ItemEnum::Choice choice;\n"; 0276 stream() << " choice.name = QStringLiteral(\"" << choice.name << "\");\n"; 0277 if (cfg().setUserTexts) { 0278 if (!choice.label.isEmpty()) { 0279 stream() << " choice.label = " << translatedString(cfg(), choice.label, choice.context) << ";\n"; 0280 } 0281 if (!choice.toolTip.isEmpty()) { 0282 stream() << " choice.toolTip = " << translatedString(cfg(), choice.toolTip, choice.context) << ";\n"; 0283 } 0284 if (!choice.whatsThis.isEmpty()) { 0285 stream() << " choice.whatsThis = " << translatedString(cfg(), choice.whatsThis, choice.context) << ";\n"; 0286 } 0287 } 0288 stream() << " values" << entry->name << ".append( choice );\n"; 0289 stream() << " }\n"; 0290 } 0291 } 0292 0293 void KConfigSourceGenerator::createNormalEntry(const CfgEntry *entry, const QString &key) 0294 { 0295 const QString itemVarStr = itemPath(entry, cfg()); 0296 const QString innerItemVarStr = innerItemVar(entry, cfg()); 0297 if (!entry->signalList.isEmpty()) { 0298 stream() << " " << innerItemVarStr << " = " << newInnerItem(entry, key, entry->defaultValue, cfg()) << '\n'; 0299 } 0300 0301 stream() << " " << itemVarStr << " = " << newItem(entry, key, entry->defaultValue, cfg()) << '\n'; 0302 0303 if (!entry->min.isEmpty()) { 0304 stream() << " " << innerItemVarStr << "->setMinValue(" << entry->min << ");\n"; 0305 } 0306 0307 if (!entry->max.isEmpty()) { 0308 stream() << " " << innerItemVarStr << "->setMaxValue(" << entry->max << ");\n"; 0309 } 0310 0311 if (cfg().setUserTexts) { 0312 stream() << userTextsFunctions(entry, cfg()); 0313 } 0314 0315 if (cfg().allNotifiers || cfg().notifiers.contains(entry->name)) { 0316 stream() << " " << itemVarStr << "->setWriteFlags(KConfigBase::Notify);\n"; 0317 } 0318 0319 for (const CfgEntry::Choice &choice : std::as_const(entry->choices.choices)) { 0320 if (!choice.val.isEmpty()) { 0321 stream() << " " << innerItemVarStr << "->setValueForChoice(QStringLiteral( \"" << choice.name << "\" ), QStringLiteral( \"" << choice.val 0322 << "\" ));\n"; 0323 } 0324 } 0325 0326 if (!entry->parentGroup.isEmpty()) { 0327 stream() << " " << itemVarStr << "->setGroup(cg" << QString(entry->group).remove(QRegularExpression(QStringLiteral("\\W"))) << ");\n"; 0328 } 0329 0330 stream() << " addItem( " << itemVarStr; 0331 QString quotedName = entry->name; 0332 addQuotes(quotedName); 0333 if (quotedName != key) { 0334 stream() << ", QStringLiteral( \"" << entry->name << "\" )"; 0335 } 0336 stream() << " );\n"; 0337 } 0338 0339 // TODO : Some compiler option won't work or generate bogus settings file. 0340 // * Does not manage properly Notifiers=true kcfgc option for parameterized entries : 0341 // ** KConfigCompilerSignallingItem generated with wrong userData parameter (4th one). 0342 // ** setWriteFlags() is missing. 0343 // * Q_PROPERTY signal won't work 0344 void KConfigSourceGenerator::createIndexedEntry(const CfgEntry *entry, const QString &key) 0345 { 0346 for (int i = 0; i <= entry->paramMax; i++) { 0347 const QString argBracket = QStringLiteral("[%1]").arg(i); 0348 const QString innerItemVarStr = innerItemVar(entry, cfg()) + argBracket; 0349 0350 const QString defaultStr = !entry->paramDefaultValues[i].isEmpty() ? entry->paramDefaultValues[i] 0351 : !entry->defaultValue.isEmpty() ? paramString(entry->defaultValue, entry, i) 0352 : defaultValue(entry->type); 0353 0354 if (!entry->signalList.isEmpty()) { 0355 stream() << " " << innerItemVarStr << " = " << newInnerItem(entry, paramString(key, entry, i), defaultStr, cfg(), argBracket) << '\n'; 0356 } 0357 0358 const QString itemVarStr = itemPath(entry, cfg()) + argBracket; 0359 0360 stream() << " " << itemVarStr << " = " << newItem(entry, paramString(key, entry, i), defaultStr, cfg(), argBracket) << '\n'; 0361 0362 if (!entry->min.isEmpty()) { 0363 stream() << " " << innerItemVarStr << "->setMinValue(" << entry->min << ");\n"; 0364 } 0365 if (!entry->max.isEmpty()) { 0366 stream() << " " << innerItemVarStr << "->setMaxValue(" << entry->max << ");\n"; 0367 } 0368 0369 for (const CfgEntry::Choice &choice : std::as_const(entry->choices.choices)) { 0370 if (!choice.val.isEmpty()) { 0371 stream() << " " << innerItemVarStr << "->setValueForChoice(QStringLiteral( \"" << choice.name << "\" ), QStringLiteral( \"" << choice.val 0372 << "\" ));\n"; 0373 } 0374 } 0375 0376 if (cfg().setUserTexts) { 0377 stream() << userTextsFunctions(entry, cfg(), itemVarStr, entry->paramName); 0378 } 0379 0380 // Make mutators for enum parameters work by adding them with $(..) replaced by the 0381 // param name. The check for isImmutable in the set* functions doesn't have the param 0382 // name available, just the corresponding enum value (int), so we need to store the 0383 // param names in a separate static list!. 0384 const bool isEnum = entry->paramType == QLatin1String("Enum"); 0385 const QString arg = isEnum ? entry->paramValues[i] : QString::number(i); 0386 0387 QString paramName = entry->paramName; 0388 0389 stream() << " addItem( " << itemVarStr << ", QStringLiteral( \""; 0390 stream() << paramName.replace(QStringLiteral("$(") + entry->param + QLatin1Char(')'), QLatin1String("%1")).arg(arg); 0391 stream() << "\" ) );\n"; 0392 } 0393 } 0394 0395 void KConfigSourceGenerator::handleCurrentGroupChange(const CfgEntry *entry) 0396 { 0397 if (entry->group == mCurrentGroup) { 0398 return; 0399 } 0400 0401 // HACK: This fixes one spacing line in the diff. Remove this in the future and adapt the testcases. 0402 static bool first = true; 0403 if (!entry->group.isEmpty()) { 0404 if (!first) { 0405 stream() << '\n'; 0406 } 0407 first = false; 0408 } 0409 0410 mCurrentGroup = entry->group; 0411 0412 if (!entry->parentGroup.isEmpty()) { 0413 QString parentGroup = QString(entry->parentGroup).remove(QRegularExpression(QStringLiteral("\\W"))); 0414 if (!mConfigGroupList.contains(parentGroup)) { 0415 stream() << " KConfigGroup cg" << parentGroup << "(this->config(), " << paramString(entry->parentGroup, parseResult.parameters) << ");\n"; 0416 mConfigGroupList << parentGroup; 0417 } 0418 QString currentGroup = QString(mCurrentGroup).remove(QRegularExpression(QStringLiteral("\\W"))); 0419 if (!mConfigGroupList.contains(currentGroup)) { 0420 stream() << " KConfigGroup cg" << currentGroup << " = cg" << QString(entry->parentGroup).remove(QRegularExpression(QStringLiteral("\\W"))) 0421 << ".group(" << paramString(mCurrentGroup, parseResult.parameters) << ");\n"; 0422 mConfigGroupList << currentGroup; 0423 } 0424 } else { 0425 stream() << " setCurrentGroup( " << paramString(mCurrentGroup, parseResult.parameters) << " );"; 0426 stream() << "\n\n"; 0427 } 0428 } 0429 0430 void KConfigSourceGenerator::doConstructor() 0431 { 0432 // Constructor 0433 stream() << cfg().className << "::" << cfg().className << "("; 0434 createConstructorParameterList(); 0435 stream() << " )\n"; 0436 stream() << " : "; 0437 createParentConstructorCall(); 0438 createInitializerList(); 0439 0440 stream() << "{\n"; 0441 0442 if (cfg().parentInConstructor) { 0443 stream() << " setParent(parent);\n"; 0444 } 0445 0446 if (cfg().dpointer) { 0447 stream() << " d = new " << cfg().className << "Private;\n"; 0448 } 0449 0450 // Needed in case the singleton class is used as baseclass for 0451 // another singleton. 0452 if (cfg().singleton) { 0453 stream() << " Q_ASSERT(!s_global" << cfg().className << "()->q);\n"; 0454 stream() << " s_global" << cfg().className << "()->q = this;\n"; 0455 } 0456 0457 if (!parseResult.signalList.isEmpty()) { 0458 // this cast to base-class pointer-to-member is valid C++ 0459 // https://stackoverflow.com/questions/4272909/is-it-safe-to-upcast-a-method-pointer-and-use-it-with-base-class-pointer/ 0460 stream() << " KConfigCompilerSignallingItem::NotifyFunction notifyFunction =" 0461 << " static_cast<KConfigCompilerSignallingItem::NotifyFunction>(&" << cfg().className << "::itemChanged);\n"; 0462 0463 stream() << '\n'; 0464 } 0465 0466 for (const auto *entry : std::as_const(parseResult.entries)) { 0467 handleCurrentGroupChange(entry); 0468 0469 const QString key = paramString(entry->key, parseResult.parameters); 0470 if (!entry->code.isEmpty()) { 0471 stream() << entry->code << '\n'; 0472 } 0473 createEnums(entry); 0474 0475 stream() << itemDeclaration(entry, cfg()); 0476 0477 if (entry->param.isEmpty()) { 0478 createNormalEntry(entry, key); 0479 } else { 0480 createIndexedEntry(entry, key); 0481 } 0482 } 0483 0484 stream() << "}\n\n"; 0485 } 0486 0487 void KConfigSourceGenerator::createGetterDPointerMode(const CfgEntry *entry) 0488 { 0489 // Accessor 0490 if (cfg().useEnumTypes && entry->type == QLatin1String("Enum")) { 0491 stream() << enumType(entry, cfg().globalEnums); 0492 } else { 0493 stream() << cppType(entry->type); 0494 } 0495 0496 stream() << " " << getFunction(entry->name, cfg().className) << "("; 0497 if (!entry->param.isEmpty()) { 0498 stream() << " " << cppType(entry->paramType) << " i "; 0499 } 0500 stream() << ")" << Const() << '\n'; 0501 0502 // function body inline only if not using dpointer 0503 // for BC mode 0504 startScope(); 0505 // HACK: Fix memberAccessorBody 0506 stream() << " " << memberAccessorBody(entry, cfg().globalEnums); 0507 endScope(); 0508 stream() << '\n'; 0509 } 0510 0511 void KConfigSourceGenerator::createImmutableGetterDPointerMode(const CfgEntry *entry) 0512 { 0513 stream() << whitespace() << ""; 0514 stream() << "bool " 0515 << " " << immutableFunction(entry->name, cfg().className) << "("; 0516 if (!entry->param.isEmpty()) { 0517 stream() << " " << cppType(entry->paramType) << " i "; 0518 } 0519 stream() << ")" << Const() << '\n'; 0520 startScope(); 0521 memberImmutableBody(entry, cfg().globalEnums); 0522 endScope(); 0523 stream() << '\n'; 0524 } 0525 0526 void KConfigSourceGenerator::createSetterDPointerMode(const CfgEntry *entry) 0527 { 0528 // Manipulator 0529 if (!(cfg().allMutators || cfg().mutators.contains(entry->name))) { 0530 return; 0531 } 0532 0533 stream() << "void " << setFunction(entry->name, cfg().className) << "( "; 0534 if (!entry->param.isEmpty()) { 0535 stream() << cppType(entry->paramType) << " i, "; 0536 } 0537 0538 if (cfg().useEnumTypes && entry->type == QLatin1String("Enum")) { 0539 stream() << enumType(entry, cfg().globalEnums); 0540 } else { 0541 stream() << param(entry->type); 0542 } 0543 stream() << " v )\n"; 0544 0545 // function body inline only if not using dpointer 0546 // for BC mode 0547 startScope(); 0548 memberMutatorBody(entry); 0549 endScope(); 0550 stream() << '\n'; 0551 } 0552 0553 void KConfigSourceGenerator::createItemGetterDPointerMode(const CfgEntry *entry) 0554 { 0555 // Item accessor 0556 if (!cfg().itemAccessors) { 0557 return; 0558 } 0559 stream() << '\n'; 0560 stream() << cfg().inherits << "::Item" << itemType(entry->type) << " *" << getFunction(entry->name, cfg().className) << "Item("; 0561 if (!entry->param.isEmpty()) { 0562 stream() << " " << cppType(entry->paramType) << " i "; 0563 } 0564 stream() << ")\n"; 0565 startScope(); 0566 stream() << " " << itemAccessorBody(entry, cfg()); 0567 endScope(); 0568 } 0569 0570 void KConfigSourceGenerator::doGetterSetterDPointerMode() 0571 { 0572 if (!cfg().dpointer) { 0573 return; 0574 } 0575 0576 // setters and getters go in Cpp if in dpointer mode 0577 for (const auto *entry : std::as_const(parseResult.entries)) { 0578 createSetterDPointerMode(entry); 0579 createGetterDPointerMode(entry); 0580 createImmutableGetterDPointerMode(entry); 0581 createItemGetterDPointerMode(entry); 0582 stream() << '\n'; 0583 } 0584 } 0585 0586 void KConfigSourceGenerator::createDefaultValueGetterSetter() 0587 { 0588 // default value getters always go in Cpp 0589 for (const auto *entry : std::as_const(parseResult.entries)) { 0590 QString n = entry->name; 0591 QString t = entry->type; 0592 0593 // Default value Accessor, as "helper" function 0594 if ((cfg().allDefaultGetters || cfg().defaultGetters.contains(n)) && !entry->defaultValue.isEmpty()) { 0595 stream() << cppType(t) << " " << getDefaultFunction(n, cfg().className) << "_helper("; 0596 if (!entry->param.isEmpty()) { 0597 stream() << " " << cppType(entry->paramType) << " i "; 0598 } 0599 stream() << ")" << Const() << '\n'; 0600 startScope(); 0601 stream() << memberGetDefaultBody(entry) << '\n'; 0602 endScope(); 0603 stream() << '\n'; 0604 } 0605 } 0606 } 0607 0608 void KConfigSourceGenerator::createDestructor() 0609 { 0610 stream() << cfg().className << "::~" << cfg().className << "()\n"; 0611 startScope(); 0612 if (cfg().dpointer) { 0613 stream() << " delete d;\n"; 0614 } 0615 if (cfg().singleton) { 0616 const QString qgs = QLatin1String("s_global") + cfg().className; 0617 stream() << " if (" << qgs << ".exists() && !" << qgs << ".isDestroyed()) {\n"; 0618 stream() << " " << qgs << "()->q = nullptr;\n"; 0619 stream() << " }\n"; 0620 } 0621 endScope(); 0622 stream() << '\n'; 0623 } 0624 0625 void KConfigSourceGenerator::createNonModifyingSignalsHelper() 0626 { 0627 if (!parseResult.hasNonModifySignals) { 0628 return; 0629 } 0630 stream() << "bool " << cfg().className << "::" 0631 << "usrSave()\n"; 0632 startScope(); 0633 stream() << " const bool res = " << cfg().inherits << "::usrSave();\n"; 0634 stream() << " if (!res) return false;\n\n"; 0635 for (const Signal &signal : std::as_const(parseResult.signalList)) { 0636 if (signal.modify) { 0637 continue; 0638 } 0639 0640 stream() << " if (" << varPath(QStringLiteral("settingsChanged"), cfg()) << ".contains(" << signalEnumName(signal.name) << "))\n"; 0641 stream() << " Q_EMIT " << signal.name << "("; 0642 auto it = signal.arguments.cbegin(); 0643 const auto itEnd = signal.arguments.cend(); 0644 while (it != itEnd) { 0645 Param argument = *it; 0646 bool cast = false; 0647 if (cfg().useEnumTypes && argument.type == QLatin1String("Enum")) { 0648 for (int i = 0, end = parseResult.entries.count(); i < end; ++i) { 0649 if (parseResult.entries.at(i)->name == argument.name) { 0650 stream() << "static_cast<" << enumType(parseResult.entries.at(i), cfg().globalEnums) << ">("; 0651 cast = true; 0652 break; 0653 } 0654 } 0655 } 0656 stream() << varPath(argument.name, cfg()); 0657 if (cast) { 0658 stream() << ")"; 0659 } 0660 if (++it != itEnd) { 0661 stream() << ", "; 0662 } 0663 } 0664 0665 stream() << ");\n"; 0666 } 0667 0668 stream() << " " << varPath(QStringLiteral("settingsChanged"), cfg()) << ".clear();\n"; 0669 stream() << " return true;\n"; 0670 endScope(); 0671 } 0672 0673 void KConfigSourceGenerator::createSignalFlagsHandler() 0674 { 0675 if (parseResult.signalList.isEmpty()) { 0676 return; 0677 } 0678 0679 stream() << '\n'; 0680 stream() << "void " << cfg().className << "::" 0681 << "itemChanged(quint64 signalFlag) {\n"; 0682 if (parseResult.hasNonModifySignals) { 0683 stream() << " " << varPath(QStringLiteral("settingsChanged"), cfg()) << ".insert(signalFlag);\n"; 0684 } 0685 0686 if (!parseResult.signalList.isEmpty()) { 0687 stream() << '\n'; 0688 } 0689 0690 bool modifySignalsWritten = false; 0691 for (const Signal &signal : std::as_const(parseResult.signalList)) { 0692 if (signal.modify) { 0693 if (!modifySignalsWritten) { 0694 stream() << " switch (signalFlag) {\n"; 0695 modifySignalsWritten = true; 0696 } 0697 stream() << " case " << signalEnumName(signal.name) << ":\n"; 0698 stream() << " Q_EMIT " << signal.name << "();\n"; 0699 stream() << " break;\n"; 0700 } 0701 } 0702 if (modifySignalsWritten) { 0703 stream() << " }\n"; 0704 } 0705 0706 stream() << "}\n"; 0707 } 0708 0709 void KConfigSourceGenerator::includeMoc() 0710 { 0711 const QString mocFileName = cfg().baseName + QStringLiteral(".moc"); 0712 0713 if (parseResult.signalList.count() || cfg().generateProperties) { 0714 // Add includemoc if they are signals defined. 0715 stream() << '\n'; 0716 stream() << "#include \"" << mocFileName << "\"\n"; 0717 stream() << '\n'; 0718 } 0719 }