14#include "KConfigSourceGenerator.h"
16#include <QRegularExpression>
19 : KConfigCodeGeneratorBase(inputFile, baseDir, baseDir + cfg.baseName +
QLatin1String(
".cpp"), cfg, parseResult)
23void KConfigSourceGenerator::start()
25 KConfigCodeGeneratorBase::start();
29 if (!cfg().nameSpace.isEmpty()) {
30 stream() <<
"using namespace " << cfg().nameSpace <<
";";
34 createPrivateDPointerImplementation();
35 createSingletonImplementation();
38 doGetterSetterDPointerMode();
39 createDefaultValueGetterSetter();
41 createNonModifyingSignalsHelper();
42 createSignalFlagsHandler();
46void KConfigSourceGenerator::createHeaders()
51 addQuotes(headerName);
53 addHeaders({headerName});
56 addHeaders(cfg().sourceIncludes);
57 if (cfg().setUserTexts && cfg().translationSystem == KConfigParameters::KdeTranslation) {
58 addHeaders({QStringLiteral(
"klocalizedstring.h")});
63 if (cfg().singleton) {
64 addHeaders({QStringLiteral(
"qglobal.h"), QStringLiteral(
"QFile")});
67 if (cfg().singleton && parseResult.cfgFileNameArg) {
72 if (cfg().singleton && parseResult.cfgFileNameArg) {
73 addHeaders({QStringLiteral(
"QDebug")});
76 if (cfg().dpointer && parseResult.hasNonModifySignals) {
77 addHeaders({QStringLiteral(
"QSet")});
80 if (cfg().singleton) {
85void KConfigSourceGenerator::createPrivateDPointerImplementation()
88 if (!cfg().dpointer) {
94 stream() <<
"class " << cfg().className <<
"Private\n";
96 stream() <<
" public:\n";
99 for (
const auto *entry :
std::as_const(parseResult.entries)) {
100 if (entry->group != group) {
101 group = entry->group;
103 stream() <<
" // " << group <<
'\n';
105 stream() <<
" " << cppType(entry->type) <<
" " << varName(entry->name, cfg());
106 if (!entry->param.isEmpty()) {
107 stream() << QStringLiteral(
"[%1]").arg(entry->paramMax + 1);
111 stream() <<
"\n // items\n";
114 for (
const auto *entry :
std::as_const(parseResult.entries)) {
115 const QString declType = entry->signalList.
isEmpty() ?
QString(cfg().inherits + QStringLiteral(
"::Item") + itemType(entry->type))
116 : QStringLiteral(
"KConfigCompilerSignallingItem");
118 stream() <<
" " << declType <<
" *" << itemVar(entry, cfg());
119 if (!entry->param.isEmpty()) {
120 stream() << QStringLiteral(
"[%1]").arg(entry->paramMax + 1);
125 if (parseResult.hasNonModifySignals) {
126 stream() <<
" QSet<quint64> " << varName(QStringLiteral(
"settingsChanged"), cfg()) <<
";\n";
129 stream() <<
"};\n\n";
133void KConfigSourceGenerator::createSingletonImplementation()
136 if (!cfg().singleton) {
141 stream() <<
"class " << cfg().className <<
"Helper\n";
142 stream() <<
'{' <<
'\n';
143 stream() <<
" public:\n";
144 stream() <<
" " << cfg().className <<
"Helper() : q(nullptr) {}\n";
145 stream() <<
" ~" << cfg().className <<
"Helper() { delete q; q = nullptr; }\n";
146 stream() <<
" " << cfg().className <<
"Helper(const " << cfg().className <<
"Helper&) = delete;\n";
147 stream() <<
" " << cfg().className <<
"Helper& operator=(const " << cfg().className <<
"Helper&) = delete;\n";
148 stream() <<
" " << cfg().className <<
" *q;\n";
152 stream() <<
"Q_GLOBAL_STATIC(" << cfg().className <<
"Helper, s_global" << cfg().className <<
")\n";
154 stream() << cfg().className <<
" *" << cfg().className <<
"::self()\n";
156 if (parseResult.cfgFileNameArg) {
157 stream() <<
" if (!s_global" << cfg().className <<
"()->q)\n";
158 stream() <<
" qFatal(\"you need to call " << cfg().className <<
"::instance before using\");\n";
160 stream() <<
" if (!s_global" << cfg().className <<
"()->q) {\n";
161 stream() <<
" new " << cfg().className <<
';' <<
'\n';
162 stream() <<
" s_global" << cfg().className <<
"()->q->read();\n";
163 stream() <<
" }\n\n";
165 stream() <<
" return s_global" << cfg().className <<
"()->q;\n";
168 if (parseResult.cfgFileNameArg) {
170 stream() <<
"void " << cfg().className <<
"::instance(" <<
type <<
" " << arg <<
")\n";
172 stream() <<
" if (s_global" << cfg().className <<
"()->q) {\n";
173 stream() <<
" qDebug() << \"" << cfg().className <<
"::instance called after the first use - ignoring\";\n";
174 stream() <<
" return;\n";
176 stream() <<
" new " << cfg().className <<
"(";
177 if (parseResult.cfgStateConfig) {
178 stream() <<
"KSharedConfig::openStateConfig(" << arg <<
")";
179 }
else if (isString) {
180 stream() <<
"KSharedConfig::openConfig(" << arg <<
")";
182 stream() <<
"std::move(" << arg <<
")";
185 stream() <<
" s_global" << cfg().className <<
"()->q->read();\n";
188 instance(QStringLiteral(
"const QString&"), QStringLiteral(
"cfgfilename"),
true);
189 instance(QStringLiteral(
"KSharedConfig::Ptr"), QStringLiteral(
"config"),
false);
193void KConfigSourceGenerator::createPreamble()
196 for (
const auto *entry :
std::as_const(parseResult.entries)) {
197 if (entry->paramValues.isEmpty()) {
201 cppPreamble += QStringLiteral(
"const char* const ") + cfg().className + QStringLiteral(
"::") + enumName(entry->param);
202 cppPreamble += cfg().globalEnums
203 ? QStringLiteral(
"ToString[] = { \"") + entry->paramValues.join(QStringLiteral(
"\", \"")) + QStringLiteral(
"\" };\n")
204 : QStringLiteral(
"::enumToString[] = { \"") + entry->paramValues.join(QStringLiteral(
"\", \"")) + QStringLiteral(
"\" };\n");
208 stream() << cppPreamble <<
'\n';
212void KConfigSourceGenerator::createConstructorParameterList()
214 if (parseResult.cfgFileNameArg) {
215 if (!cfg().forceStringFilename) {
216 stream() <<
" KSharedConfig::Ptr config";
218 stream() <<
" const QString& config";
220 stream() << (parseResult.parameters.
isEmpty() ?
"" :
",");
223 for (
auto it = parseResult.parameters.
cbegin(); it != parseResult.parameters.
cend(); ++it) {
224 if (it != parseResult.parameters.
cbegin()) {
227 stream() <<
" " << param((*it).type) <<
" " << (*it).name;
230 if (cfg().parentInConstructor) {
231 if (parseResult.cfgFileNameArg || !parseResult.parameters.
isEmpty()) {
234 stream() <<
" QObject *parent";
238void KConfigSourceGenerator::createParentConstructorCall()
240 stream() << cfg().inherits <<
"(";
241 if (parseResult.cfgStateConfig) {
242 stream() <<
" KSharedConfig::openStateConfig(QStringLiteral( \"" << parseResult.cfgFileName <<
"\") ";
243 }
else if (!parseResult.cfgFileName.
isEmpty()) {
244 stream() <<
" QStringLiteral( \"" << parseResult.cfgFileName <<
"\" ";
246 if (parseResult.cfgFileNameArg) {
247 if (!cfg().forceStringFilename) {
248 stream() <<
" std::move( config ) ";
250 stream() <<
" config ";
253 if (!parseResult.cfgFileName.
isEmpty()) {
259void KConfigSourceGenerator::createInitializerList()
261 for (
const auto ¶meter :
std::as_const(parseResult.parameters)) {
262 stream() <<
" , mParam" << parameter.name <<
"(" << parameter.name <<
")\n";
266void KConfigSourceGenerator::createEnums(
const CfgEntry *entry)
271 stream() <<
" QList<" << cfg().inherits <<
"::ItemEnum::Choice> values" << entry->name <<
";\n";
273 for (
const auto &choice :
std::as_const(entry->choices.choices)) {
275 stream() <<
" " << cfg().inherits <<
"::ItemEnum::Choice choice;\n";
276 stream() <<
" choice.name = QStringLiteral(\"" << choice.name <<
"\");\n";
277 if (cfg().setUserTexts) {
278 if (!choice.label.isEmpty()) {
279 stream() <<
" choice.label = " << translatedString(cfg(), choice.label, choice.context) <<
";\n";
281 if (!choice.toolTip.isEmpty()) {
282 stream() <<
" choice.toolTip = " << translatedString(cfg(), choice.toolTip, choice.context) <<
";\n";
284 if (!choice.whatsThis.isEmpty()) {
285 stream() <<
" choice.whatsThis = " << translatedString(cfg(), choice.whatsThis, choice.context) <<
";\n";
288 stream() <<
" values" << entry->name <<
".append( choice );\n";
293void KConfigSourceGenerator::createNormalEntry(
const CfgEntry *entry,
const QString &key)
295 const QString itemVarStr = itemPath(entry, cfg());
296 const QString innerItemVarStr = innerItemVar(entry, cfg());
297 if (!entry->signalList.
isEmpty()) {
298 stream() <<
" " << innerItemVarStr <<
" = " << newInnerItem(entry, key, entry->defaultValue, cfg()) <<
'\n';
301 stream() <<
" " << itemVarStr <<
" = " << newItem(entry, key, entry->defaultValue, cfg()) <<
'\n';
304 stream() <<
" " << innerItemVarStr <<
"->setMinValue(" << entry->min <<
");\n";
308 stream() <<
" " << innerItemVarStr <<
"->setMaxValue(" << entry->max <<
");\n";
311 if (cfg().setUserTexts) {
312 stream() << userTextsFunctions(entry, cfg());
315 if (cfg().allNotifiers || cfg().notifiers.contains(entry->name)) {
316 stream() <<
" " << itemVarStr <<
"->setWriteFlags(KConfigBase::Notify);\n";
319 for (
const CfgEntry::Choice &choice :
std::as_const(entry->choices.choices)) {
320 if (!choice.val.isEmpty()) {
321 stream() <<
" " << innerItemVarStr <<
"->setValueForChoice(QStringLiteral( \"" << choice.name <<
"\" ), QStringLiteral( \"" << choice.val
326 if (!entry->parentGroup.
isEmpty()) {
330 stream() <<
" addItem( " << itemVarStr;
331 QString quotedName = entry->name;
332 addQuotes(quotedName);
333 if (quotedName != key) {
334 stream() <<
", QStringLiteral( \"" << entry->name <<
"\" )";
344void KConfigSourceGenerator::createIndexedEntry(
const CfgEntry *entry,
const QString &key)
346 for (
int i = 0; i <= entry->paramMax; i++) {
347 const QString argBracket = QStringLiteral(
"[%1]").
arg(i);
348 const QString innerItemVarStr = innerItemVar(entry, cfg()) + argBracket;
350 const QString defaultStr = !entry->paramDefaultValues[i].
isEmpty() ? entry->paramDefaultValues[i]
351 : !entry->defaultValue.
isEmpty() ? paramString(entry->defaultValue, entry, i)
352 : defaultValue(entry->
type);
354 if (!entry->signalList.
isEmpty()) {
355 stream() <<
" " << innerItemVarStr <<
" = " << newInnerItem(entry, paramString(key, entry, i), defaultStr, cfg(), argBracket) <<
'\n';
358 const QString itemVarStr = itemPath(entry, cfg()) + argBracket;
360 stream() <<
" " << itemVarStr <<
" = " << newItem(entry, paramString(key, entry, i), defaultStr, cfg(), argBracket) <<
'\n';
363 stream() <<
" " << innerItemVarStr <<
"->setMinValue(" << entry->min <<
");\n";
366 stream() <<
" " << innerItemVarStr <<
"->setMaxValue(" << entry->max <<
");\n";
369 for (
const CfgEntry::Choice &choice :
std::as_const(entry->choices.choices)) {
370 if (!choice.val.isEmpty()) {
371 stream() <<
" " << innerItemVarStr <<
"->setValueForChoice(QStringLiteral( \"" << choice.name <<
"\" ), QStringLiteral( \"" << choice.val
376 if (cfg().setUserTexts) {
377 stream() << userTextsFunctions(entry, cfg(), itemVarStr, entry->paramName);
384 const bool isEnum = entry->paramType ==
QLatin1String(
"Enum");
387 QString paramName = entry->paramName;
389 stream() <<
" addItem( " << itemVarStr <<
", QStringLiteral( \"";
391 stream() <<
"\" ) );\n";
395void KConfigSourceGenerator::handleCurrentGroupChange(
const CfgEntry *entry)
397 if (entry->group == mCurrentGroup) {
402 static bool first =
true;
410 mCurrentGroup = entry->group;
412 if (!entry->parentGroup.
isEmpty()) {
414 if (!mConfigGroupList.
contains(parentGroup)) {
415 stream() <<
" KConfigGroup cg" << parentGroup <<
"(this->config(), " << paramString(entry->parentGroup, parseResult.parameters) <<
");\n";
416 mConfigGroupList << parentGroup;
419 if (!mConfigGroupList.
contains(currentGroup)) {
421 <<
".group(" << paramString(mCurrentGroup, parseResult.parameters) <<
");\n";
422 mConfigGroupList << currentGroup;
425 stream() <<
" setCurrentGroup( " << paramString(mCurrentGroup, parseResult.parameters) <<
" );";
430void KConfigSourceGenerator::doConstructor()
433 stream() << cfg().className <<
"::" << cfg().className <<
"(";
434 createConstructorParameterList();
437 createParentConstructorCall();
438 createInitializerList();
442 if (cfg().parentInConstructor) {
443 stream() <<
" setParent(parent);\n";
446 if (cfg().dpointer) {
447 stream() <<
" d = new " << cfg().className <<
"Private;\n";
452 if (cfg().singleton) {
453 stream() <<
" Q_ASSERT(!s_global" << cfg().className <<
"()->q);\n";
454 stream() <<
" s_global" << cfg().className <<
"()->q = this;\n";
457 if (!parseResult.signalList.
isEmpty()) {
460 stream() <<
" KConfigCompilerSignallingItem::NotifyFunction notifyFunction ="
461 <<
" static_cast<KConfigCompilerSignallingItem::NotifyFunction>(&" << cfg().className <<
"::itemChanged);\n";
466 for (
const auto *entry :
std::as_const(parseResult.entries)) {
467 handleCurrentGroupChange(entry);
469 const QString key = paramString(entry->key, parseResult.parameters);
471 stream() << entry->code <<
'\n';
475 stream() << itemDeclaration(entry, cfg());
478 createNormalEntry(entry, key);
480 createIndexedEntry(entry, key);
487void KConfigSourceGenerator::createGetterDPointerMode(
const CfgEntry *entry)
490 if (cfg().useEnumTypes && entry->type ==
QLatin1String(
"Enum")) {
491 stream() << enumType(entry, cfg().globalEnums);
493 stream() << cppType(entry->type);
496 stream() <<
" " << getFunction(entry->name, cfg().className) <<
"(";
498 stream() <<
" " << cppType(entry->paramType) <<
" i ";
500 stream() <<
")" << Const() <<
'\n';
506 stream() <<
" " << memberAccessorBody(entry, cfg().globalEnums);
511void KConfigSourceGenerator::createImmutableGetterDPointerMode(
const CfgEntry *entry)
513 stream() << whitespace() <<
"";
515 <<
" " << immutableFunction(entry->name, cfg().className) <<
"(";
517 stream() <<
" " << cppType(entry->paramType) <<
" i ";
519 stream() <<
")" << Const() <<
'\n';
521 memberImmutableBody(entry, cfg().globalEnums);
526void KConfigSourceGenerator::createSetterDPointerMode(
const CfgEntry *entry)
529 if (!(cfg().allMutators || cfg().mutators.contains(entry->name))) {
533 stream() <<
"void " << setFunction(entry->name, cfg().className) <<
"( ";
535 stream() << cppType(entry->paramType) <<
" i, ";
538 if (cfg().useEnumTypes && entry->type ==
QLatin1String(
"Enum")) {
539 stream() << enumType(entry, cfg().globalEnums);
541 stream() << param(entry->type);
543 stream() <<
" v )\n";
548 memberMutatorBody(entry);
553void KConfigSourceGenerator::createItemGetterDPointerMode(
const CfgEntry *entry)
556 if (!cfg().itemAccessors) {
560 stream() << cfg().inherits <<
"::Item" << itemType(entry->type) <<
" *" << getFunction(entry->name, cfg().className) <<
"Item(";
562 stream() <<
" " << cppType(entry->paramType) <<
" i ";
566 stream() <<
" " << itemAccessorBody(entry, cfg());
570void KConfigSourceGenerator::doGetterSetterDPointerMode()
572 if (!cfg().dpointer) {
577 for (
const auto *entry :
std::as_const(parseResult.entries)) {
578 createSetterDPointerMode(entry);
579 createGetterDPointerMode(entry);
580 createImmutableGetterDPointerMode(entry);
581 createItemGetterDPointerMode(entry);
586void KConfigSourceGenerator::createDefaultValueGetterSetter()
589 for (
const auto *entry :
std::as_const(parseResult.entries)) {
594 if ((cfg().allDefaultGetters || cfg().defaultGetters.contains(n)) && !entry->defaultValue.
isEmpty()) {
595 stream() << cppType(t) <<
" " << getDefaultFunction(n, cfg().className) <<
"_helper(";
597 stream() <<
" " << cppType(entry->paramType) <<
" i ";
599 stream() <<
")" << Const() <<
'\n';
601 stream() << memberGetDefaultBody(entry) <<
'\n';
608void KConfigSourceGenerator::createDestructor()
610 stream() << cfg().className <<
"::~" << cfg().className <<
"()\n";
612 if (cfg().dpointer) {
613 stream() <<
" delete d;\n";
615 if (cfg().singleton) {
617 stream() <<
" if (" << qgs <<
".exists() && !" << qgs <<
".isDestroyed()) {\n";
618 stream() <<
" " << qgs <<
"()->q = nullptr;\n";
625void KConfigSourceGenerator::createNonModifyingSignalsHelper()
627 if (!parseResult.hasNonModifySignals) {
630 stream() <<
"bool " << cfg().className <<
"::"
633 stream() <<
" const bool res = " << cfg().inherits <<
"::usrSave();\n";
634 stream() <<
" if (!res) return false;\n\n";
635 for (
const Signal &signal :
std::as_const(parseResult.signalList)) {
640 stream() <<
" if (" << varPath(QStringLiteral(
"settingsChanged"), cfg()) <<
".contains(" << signalEnumName(signal.name) <<
"))\n";
641 stream() <<
" Q_EMIT " << signal.name <<
"(";
642 auto it = signal.arguments.cbegin();
643 const auto itEnd = signal.arguments.cend();
644 while (it != itEnd) {
645 Param argument = *it;
647 if (cfg().useEnumTypes && argument.type ==
QLatin1String(
"Enum")) {
648 for (
int i = 0, end = parseResult.entries.
count(); i <
end; ++i) {
649 if (parseResult.entries.
at(i)->name == argument.name) {
650 stream() <<
"static_cast<" << enumType(parseResult.entries.
at(i), cfg().globalEnums) <<
">(";
656 stream() << varPath(argument.name, cfg());
668 stream() <<
" " << varPath(QStringLiteral(
"settingsChanged"), cfg()) <<
".clear();\n";
669 stream() <<
" return true;\n";
673void KConfigSourceGenerator::createSignalFlagsHandler()
675 if (parseResult.signalList.
isEmpty()) {
680 stream() <<
"void " << cfg().className <<
"::"
681 <<
"itemChanged(quint64 signalFlag) {\n";
682 if (parseResult.hasNonModifySignals) {
683 stream() <<
" " << varPath(QStringLiteral(
"settingsChanged"), cfg()) <<
".insert(signalFlag);\n";
686 if (!parseResult.signalList.
isEmpty()) {
690 bool modifySignalsWritten =
false;
691 for (
const Signal &signal :
std::as_const(parseResult.signalList)) {
693 if (!modifySignalsWritten) {
694 stream() <<
" switch (signalFlag) {\n";
695 modifySignalsWritten =
true;
697 stream() <<
" case " << signalEnumName(signal.name) <<
":\n";
698 stream() <<
" Q_EMIT " << signal.name <<
"();\n";
699 stream() <<
" break;\n";
702 if (modifySignalsWritten) {
709void KConfigSourceGenerator::includeMoc()
711 const QString mocFileName = cfg().baseName + QStringLiteral(
".moc");
713 if (parseResult.signalList.
count() || cfg().generateProperties) {
716 stream() <<
"#include \"" << mocFileName <<
"\"\n";
Configuration Compiler Configuration.
Type type(const QSqlDatabase &db)
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
const_reference at(qsizetype i) const const
const_iterator cbegin() const const
const_iterator cend() const const
qsizetype count() const const
bool isEmpty() const const
QString arg(Args &&... args) const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const