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();
45void KConfigSourceGenerator::createHeaders()
50 addQuotes(headerName);
52 addHeaders({headerName});
55 addHeaders(cfg().sourceIncludes);
56 if (cfg().setUserTexts && cfg().translationSystem == KConfigParameters::KdeTranslation) {
57 addHeaders({QStringLiteral(
"klocalizedstring.h")});
62 if (cfg().singleton) {
63 addHeaders({QStringLiteral(
"qglobal.h"), QStringLiteral(
"QFile")});
66 if (cfg().singleton && parseResult.cfgFileNameArg) {
71 if (cfg().singleton && parseResult.cfgFileNameArg) {
72 addHeaders({QStringLiteral(
"QDebug")});
75 if (cfg().dpointer && parseResult.hasNonModifySignals) {
76 addHeaders({QStringLiteral(
"QSet")});
79 if (cfg().qmlRegistration && cfg().singleton) {
80 addHeaders({QStringLiteral(
"QQmlEngine")});
83 if (cfg().singleton) {
88void KConfigSourceGenerator::createPrivateDPointerImplementation()
91 if (!cfg().dpointer) {
97 stream() <<
"class " << cfg().className <<
"Private\n";
99 stream() <<
" public:\n";
102 for (
const auto *entry : std::as_const(parseResult.entries)) {
103 if (entry->group != group) {
104 group = entry->group;
106 stream() <<
" // " << group <<
'\n';
108 stream() <<
" " << cppType(entry->type) <<
" " << varName(entry->name, cfg());
109 if (!entry->param.isEmpty()) {
110 stream() << QStringLiteral(
"[%1]").arg(entry->paramMax + 1);
114 stream() <<
"\n // items\n";
117 for (
const auto *entry : std::as_const(parseResult.entries)) {
118 const QString declType = entry->signalList.
isEmpty() ?
QString(cfg().inherits + QStringLiteral(
"::Item") + itemType(entry->type))
119 : QStringLiteral(
"KConfigCompilerSignallingItem");
121 stream() <<
" " << declType <<
" *" << itemVar(entry, cfg());
122 if (!entry->param.isEmpty()) {
123 stream() << QStringLiteral(
"[%1]").arg(entry->paramMax + 1);
128 if (parseResult.hasNonModifySignals) {
129 stream() <<
" QSet<quint64> " << varName(QStringLiteral(
"settingsChanged"), cfg()) <<
";\n";
132 stream() <<
"};\n\n";
136void KConfigSourceGenerator::createSingletonImplementation()
139 if (!cfg().singleton) {
144 stream() <<
"class " << cfg().className <<
"Helper\n";
145 stream() <<
'{' <<
'\n';
146 stream() <<
" public:\n";
147 stream() <<
" " << cfg().className <<
"Helper() : q(nullptr) {}\n";
148 stream() <<
" ~" << cfg().className <<
"Helper() { delete q; q = nullptr; }\n";
149 stream() <<
" " << cfg().className <<
"Helper(const " << cfg().className <<
"Helper&) = delete;\n";
150 stream() <<
" " << cfg().className <<
"Helper& operator=(const " << cfg().className <<
"Helper&) = delete;\n";
151 stream() <<
" " << cfg().className <<
" *q;\n";
155 stream() <<
"Q_GLOBAL_STATIC(" << cfg().className <<
"Helper, s_global" << cfg().className <<
")\n";
157 stream() << cfg().className <<
" *" << cfg().className <<
"::self()\n";
159 if (parseResult.cfgFileNameArg) {
160 stream() <<
" if (!s_global" << cfg().className <<
"()->q)\n";
161 stream() <<
" qFatal(\"you need to call " << cfg().className <<
"::instance before using\");\n";
163 stream() <<
" if (!s_global" << cfg().className <<
"()->q) {\n";
164 stream() <<
" new " << cfg().className <<
';' <<
'\n';
165 stream() <<
" s_global" << cfg().className <<
"()->q->read();\n";
166 stream() <<
" }\n\n";
168 stream() <<
" return s_global" << cfg().className <<
"()->q;\n";
171 if (cfg().qmlRegistration && cfg().singleton) {
172 stream() << cfg().className <<
" *" << cfg().className <<
"::create(QQmlEngine *, QJSEngine *)\n";
174 stream() <<
" QQmlEngine::setObjectOwnership(self(), QQmlEngine::CppOwnership);\n";
175 stream() <<
" return self();\n";
179 if (parseResult.cfgFileNameArg) {
181 stream() <<
"void " << cfg().className <<
"::instance(" <<
type <<
" " << arg <<
")\n";
183 stream() <<
" if (s_global" << cfg().className <<
"()->q) {\n";
184 stream() <<
" qDebug() << \"" << cfg().className <<
"::instance called after the first use - ignoring\";\n";
185 stream() <<
" return;\n";
187 stream() <<
" new " << cfg().className <<
"(";
188 if (parseResult.cfgStateConfig) {
189 stream() <<
"KSharedConfig::openStateConfig(" << arg <<
")";
190 }
else if (isString) {
191 stream() <<
"KSharedConfig::openConfig(" << arg <<
")";
193 stream() <<
"std::move(" << arg <<
")";
196 stream() <<
" s_global" << cfg().className <<
"()->q->read();\n";
199 instance(QStringLiteral(
"const QString&"), QStringLiteral(
"cfgfilename"),
true);
200 instance(QStringLiteral(
"KSharedConfig::Ptr"), QStringLiteral(
"config"),
false);
204void KConfigSourceGenerator::createPreamble()
207 for (
const auto *entry : std::as_const(parseResult.entries)) {
208 if (entry->paramValues.isEmpty()) {
212 cppPreamble += QStringLiteral(
"const char* const ") + cfg().className + QStringLiteral(
"::") + enumName(entry->param);
213 cppPreamble += cfg().globalEnums
214 ? QStringLiteral(
"ToString[] = { \"") + entry->paramValues.join(QStringLiteral(
"\", \"")) + QStringLiteral(
"\" };\n")
215 : QStringLiteral(
"::enumToString[] = { \"") + entry->paramValues.join(QStringLiteral(
"\", \"")) + QStringLiteral(
"\" };\n");
219 stream() << cppPreamble <<
'\n';
223void KConfigSourceGenerator::createConstructorParameterList()
225 if (parseResult.cfgFileNameArg) {
226 if (!cfg().forceStringFilename) {
227 stream() <<
" KSharedConfig::Ptr config";
229 stream() <<
" const QString& config";
231 stream() << (parseResult.parameters.
isEmpty() ?
"" :
",");
234 for (
auto it = parseResult.parameters.
cbegin(); it != parseResult.parameters.
cend(); ++it) {
235 if (it != parseResult.parameters.
cbegin()) {
238 stream() <<
" " << param((*it).type) <<
" " << (*it).name;
241 if (cfg().parentInConstructor) {
242 if (parseResult.cfgFileNameArg || !parseResult.parameters.
isEmpty()) {
245 stream() <<
" QObject *parent";
249void KConfigSourceGenerator::createParentConstructorCall()
251 stream() << cfg().inherits <<
"(";
252 if (parseResult.cfgStateConfig) {
253 stream() <<
" KSharedConfig::openStateConfig(QStringLiteral( \"" << parseResult.cfgFileName <<
"\") ";
254 }
else if (!parseResult.cfgFileName.
isEmpty()) {
255 stream() <<
" QStringLiteral( \"" << parseResult.cfgFileName <<
"\" ";
257 if (parseResult.cfgFileNameArg) {
258 if (!cfg().forceStringFilename) {
259 stream() <<
" std::move( config ) ";
261 stream() <<
" config ";
264 if (!parseResult.cfgFileName.
isEmpty()) {
270void KConfigSourceGenerator::createInitializerList()
272 for (
const auto ¶meter : std::as_const(parseResult.parameters)) {
273 stream() <<
" , mParam" << parameter.name <<
"(" << parameter.name <<
")\n";
277void KConfigSourceGenerator::createEnums(
const CfgEntry *entry)
282 stream() <<
" QList<" << cfg().inherits <<
"::ItemEnum::Choice> values" << entry->name <<
";\n";
284 for (
const auto &choice : std::as_const(entry->choices.choices)) {
286 stream() <<
" " << cfg().inherits <<
"::ItemEnum::Choice choice;\n";
287 stream() <<
" choice.name = QStringLiteral(\"" << choice.name <<
"\");\n";
288 if (cfg().setUserTexts) {
289 if (!choice.label.isEmpty()) {
290 stream() <<
" choice.label = " << translatedString(cfg(), choice.label, choice.context) <<
";\n";
292 if (!choice.toolTip.isEmpty()) {
293 stream() <<
" choice.toolTip = " << translatedString(cfg(), choice.toolTip, choice.context) <<
";\n";
295 if (!choice.whatsThis.isEmpty()) {
296 stream() <<
" choice.whatsThis = " << translatedString(cfg(), choice.whatsThis, choice.context) <<
";\n";
299 stream() <<
" values" << entry->name <<
".append( choice );\n";
304void KConfigSourceGenerator::createNormalEntry(
const CfgEntry *entry,
const QString &key)
306 const QString itemVarStr = itemPath(entry, cfg());
307 const QString innerItemVarStr = innerItemVar(entry, cfg());
308 if (!entry->signalList.
isEmpty()) {
309 stream() <<
" " << innerItemVarStr <<
" = " << newInnerItem(entry, key, entry->defaultValue, cfg()) <<
'\n';
312 stream() <<
" " << itemVarStr <<
" = " << newItem(entry, key, entry->defaultValue, cfg()) <<
'\n';
315 stream() <<
" " << innerItemVarStr <<
"->setMinValue(" << entry->min <<
");\n";
319 stream() <<
" " << innerItemVarStr <<
"->setMaxValue(" << entry->max <<
");\n";
322 if (cfg().setUserTexts) {
323 stream() << userTextsFunctions(entry, cfg());
326 if (cfg().allNotifiers || cfg().notifiers.contains(entry->name)) {
327 stream() <<
" " << itemVarStr <<
"->setWriteFlags(KConfigBase::Notify);\n";
330 for (
const CfgEntry::Choice &choice : std::as_const(entry->choices.choices)) {
331 if (!choice.val.isEmpty()) {
332 stream() <<
" " << innerItemVarStr <<
"->setValueForChoice(QStringLiteral( \"" << choice.name <<
"\" ), QStringLiteral( \"" << choice.val
337 if (!entry->parentGroup.
isEmpty()) {
341 stream() <<
" addItem( " << itemVarStr;
342 QString quotedName = entry->name;
343 addQuotes(quotedName);
344 if (quotedName != key) {
345 stream() <<
", QStringLiteral( \"" << entry->name <<
"\" )";
355void KConfigSourceGenerator::createIndexedEntry(
const CfgEntry *entry,
const QString &key)
357 for (
int i = 0; i <= entry->paramMax; i++) {
358 const QString argBracket = QStringLiteral(
"[%1]").
arg(i);
359 const QString innerItemVarStr = innerItemVar(entry, cfg()) + argBracket;
361 const QString defaultStr = !entry->paramDefaultValues[i].
isEmpty() ? entry->paramDefaultValues[i]
362 : !entry->defaultValue.
isEmpty() ? paramString(entry->defaultValue, entry, i)
363 : defaultValue(entry->
type);
365 if (!entry->signalList.
isEmpty()) {
366 stream() <<
" " << innerItemVarStr <<
" = " << newInnerItem(entry, paramString(key, entry, i), defaultStr, cfg(), argBracket) <<
'\n';
369 const QString itemVarStr = itemPath(entry, cfg()) + argBracket;
371 stream() <<
" " << itemVarStr <<
" = " << newItem(entry, paramString(key, entry, i), defaultStr, cfg(), argBracket) <<
'\n';
374 stream() <<
" " << innerItemVarStr <<
"->setMinValue(" << entry->min <<
");\n";
377 stream() <<
" " << innerItemVarStr <<
"->setMaxValue(" << entry->max <<
");\n";
380 for (
const CfgEntry::Choice &choice : std::as_const(entry->choices.choices)) {
381 if (!choice.val.isEmpty()) {
382 stream() <<
" " << innerItemVarStr <<
"->setValueForChoice(QStringLiteral( \"" << choice.name <<
"\" ), QStringLiteral( \"" << choice.val
387 if (cfg().setUserTexts) {
388 stream() << userTextsFunctions(entry, cfg(), itemVarStr, entry->paramName);
395 const bool isEnum = entry->paramType ==
QLatin1String(
"Enum");
398 QString paramName = entry->paramName;
400 stream() <<
" addItem( " << itemVarStr <<
", QStringLiteral( \"";
402 stream() <<
"\" ) );\n";
406void KConfigSourceGenerator::handleCurrentGroupChange(
const CfgEntry *entry)
408 if (entry->group == mCurrentGroup) {
413 static bool first =
true;
421 mCurrentGroup = entry->group;
423 if (!entry->parentGroup.
isEmpty()) {
425 if (!mConfigGroupList.
contains(parentGroup)) {
426 stream() <<
" KConfigGroup cg" << parentGroup <<
"(this->config(), " << paramString(entry->parentGroup, parseResult.parameters) <<
");\n";
427 mConfigGroupList << parentGroup;
430 if (!mConfigGroupList.
contains(currentGroup)) {
432 <<
".group(" << paramString(mCurrentGroup, parseResult.parameters) <<
");\n";
433 mConfigGroupList << currentGroup;
436 stream() <<
" setCurrentGroup( " << paramString(mCurrentGroup, parseResult.parameters) <<
" );";
441void KConfigSourceGenerator::doConstructor()
444 stream() << cfg().className <<
"::" << cfg().className <<
"(";
445 createConstructorParameterList();
448 createParentConstructorCall();
449 createInitializerList();
453 if (cfg().parentInConstructor) {
454 stream() <<
" setParent(parent);\n";
457 if (cfg().dpointer) {
458 stream() <<
" d = new " << cfg().className <<
"Private;\n";
463 if (cfg().singleton) {
464 stream() <<
" Q_ASSERT(!s_global" << cfg().className <<
"()->q);\n";
465 stream() <<
" s_global" << cfg().className <<
"()->q = this;\n";
468 if (!parseResult.signalList.
isEmpty()) {
471 stream() <<
" KConfigCompilerSignallingItem::NotifyFunction notifyFunction ="
472 <<
" static_cast<KConfigCompilerSignallingItem::NotifyFunction>(&" << cfg().className <<
"::itemChanged);\n";
477 for (
const auto *entry : std::as_const(parseResult.entries)) {
478 handleCurrentGroupChange(entry);
480 const QString key = paramString(entry->key, parseResult.parameters);
482 stream() << entry->code <<
'\n';
486 stream() << itemDeclaration(entry, cfg());
489 createNormalEntry(entry, key);
491 createIndexedEntry(entry, key);
498void KConfigSourceGenerator::createGetterDPointerMode(
const CfgEntry *entry)
501 if (cfg().useEnumTypes && entry->type ==
QLatin1String(
"Enum")) {
502 stream() << enumType(entry, cfg().globalEnums);
504 stream() << cppType(entry->type);
507 stream() <<
" " << getFunction(entry->name, cfg().className) <<
"(";
509 stream() <<
" " << cppType(entry->paramType) <<
" i ";
511 stream() <<
")" << Const() <<
'\n';
517 stream() <<
" " << memberAccessorBody(entry, cfg().globalEnums);
522void KConfigSourceGenerator::createImmutableGetterDPointerMode(
const CfgEntry *entry)
524 stream() << whitespace() <<
"";
526 <<
" " << immutableFunction(entry->name, cfg().className) <<
"(";
528 stream() <<
" " << cppType(entry->paramType) <<
" i ";
530 stream() <<
")" << Const() <<
'\n';
532 memberImmutableBody(entry, cfg().globalEnums);
537void KConfigSourceGenerator::createSetterDPointerMode(
const CfgEntry *entry)
540 if (!(cfg().allMutators || cfg().mutators.contains(entry->name))) {
544 stream() <<
"void " << setFunction(entry->name, cfg().className) <<
"( ";
546 stream() << cppType(entry->paramType) <<
" i, ";
549 if (cfg().useEnumTypes && entry->type ==
QLatin1String(
"Enum")) {
550 stream() << enumType(entry, cfg().globalEnums);
552 stream() << param(entry->type);
554 stream() <<
" v )\n";
559 memberMutatorBody(entry);
564void KConfigSourceGenerator::createItemGetterDPointerMode(
const CfgEntry *entry)
567 if (!cfg().itemAccessors) {
571 stream() << cfg().inherits <<
"::Item" << itemType(entry->type) <<
" *" << getFunction(entry->name, cfg().className) <<
"Item(";
573 stream() <<
" " << cppType(entry->paramType) <<
" i ";
577 stream() <<
" " << itemAccessorBody(entry, cfg());
581void KConfigSourceGenerator::doGetterSetterDPointerMode()
583 if (!cfg().dpointer) {
588 for (
const auto *entry : std::as_const(parseResult.entries)) {
589 createSetterDPointerMode(entry);
590 createGetterDPointerMode(entry);
591 createImmutableGetterDPointerMode(entry);
592 createItemGetterDPointerMode(entry);
597void KConfigSourceGenerator::createDefaultValueGetterSetter()
600 for (
const auto *entry : std::as_const(parseResult.entries)) {
605 if ((cfg().allDefaultGetters || cfg().defaultGetters.contains(n)) && !entry->defaultValue.
isEmpty()) {
606 stream() << cppType(t) <<
" " << getDefaultFunction(n, cfg().className) <<
"_helper(";
608 stream() <<
" " << cppType(entry->paramType) <<
" i ";
610 stream() <<
")" << Const() <<
'\n';
612 stream() << memberGetDefaultBody(entry) <<
'\n';
619void KConfigSourceGenerator::createDestructor()
621 stream() << cfg().className <<
"::~" << cfg().className <<
"()\n";
623 if (cfg().dpointer) {
624 stream() <<
" delete d;\n";
626 if (cfg().singleton) {
628 stream() <<
" if (" << qgs <<
".exists() && !" << qgs <<
".isDestroyed()) {\n";
629 stream() <<
" " << qgs <<
"()->q = nullptr;\n";
636void KConfigSourceGenerator::createNonModifyingSignalsHelper()
638 if (!parseResult.hasNonModifySignals) {
641 stream() <<
"bool " << cfg().className <<
"::"
644 stream() <<
" const bool res = " << cfg().inherits <<
"::usrSave();\n";
645 stream() <<
" if (!res) return false;\n\n";
646 for (
const Signal &signal : std::as_const(parseResult.signalList)) {
651 stream() <<
" if (" << varPath(QStringLiteral(
"settingsChanged"), cfg()) <<
".contains(" << signalEnumName(signal.name) <<
"))\n";
652 stream() <<
" Q_EMIT " << signal.name <<
"(";
653 auto it = signal.arguments.cbegin();
654 const auto itEnd = signal.arguments.cend();
655 while (it != itEnd) {
656 Param argument = *it;
658 if (cfg().useEnumTypes && argument.type ==
QLatin1String(
"Enum")) {
659 for (
int i = 0, end = parseResult.entries.
count(); i < end; ++i) {
660 if (parseResult.entries.
at(i)->name == argument.name) {
661 stream() <<
"static_cast<" << enumType(parseResult.entries.
at(i), cfg().globalEnums) <<
">(";
667 stream() << varPath(argument.name, cfg());
679 stream() <<
" " << varPath(QStringLiteral(
"settingsChanged"), cfg()) <<
".clear();\n";
680 stream() <<
" return true;\n";
684void KConfigSourceGenerator::createSignalFlagsHandler()
686 if (parseResult.signalList.
isEmpty()) {
691 stream() <<
"void " << cfg().className <<
"::"
692 <<
"itemChanged(quint64 signalFlag) {\n";
693 if (parseResult.hasNonModifySignals) {
694 stream() <<
" " << varPath(QStringLiteral(
"settingsChanged"), cfg()) <<
".insert(signalFlag);\n";
697 if (!parseResult.signalList.
isEmpty()) {
701 bool modifySignalsWritten =
false;
702 for (
const Signal &signal : std::as_const(parseResult.signalList)) {
704 if (!modifySignalsWritten) {
705 stream() <<
" switch (signalFlag) {\n";
706 modifySignalsWritten =
true;
708 stream() <<
" case " << signalEnumName(signal.name) <<
":\n";
709 stream() <<
" Q_EMIT " << signal.name <<
"();\n";
710 stream() <<
" break;\n";
713 if (modifySignalsWritten) {
Configuration Compiler Configuration.
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
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