aboutsummaryrefslogtreecommitdiff
path: root/src/kconfig_compiler
diff options
context:
space:
mode:
authorTomaz Canabrava <tcanabrava@kde.org>2020-01-17 10:03:43 +0000
committerTomaz Canabrava <tcanabrava@kde.org>2020-01-17 10:03:43 +0000
commit5f8c2ce63499d05dfb4753eb1acc21dccf21d434 (patch)
treefed718a3c8f4c4974411d612a79c4125ae3fffd8 /src/kconfig_compiler
parent98c32e29f50465d4d4e16bafdf0491edbfb422b0 (diff)
downloadkconfig-5f8c2ce63499d05dfb4753eb1acc21dccf21d434.tar.gz
kconfig-5f8c2ce63499d05dfb4753eb1acc21dccf21d434.tar.bz2
Revert "WIP: Refactor KConfigXT"
This reverts commit 98c32e29f50465d4d4e16bafdf0491edbfb422b0. This broke kdevelop and kmymoney. I'm workin on the fixes and more unittests for them.
Diffstat (limited to 'src/kconfig_compiler')
-rw-r--r--src/kconfig_compiler/CMakeLists.txt9
-rw-r--r--src/kconfig_compiler/KCFGXmlParser.cpp564
-rw-r--r--src/kconfig_compiler/KCFGXmlParser.h82
-rw-r--r--src/kconfig_compiler/KConfigCodeGeneratorBase.cpp276
-rw-r--r--src/kconfig_compiler/KConfigCodeGeneratorBase.h118
-rw-r--r--src/kconfig_compiler/KConfigCommonStructs.h195
-rw-r--r--src/kconfig_compiler/KConfigHeaderGenerator.cpp612
-rw-r--r--src/kconfig_compiler/KConfigHeaderGenerator.h78
-rw-r--r--src/kconfig_compiler/KConfigSourceGenerator.cpp657
-rw-r--r--src/kconfig_compiler/KConfigSourceGenerator.h86
-rw-r--r--src/kconfig_compiler/KConfigXTParameters.cpp100
-rw-r--r--src/kconfig_compiler/KConfigXTParameters.h81
-rw-r--r--src/kconfig_compiler/kconfig_compiler.cpp2208
13 files changed, 2089 insertions, 2977 deletions
diff --git a/src/kconfig_compiler/CMakeLists.txt b/src/kconfig_compiler/CMakeLists.txt
index 3543dfa2..dc0a08db 100644
--- a/src/kconfig_compiler/CMakeLists.txt
+++ b/src/kconfig_compiler/CMakeLists.txt
@@ -1,13 +1,6 @@
-set(kconfig_compiler_SRCS
- KConfigXTParameters.cpp
- KConfigCodeGeneratorBase.cpp
- KConfigHeaderGenerator.cpp
- KConfigSourceGenerator.cpp
- KCFGXmlParser.cpp
- kconfig_compiler.cpp
-)
+set(kconfig_compiler_SRCS kconfig_compiler.cpp)
add_executable(kconfig_compiler ${kconfig_compiler_SRCS})
diff --git a/src/kconfig_compiler/KCFGXmlParser.cpp b/src/kconfig_compiler/KCFGXmlParser.cpp
deleted file mode 100644
index 214335c3..00000000
--- a/src/kconfig_compiler/KCFGXmlParser.cpp
+++ /dev/null
@@ -1,564 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 "KCFGXmlParser.h"
-#include "KConfigXTParameters.h"
-
-#include <QDomAttr>
-#include <QDomElement>
-#include <QDomNode>
-#include <QFile>
-#include <QList>
-#include <QStringList>
-#include <QTextStream>
-
-namespace
-{
-QTextStream cout(stdout);
-QTextStream cerr(stderr);
-}
-
-//TODO: Move preprocessDefault to Header / CPP implementation.
-// it makes no sense for a parser to process those values and generate code.
-
-static void preProcessDefault(QString &defaultValue, const QString &name,
- const QString &type,
- const CfgEntry::Choices &choices,
- QString &code, const KConfigXTParameters &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<QUrl> 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()) {
- const QRegularExpression colorRe(QRegularExpression::anchoredPattern(
- QStringLiteral("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?")));
-
- if (colorRe.match(defaultValue).hasMatch()) {
- defaultValue = QLatin1String("QColor( ") + defaultValue + QLatin1String(" )");
- } else {
- defaultValue = QLatin1String("QColor( \"") + defaultValue + QLatin1String("\" )");
- }
-
- } else if (type == QLatin1String("Enum")) {
- QList<CfgEntry::Choice>::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<int> 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;
- }
-}
-
-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;
-}
-
-void KCFGXmlParser::readParameterFromEntry(CfgEntry &readEntry, const QDomElement &e)
-{
- readEntry.param = e.attribute(QStringLiteral("name"));
- readEntry.paramType = e.attribute(QStringLiteral("type"));
-
- if (readEntry.param.isEmpty()) {
- cerr << "Parameter must have a name: " << dumpNode(e) << endl;
- exit (1);
- }
-
- if (readEntry.paramType.isEmpty()) {
- cerr << "Parameter must have a type: " << dumpNode(e) << endl;
- exit(1);
- }
-
- if ((readEntry.paramType == QLatin1String("Int")) || (readEntry.paramType == QLatin1String("UInt"))) {
- bool ok;
- readEntry.paramMax = e.attribute(QStringLiteral("max")).toInt(&ok);
- if (!ok) {
- cerr << "Integer parameter must have a maximum (e.g. max=\"0\"): " << dumpNode(e) << endl;
- exit(1);
- }
- } else if (readEntry.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")) {
- readEntry.paramValues.append(e3.text());
- }
- }
- break;
- }
- }
- if (readEntry.paramValues.isEmpty()) {
- cerr << "No values specified for parameter '" << readEntry.param << "'." << endl;
- exit(1);
- }
- readEntry.paramMax = readEntry.paramValues.count() - 1;
- } else {
- cerr << "Parameter '" << readEntry.param << "' has type " << readEntry.paramType
- << " but must be of type int, uint or Enum." << endl;
- exit(1);
- }
-}
-
-bool KCFGXmlParser::hasDefaultCode(CfgEntry &readEntry, const QDomElement &element)
-{
- for (QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) {
- if (e.attribute(QStringLiteral("param")).isEmpty()) {
- if (e.attribute(QStringLiteral("code")) == QLatin1String("true")) {
- return true;
- }
- }
- }
- return false;
-}
-
-
-void KCFGXmlParser::readChoicesFromEntry(CfgEntry &readEntry, const QDomElement &e)
-{
- QList<CfgEntry::Choice> chlist;
- for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) {
- if (e2.tagName() != QLatin1String("choice")) {
- continue;
- }
- CfgEntry::Choice choice;
- choice.name = e2.attribute(QStringLiteral("name"));
- if (choice.name.isEmpty()) {
- cerr << "Tag <choice> 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);
- }
-
- QString name = e.attribute(QStringLiteral("name"));
- QString prefix = e.attribute(QStringLiteral("prefix"));
-
- readEntry.choices = CfgEntry::Choices(chlist, name, prefix);
-}
-
-void KCFGXmlParser::readGroupElements(CfgEntry &readEntry, const QDomElement &element)
-{
- for (QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) {
- QString tag = e.tagName();
- if (tag == QLatin1String("label")) {
- readEntry.label = e.text();
- readEntry.labelContext = e.attribute(QStringLiteral("context"));
- } else if (tag == QLatin1String("tooltip")) {
- readEntry.toolTip = e.text();
- readEntry.toolTipContext = e.attribute(QStringLiteral("context"));
- } else if (tag == QLatin1String("whatsthis")) {
- readEntry.whatsThis = e.text();
- readEntry.whatsThisContext = e.attribute(QStringLiteral("context"));
- } else if (tag == QLatin1String("min")) {
- readEntry.min = e.text();
- } else if (tag == QLatin1String("max")) {
- readEntry.max = e.text();
- } else if (tag == QLatin1String("code")) {
- readEntry.code = e.text();
- } else if (tag == QLatin1String("parameter")) {
- readParameterFromEntry(readEntry, e);
- } else if (tag == QLatin1String("default")) {
- if (e.attribute(QStringLiteral("param")).isEmpty()) {
- readEntry.defaultValue = e.text();
- }
- } else if (tag == QLatin1String("choices")) {
- readChoicesFromEntry(readEntry, e);
- } else if (tag == QLatin1String("emit")) {
- Signal signal;
- signal.name = e.attribute(QStringLiteral("signal"));
- readEntry.signalList.append(signal);
- }
- }
-}
-
-void KCFGXmlParser::createChangedSignal(CfgEntry &readEntry)
-{
- if (cfg.generateProperties && (cfg.allMutators || cfg.mutators.contains(readEntry.name))) {
- Signal s;
- s.name = changeSignalName(readEntry.name);
- s.modify = true;
- readEntry.signalList.append(s);
- }
-}
-
-void KCFGXmlParser::validateNameAndKey(CfgEntry &readEntry, const QDomElement &element)
-{
- bool nameIsEmpty = readEntry.name.isEmpty();
- if (nameIsEmpty && readEntry.key.isEmpty()) {
- cerr << "Entry must have a name or a key: " << dumpNode(element) << endl;
- exit (1);
- }
-
- if (readEntry.key.isEmpty()) {
- readEntry.key = readEntry.name;
- }
-
- if (nameIsEmpty) {
- readEntry.name = readEntry.key;
- readEntry.name.remove(QLatin1Char(' '));
- } else if (readEntry.name.contains(QLatin1Char(' '))) {
- cout << "Entry '" << readEntry.name << "' contains spaces! <name> elements can not contain spaces!" << endl;
- readEntry.name.remove(QLatin1Char(' '));
- }
-
- if (readEntry.name.contains(QStringLiteral("$("))) {
- if (readEntry.param.isEmpty()) {
- cerr << "Name may not be parameterized: " << readEntry.name << endl;
- exit (1);
- }
- } else {
- if (!readEntry.param.isEmpty()) {
- cerr << "Name must contain '$(" << readEntry.param << ")': " << readEntry.name << endl;
- exit (1);
- }
- }
-}
-
-void KCFGXmlParser::readParamDefaultValues(CfgEntry &readEntry, const QDomElement &element)
-{
- if (readEntry.param.isEmpty()) {
- return;
- }
- // Adjust name
- readEntry.paramName = readEntry.name;
-
- readEntry.name.remove(QStringLiteral("$(") + readEntry.param + QLatin1Char(')'));
- // Lookup defaults for indexed entries
- for (int i = 0; i <= readEntry.paramMax; i++) {
- readEntry.paramDefaultValues.append(QString());
- }
-
- for (QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) {
- QString tag = e.tagName();
- if (tag != QLatin1String("default")) {
- continue;
- }
- QString index = e.attribute(QStringLiteral("param"));
- if (index.isEmpty()) {
- continue;
- }
-
- bool ok;
- int i = index.toInt(&ok);
- if (!ok) {
- i = readEntry.paramValues.indexOf(index);
- if (i == -1) {
- cerr << "Index '" << index << "' for default value is unknown." << endl;
- exit (1);
- }
- }
-
- if ((i < 0) || (i > readEntry.paramMax)) {
- cerr << "Index '" << i << "' for default value is out of range [0, " << readEntry.paramMax << "]." << endl;
- exit (1);
- }
-
- QString tmpDefaultValue = e.text();
-
- if (e.attribute(QStringLiteral("code")) != QLatin1String("true")) {
- preProcessDefault(tmpDefaultValue, readEntry.name, readEntry.type, readEntry.choices, readEntry.code, cfg);
- }
-
- readEntry.paramDefaultValues[i] = tmpDefaultValue;
- }
-}
-
-CfgEntry *KCFGXmlParser::parseEntry(const QString &group, const QDomElement &element)
-{
- CfgEntry readEntry;
- readEntry.type = element.attribute(QStringLiteral("type"));
- readEntry.name = element.attribute(QStringLiteral("name"));
- readEntry.key = element.attribute(QStringLiteral("key"));
- readEntry.hidden = element.attribute(QStringLiteral("hidden")) == QLatin1String("true");;
- readEntry.group = group;
-
- const bool nameIsEmpty = readEntry.name.isEmpty();
-
- readGroupElements(readEntry, element);
-
- createChangedSignal(readEntry);
- validateNameAndKey(readEntry, element);
-
- if (readEntry.label.isEmpty()) {
- readEntry.label = readEntry.key;
- }
-
- if (readEntry.type.isEmpty()) {
- readEntry.type = QStringLiteral("String"); // XXX : implicit type might be bad
- }
-
- readParamDefaultValues(readEntry, element);
-
- if (!mValidNameRegexp.match(readEntry.name).hasMatch()) {
- if (nameIsEmpty)
- cerr << "The key '" << readEntry.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 '" << readEntry.name << "' is not a valid name for an entry." << endl;
- }
- exit (1);
- }
-
- if (mAllNames.contains(readEntry.name)) {
- if (nameIsEmpty)
- cerr << "The key '" << readEntry.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 '" << readEntry.name << "' is not unique." << endl;
- }
- exit (1);
- }
-
- mAllNames.append(readEntry.name);
-
- if (!hasDefaultCode(readEntry, element)) {
- // TODO: Move all the options to CfgEntry.
- preProcessDefault(readEntry.defaultValue, readEntry.name, readEntry.type, readEntry.choices, readEntry.code, cfg);
- }
-
- // TODO: Try to Just return the CfgEntry we populated instead of
- // creating another one to fill the code.
- CfgEntry *result = new CfgEntry();
- result->group = readEntry.group;
- result->type = readEntry.type;
- result->key = readEntry.key;
- result->name = readEntry.name;
- result->labelContext = readEntry.labelContext;
- result->label = readEntry.label;
- result->toolTipContext = readEntry.toolTipContext;
- result->toolTip = readEntry.toolTip;
- result->whatsThisContext = readEntry.whatsThisContext;
- result->whatsThis = readEntry.whatsThis;
- result->code = readEntry.code;
- result->defaultValue = readEntry.defaultValue;
- result->choices = readEntry.choices;
- result->signalList = readEntry.signalList;
- result->hidden = readEntry.hidden;
-
- if (!readEntry.param.isEmpty()) {
- result->param = readEntry.param;
- result->paramName = readEntry.paramName;
- result->paramType = readEntry.paramType;
- result->paramValues = readEntry.paramValues;
- result->paramDefaultValues = readEntry.paramDefaultValues;
- result->paramMax = readEntry.paramMax;
- }
- result->min = readEntry.min;
- result->max = readEntry.max;
-
- return result;
-}
-
-// TODO: Change the name of the config variable.
-KCFGXmlParser::KCFGXmlParser(const KConfigXTParameters &cfg, const QString& inputFileName)
- : cfg(cfg), mInputFileName(inputFileName)
-{
- mValidNameRegexp.setPattern(QRegularExpression::anchoredPattern(QStringLiteral("[a-zA-Z_][a-zA-Z0-9_]*")));
-}
-
-void KCFGXmlParser::start()
-{
- QFile input(mInputFileName);
- 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 " << mInputFileName << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl;
- exit (1);
- }
-
- QDomElement cfgElement = doc.documentElement();
- if (cfgElement.isNull()) {
- cerr << "No document in kcfg file" << endl;
- exit (1);
- }
-
- for (QDomElement element = cfgElement.firstChildElement(); !element.isNull(); element = element.nextSiblingElement()) {
- QString tag = element.tagName();
-
- if (tag == QLatin1String("include")) {
- readIncludeTag(element);
- } else if (tag == QLatin1String("kcfgfile")) {
- readKcfgfileTag(element);
- } else if (tag == QLatin1String("group")) {
- readGroupTag(element);
- } else if (tag == QLatin1String("signal")) {
- readSignalTag(element);
- }
- }
-}
-
-ParseResult KCFGXmlParser::getParseResult() const
-{
- return mParseResult;
-}
-
-void KCFGXmlParser::readIncludeTag(const QDomElement &e)
-{
- QString includeFile = e.text();
- if (!includeFile.isEmpty()) {
- mParseResult.includes.append(includeFile);
- }
-}
-
-void KCFGXmlParser::readGroupTag(const QDomElement &e)
-{
- QString group = e.attribute(QStringLiteral("name"));
- if (group.isEmpty()) {
- cerr << "Group without name" << endl;
- exit (1);
- }
-
- for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) {
- if (e2.tagName() != QLatin1String("entry")) {
- continue;
- }
- CfgEntry *entry = parseEntry(group, e2);
- if (entry) {
- mParseResult.entries.append(entry);
- } else {
- cerr << "Can not parse entry." << endl;
- exit (1);
- }
- }
-}
-
-void KCFGXmlParser::readKcfgfileTag(const QDomElement &e)
-{
- mParseResult.cfgFileName = e.attribute(QStringLiteral("name"));
- mParseResult.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");
- }
- mParseResult.parameters.append(p);
- }
- }
-}
-
-void KCFGXmlParser::readSignalTag(const QDomElement &e)
-{
- QString signalName = e.attribute(QStringLiteral("name"));
- if (signalName.isEmpty()) {
- cerr << "Signal without name." << endl;
- exit (1);
- }
- Signal theSignal;
- theSignal.name = signalName;
-
- for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) {
- if (e2.tagName() == QLatin1String("argument")) {
- Param argument;
- argument.type = e2.attribute(QStringLiteral("type"));
- if (argument.type.isEmpty()) {
- cerr << "Signal argument without type." << endl;
- exit (1);
- }
- argument.name= e2.text();
- theSignal.arguments.append(argument);
- } else if (e2.tagName() == QLatin1String("label")) {
- theSignal.label = e2.text();
- }
- }
-
- mParseResult.signalList.append(theSignal);
-}
diff --git a/src/kconfig_compiler/KCFGXmlParser.h b/src/kconfig_compiler/KCFGXmlParser.h
deleted file mode 100644
index 8c85d878..00000000
--- a/src/kconfig_compiler/KCFGXmlParser.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 KCFGXMLPARSER_H
-#define KCFGXMLPARSER_H
-
-#include <QDomDocument>
-#include <QString>
-#include <QRegularExpression>
-
-#include "KConfigCommonStructs.h"
-#include "KConfigXTParameters.h"
-
-/* This parses the contents of a Xml file into a ParseResult Structure,
- * It also fails hard:
- * If start() succeeds, you can use the result,
- * if start() fails, the program aborts with an error message so there's
- * no possibility of generating incorrect code information.
- */
-class KCFGXmlParser {
-public:
- KCFGXmlParser(const KConfigXTParameters &cfg, const QString& inputFileName);
-
- // Start the parser and reads the contents of the inputFileName into the ParseResult Structure
- void start();
-
- // Get the result of the parse
- ParseResult getParseResult() const;
-
-private:
- // creates a `somethingChanged` signal for every property
- void createChangedSignal(CfgEntry &readEntry);
-
- void validateNameAndKey(CfgEntry &readEntry, const QDomElement &element);
-
- // TODO: Use std::optional and CfgEntry (without heap allocation) for this function
- // *or* fail hard if the parse fails.
- CfgEntry *parseEntry(const QString &group, const QDomElement &element);
-
- // Steps
- void readIncludeTag(const QDomElement &element);
- void readGroupTag(const QDomElement &element);
- void readKcfgfileTag(const QDomElement &element);
- void readSignalTag(const QDomElement &element);
-
- // Those are the Entries in the Xml, that represent a parameter within the <group> </group> tag.
- void readParameterFromEntry(CfgEntry &entry, const QDomElement &element);
- bool hasDefaultCode(CfgEntry &entry, const QDomElement &element);
- void readChoicesFromEntry(CfgEntry &entry, const QDomElement &element);
- void readGroupElements(CfgEntry &entry, const QDomElement &element);
- void readParamDefaultValues(CfgEntry &entry, const QDomElement &element);
-
-private:
- ParseResult mParseResult;
- KConfigXTParameters cfg;
- QString mInputFileName;
- QStringList mAllNames;
- QRegularExpression mValidNameRegexp;
-};
-
-#endif
diff --git a/src/kconfig_compiler/KConfigCodeGeneratorBase.cpp b/src/kconfig_compiler/KConfigCodeGeneratorBase.cpp
deleted file mode 100644
index 024af19c..00000000
--- a/src/kconfig_compiler/KConfigCodeGeneratorBase.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 "KConfigCodeGeneratorBase.h"
-#include "KConfigXTParameters.h"
-#include "KConfigCommonStructs.h"
-
-#include <QTextStream>
-#include <QLatin1Char>
-#include <QFileInfo>
-
-#include <ostream>
-#include <QDebug>
-
-using std::endl;
-
-namespace
-{
-QTextStream cout(stdout);
-QTextStream cerr(stderr);
-}
-
-KConfigCodeGeneratorBase::KConfigCodeGeneratorBase(
- const QString& inputFile,
- const QString& baseDir,
- const QString& fileName,
- const KConfigXTParameters &parameters,
- ParseResult &parseResult)
- : inputFile(inputFile), baseDir(baseDir), fileName(fileName), cfg(parameters), parseResult(parseResult)
-{
- file.setFileName(fileName);
- if (!file.open(QIODevice::WriteOnly)) {
- cerr << "Can not open '" << fileName << "for writing." << endl;
- exit(1);
- }
- stream.setDevice(&file);
- stream.setCodec("utf-8");
-
- if (cfg.staticAccessors) {
- This = QStringLiteral("self()->");
- } else {
- Const = QStringLiteral(" const");
- }
-}
-
-KConfigCodeGeneratorBase::~KConfigCodeGeneratorBase()
-{
- save();
-}
-
-void KConfigCodeGeneratorBase::save()
-{
- file.close();
-}
-
-void KConfigCodeGeneratorBase::indent()
-{
- if (indentLevel >= 4) {
- indentLevel += 2;
- } else {
- indentLevel += 4;
- }
-}
-
-void KConfigCodeGeneratorBase::unindent()
-{
- if (indentLevel > 4) {
- indentLevel -= 2;
- } else {
- indentLevel -= 4;
- }
-}
-
-QString KConfigCodeGeneratorBase::whitespace()
-{
- QString spaces;
- for (int i = 0; i < indentLevel; i++) {
- spaces.append(QLatin1Char(' '));
- }
- return spaces;
-}
-
-void KConfigCodeGeneratorBase::startScope()
-{
- stream << whitespace() << QLatin1Char('{');
- stream << endl;
- indent();
-}
-
-void KConfigCodeGeneratorBase::endScope(ScopeFinalizer finalizer)
-{
- unindent();
- stream << whitespace() << QLatin1Char('}');
- if (finalizer == ScopeFinalizer::Semicolon) {
- stream << ';';
- }
- stream << endl;
-}
-
-void KConfigCodeGeneratorBase::start()
-{
- const QString fileName = QFileInfo(inputFile).fileName();
- stream << "// This file is generated by kconfig_compiler_kf5 from " << fileName << ".kcfg" << "." << endl;
- stream << "// All changes you do to this file will be lost." << endl;
-}
-
-void KConfigCodeGeneratorBase::addHeaders(const QStringList& headerList)
-{
- for (auto include : qAsConst(headerList)) {
- if (include.startsWith(QLatin1Char('"'))) {
- stream << "#include " << include << endl;
- } else {
- stream << "#include <" << include << ">" << endl;
- }
- }
-}
-
-// adds as many 'namespace foo {' lines to p_out as
-// there are namespaces in p_ns
-void KConfigCodeGeneratorBase::beginNamespaces()
-{
- if (!cfg.nameSpace.isEmpty()) {
- for (const QString &ns : cfg.nameSpace.split(QStringLiteral("::"))) {
- stream << "namespace " << ns << " {" << endl;
- }
- stream << endl;
- }
-}
-
-// adds as many '}' lines to p_out as
-// there are namespaces in p_ns
-void KConfigCodeGeneratorBase::endNamespaces()
-{
- if (!cfg.nameSpace.isEmpty()) {
- stream << endl;
- const int namespaceCount = cfg.nameSpace.count(QStringLiteral("::")) + 1;
- for (int i = 0; i < namespaceCount; ++i) {
- stream << "}" << endl;
- }
- }
-}
-
-// returns the member accesor implementation
-// which should go in the h file if inline
-// or the cpp file if not inline
-QString KConfigCodeGeneratorBase::memberAccessorBody(const CfgEntry *e, bool globalEnums) const
-{
- 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;
-}
-
-void KConfigCodeGeneratorBase::createIfSetLogic(const CfgEntry *e, const QString &varExpression)
-{
- const QString n = e->name;
- const QString t = e->type;
- const bool hasBody = !e->signalList.empty() || cfg.generateProperties;
-
- stream << whitespace() << "if (";
- if (hasBody) {
- stream << "v != " << varExpression << " && ";
- }
- stream << "!" << This << "isImmutable( QStringLiteral( \"";
- if (!e->param.isEmpty()) {
- QString paramName = e->paramName;
-
- stream << paramName.replace(QStringLiteral("$(") + e->param + QStringLiteral(")"), QLatin1String("%1")) << "\" ).arg( ";
- if (e->paramType == QLatin1String("Enum")) {
- stream << "QLatin1String( ";
-
- if (cfg.globalEnums) {
- stream << enumName(e->param) << "ToString[i]";
- } else {
- stream << enumName(e->param) << "::enumToString[i]";
- }
-
- stream << " )";
- } else {
- stream << "i";
- }
- stream << " )";
- } else {
- stream << n << "\" )";
- }
- stream << " ))";
-}
-
-void KConfigCodeGeneratorBase::memberMutatorBody(const CfgEntry *e)
-{
- QString n = e->name;
- QString t = e->type;
-
- // HACK: Don't open '{' manually, use startScope / endScope to automatically handle whitespace indentation.
- if (!e->min.isEmpty()) {
- if (e->min != QLatin1String("0") || !isUnsigned(t)) { // skip writing "if uint<0" (#187579)
- stream << whitespace() << "if (v < " << e->min << ")" << endl;
- stream << whitespace() << "{" << endl;
- stream << whitespace(); addDebugMethod(stream, cfg, n);
- stream << ": value \" << v << \" is less than the minimum value of " << e->min << "\";" << endl;
- stream << whitespace() << " v = " << e->min << ";" << endl;
- stream << whitespace() << "}" << endl;
- }
- }
-
- if (!e->max.isEmpty()) {
- stream << endl;
- stream << whitespace() << "if (v > " << e->max << ")" << endl;
- stream << whitespace() << "{" << endl;
- stream << whitespace(); addDebugMethod(stream, cfg, n);
- stream << ": value \" << v << \" is greater than the maximum value of " << e->max << "\";" << endl;
- stream << whitespace() << " v = " << e->max << ";" << endl;
- stream << whitespace() << "}" << endl << endl;
- }
-
- const QString varExpression = This + varPath(n, cfg) + (e->param.isEmpty() ? QString() : QStringLiteral("[i]"));
-
- // TODO: Remove this `hasBody` logic, always use an '{' for the if.
- const bool hasBody = !e->signalList.empty() || cfg.generateProperties;
-
- // This call creates an `if (someTest ...) that's just to long to throw over the code.
- createIfSetLogic(e, varExpression);
- stream << (hasBody ? " {" : "") << endl;
- stream << whitespace() << " " << varExpression << " = v;" << endl;
-
- const auto listSignal = e->signalList;
- for (const Signal &signal : qAsConst(listSignal)) {
- if (signal.modify) {
- stream << whitespace() << " Q_EMIT " << This << signal.name << "();" << endl;
- } else {
- stream << whitespace() << " " << This << varPath(QStringLiteral("settingsChanged"), cfg)
- << " |= " << signalEnumName(signal.name) << ";" << endl;
- }
- }
- if (hasBody) {
- stream << whitespace() << "}" << endl;
- }
-}
diff --git a/src/kconfig_compiler/KConfigCodeGeneratorBase.h b/src/kconfig_compiler/KConfigCodeGeneratorBase.h
deleted file mode 100644
index fdf3b7e3..00000000
--- a/src/kconfig_compiler/KConfigCodeGeneratorBase.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- This file is part of KDE.
-
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 KCONFIGCODEGENERATORBASE_H
-#define KCONFIGCODEGENERATORBASE_H
-
-#include <QString>
-#include <QTextStream>
-#include <QFile>
-#include <QVector>
-
-#include "KConfigXTParameters.h"
-
-class CfgEntry;
-struct ParseResult;
-
-/* This class manages the base of writing a C - Based code */
-class KConfigCodeGeneratorBase {
-public:
- enum ScopeFinalizer {None, Semicolon};
-
- KConfigCodeGeneratorBase(
- const QString& inputFileName, // The kcfg file
- const QString& baseDir, // where we should store the generated file
- const QString& fileName, // the name of the generated file
- const KConfigXTParameters &parameters, // parameters passed to the generator
- ParseResult &parseResult // The pre processed configuration entries
- );
- virtual ~KConfigCodeGeneratorBase();
-
- // iterates over the header list adding an #include directive.
- void addHeaders(const QStringList& header);
-
- // Create all the namespace indentation levels based on the parsed result and parameters */
- void beginNamespaces();
-
- // Closes all the namespaces adding lines with single '}'
- void endNamespaces();
-
- // Add the correct amount of whitespace in the code.
- QString whitespace();
-
- // start a block scope `{` and increase indentation level.
- void endScope(ScopeFinalizer finalizer = None);
-
- // end a block scope `}` and decrease indentation level.
- void startScope();
-
- // start writing to the output file
- virtual void start();
-
- // save the result on the disk
- void save();
-
- // Code Implementations
- // Implements the `Get` methods for the CfgEntry
- // TODO: write to the stream directly without returning a QString.
- QString memberAccessorBody(const CfgEntry *e, bool globalEnums) const;
-
- // Implements the `Set` methods for the CfgEntry
- void memberMutatorBody(const CfgEntry *e);
-
- // This is the code that creates the logic for the Setter / Mutator.
- // It *just* creates the if test, no body. The reason is that just
- // the if test was more than 20 lines of code and hard to understand
- // what was happening in a bigger function.
- void createIfSetLogic(const CfgEntry *e, const QString &varExpression);
-
-protected:
- /* advance the number of spaces for the indentation level */
- void indent();
-
- /* reduce the number of spaces for the indentation level */
- void unindent();
-
- QString inputFile; // the base file name, input file is based on this.
-
- QString baseDir; // Where we are going to save the file
- QString fileName; // The file name
-
- const KConfigXTParameters &cfg; // The parameters passed via the kcfgc file
- ParseResult &parseResult; // the result of the parsed kcfg file
- QTextStream stream; // the stream that operates in the file to write data.
- QFile file; // The file handler.
-
- // Special access to `this->` and `const` thru the code.
- QString This;
- QString Const;
-
-private:
- int indentLevel = 0;
-};
-
-#endif
diff --git a/src/kconfig_compiler/KConfigCommonStructs.h b/src/kconfig_compiler/KConfigCommonStructs.h
deleted file mode 100644
index c78c7b76..00000000
--- a/src/kconfig_compiler/KConfigCommonStructs.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 KCONFIGCOMMONSTRUCTS_H
-#define KCONFIGCOMMONSTRUCTS_H
-
-#include <QString>
-#include <QVector>
-#include <QList>
-
-#include "KConfigXTParameters.h"
-
-struct Param
-{
- QString name;
- QString type;
-};
-
-struct Signal
-{
- QString name;
- QString label;
- QList<Param> arguments;
- bool modify = false;
-};
-
-class CfgEntry
-{
-public:
- struct Choice {
- QString name;
- QString context;
- QString label;
- QString toolTip;
- QString whatsThis;
- };
- class Choices
- {
- public:
- Choices() {}
- Choices(const QList<Choice> &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<Choice> choices;
- const QString &name() const
- {
- return mName;
- }
- const QString &externalQualifier() const
- {
- return mExternalQual;
- }
- bool external() const
- {
- return !mExternalQual.isEmpty();
- }
- private:
- QString mName;
- QString mExternalQual;
- };
-
-public:
- QString group;
- QString type;
- QString key;
- QString name;
- QString labelContext;
- QString label;
- QString toolTipContext;
- QString toolTip;
- QString whatsThisContext;
- QString whatsThis;
- QString code;
- QString defaultValue;
- QString param;
- QString paramName;
- QString paramType;
- Choices choices;
- QList<Signal> signalList;
- QStringList paramValues;
- QStringList paramDefaultValues;
- int paramMax;
- bool hidden;
- QString min;
- QString max;
-};
-
-struct ParseResult {
- QString cfgFileName;
- bool cfgFileNameArg = false;
- QList<Param> parameters;
- QList<Signal> signalList;
- QStringList includes;
- QList<CfgEntry *> entries;
- bool hasNonModifySignals = false;
-};
-
-// TODO: Move those methods
-QString enumName(const QString &n);
-QString enumName(const QString &n, const CfgEntry::Choices &c);
-QString param(const QString &t);
-QString cppType(const QString &t);
-QString itemType(const QString &type);
-QString changeSignalName(const QString &n);
-
-QString enumType(const CfgEntry *e, bool globalEnums);
-
-QString getDefaultFunction(const QString &n, const QString &className = QString());
-QString setFunction(const QString &n, const QString &className = QString());
-QString getFunction(const QString &n, const QString &className = QString());
-
-QString itemAccessorBody(const CfgEntry *e, const KConfigXTParameters &cfg);
-QString signalEnumName(const QString &signalName);
-
-bool isUnsigned(const QString &type);
-
-// returns the name of an member variable
-// use itemPath to know the full path
-// like using d-> in case of dpointer
-QString varName(const QString &n, const KConfigXTParameters &cfg);
-
-QString varPath(const QString &n, const KConfigXTParameters &cfg);
-
-// returns the name of an item variable
-// use itemPath to know the full path
-// like using d-> in case of dpointer
-QString itemVar(const CfgEntry *e, const KConfigXTParameters &cfg);
-
-QString itemPath(const CfgEntry *e, const KConfigXTParameters &cfg);
-
-QString filenameOnly(const QString &path);
-
-QString itemDeclaration(const CfgEntry *e, const KConfigXTParameters &cfg);
-
-QString translatedString(
- const KConfigXTParameters &cfg,
- const QString &string,
- const QString &context = QString(),
- const QString &param = QString(),
- const QString &paramValue = QString());
-
-// TODO: Sanitize those functions.
-QString newItem(
- const CfgEntry* entry,
- const QString &key,
- const QString& defaultValue,
- const KConfigXTParameters &cfg,
- const QString &param = QString());
-
-QString userTextsFunctions(
- const CfgEntry *e,
- const KConfigXTParameters &cfg,
- QString itemVarStr = QString(),
- const QString &i = QString());
-
-QString paramString(const QString &s, const CfgEntry *e, int i);
-QString paramString(const QString &group, const QList<Param> &parameters);
-
-QString defaultValue(const QString &t);
-QString memberGetDefaultBody(const CfgEntry *e);
-QString literalString(const QString &s);
-QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c);
-
-void addQuotes(QString &s);
-void addDebugMethod(QTextStream &out, const KConfigXTParameters &cfg, const QString &n);
-
-#endif
diff --git a/src/kconfig_compiler/KConfigHeaderGenerator.cpp b/src/kconfig_compiler/KConfigHeaderGenerator.cpp
deleted file mode 100644
index 088f64e7..00000000
--- a/src/kconfig_compiler/KConfigHeaderGenerator.cpp
+++ /dev/null
@@ -1,612 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 "KConfigHeaderGenerator.h"
-#include "KConfigCommonStructs.h"
-
-#include <QTextStream>
-#include <QDebug>
-
-namespace
-{
-QTextStream cout(stdout);
-QTextStream cerr(stderr);
-}
-
-KConfigHeaderGenerator::KConfigHeaderGenerator(
- const QString& inputFile,
- const QString& baseDir,
- const KConfigXTParameters &cfg,
- ParseResult &parseResult)
- : KConfigCodeGeneratorBase(inputFile, baseDir, baseDir + cfg.baseName + QLatin1Char('.') + cfg.headerExtension, cfg, parseResult)
-{
-}
-
-void KConfigHeaderGenerator::start()
-{
- KConfigCodeGeneratorBase::start();
- startHeaderGuards();
- createHeaders();
-
- beginNamespaces();
-
- createForwardDeclarations();
-
- doClassDefinition();
-
- endNamespaces();
- endHeaderGuards();
-}
-
-void KConfigHeaderGenerator::doClassDefinition()
-{
- stream << "class " << cfg.visibility << cfg.className << " : public " << cfg.inherits << endl;
- startScope();
-
- // Add Q_OBJECT macro if the config need signals.
- if (!parseResult.signalList.isEmpty() || cfg.generateProperties) {
- stream << " Q_OBJECT" << endl;
- }
- stream << " public:" << endl;
- implementEnums();
- createConstructor();
- createDestructor();
-
- for (auto *entry : qAsConst(parseResult.entries)) {
- const QString n = entry->name;
- const QString t = entry->type;
-
- const QString returnType = (cfg.useEnumTypes && t == QLatin1String("Enum"))
- ? enumType(entry, cfg.globalEnums)
- : cppType(t);
-
- createSetters(entry);
- createProperties(entry, returnType);
- createGetters(entry, returnType);
- createDefaultValueMember(entry);
- createItemAcessors(entry, returnType);
- }
-
- createSignals();
- stream << " protected:" << endl;
- createSingleton();
-
- // TODO: Move those to functions too.
- if (parseResult.hasNonModifySignals) {
- stream << whitespace() << "bool usrSave() override;" << endl;
- }
-
- // Member variables
- if (!cfg.memberVariables.isEmpty() && cfg.memberVariables != QLatin1String("private") && cfg.memberVariables != QLatin1String("dpointer")) {
- stream << " " << cfg.memberVariables << ":" << endl;
- }
-
- // Class Parameters
- for (const auto &parameter : qAsConst(parseResult.parameters)) {
- stream << whitespace() << "" << cppType(parameter.type) << " mParam" << parameter.name << ";" << endl;
- }
-
- createNonDPointerHelpers();
- createDPointer();
-
- if (cfg.customAddons) {
- stream << whitespace() << "// Include custom additions" << endl;
- stream << whitespace() << "#include \"" << cfg.baseName << "_addons." << cfg.headerExtension << '"' << endl;
- }
-
- endScope(ScopeFinalizer::Semicolon);
-}
-
-void KConfigHeaderGenerator::createHeaders()
-{
- addHeaders(cfg.headerIncludes);
- if (cfg.headerIncludes.size()) {
- stream << endl;
- }
-
- if (!cfg.singleton && parseResult.parameters.isEmpty()) {
- addHeaders({QStringLiteral("qglobal.h")});
- }
-
- if (cfg.inherits == QLatin1String("KCoreConfigSkeleton")) {
- addHeaders({QStringLiteral("kcoreconfigskeleton.h")});
- } else {
- addHeaders({QStringLiteral("kconfigskeleton.h")});
- }
-
- addHeaders({QStringLiteral("QCoreApplication"), QStringLiteral("QDebug")});
- stream << endl;
-
- addHeaders(parseResult.includes);
- if (parseResult.includes.size()) {
- stream << endl;
- }
-}
-
-void KConfigHeaderGenerator::startHeaderGuards()
-{
- const bool hasNamespace = !cfg.nameSpace.isEmpty();
- const QString namespaceName = QString(QString(cfg.nameSpace).replace(QLatin1String("::"), QLatin1String("_"))).toUpper();
- const QString namespaceStr = hasNamespace ? namespaceName + QLatin1Char('_') : QStringLiteral("");
- const QString defineName = namespaceStr + cfg.className.toUpper() + QStringLiteral("_H");
-
- stream << "#ifndef " << defineName << endl;
- stream << "#define " << defineName << endl;
- stream << endl;
-}
-
-void KConfigHeaderGenerator::endHeaderGuards()
-{
- stream << endl;
- stream << "#endif";
- stream << endl;
- // HACK: Original files ended with two last newlines, add them.
- stream << endl;
-}
-
-void KConfigHeaderGenerator::implementChoiceEnums(const CfgEntry *entry, const CfgEntry::Choices &choices)
-{
- const QList<CfgEntry::Choice> chlist = choices.choices;
-
- if (chlist.isEmpty()) {
- return;
- }
-
- QStringList values;
- for (const auto choice : qAsConst(chlist)) {
- values.append(choices.prefix + choice.name);
- }
-
- if (choices.name().isEmpty()) {
- if (cfg.globalEnums) {
- stream << whitespace() << "enum " << enumName(entry->name, entry->choices) << " { " << values.join(QStringLiteral(", ")) << " };" << endl;
- } else {
- // Create an automatically named enum
- stream << whitespace() << "class " << enumName(entry->name, entry->choices) << endl;
- stream << whitespace() << "{" << endl;
- stream << whitespace() << " public:" << endl;
- stream << whitespace() << " enum type { " << values.join(QStringLiteral(", ")) << ", COUNT };" << endl;
- stream << whitespace() << "};" << endl;
- }
- } else if (!choices.external()) {
- // Create a named enum
- stream << whitespace() << "enum " << enumName(entry->name, entry->choices) << " { " << values.join(QStringLiteral(", ")) << " };" << endl;
- }
-}
-
-void KConfigHeaderGenerator::implementValueEnums(const CfgEntry *entry, const QStringList &values)
-{
- if (values.isEmpty()) {
- return;
- }
-
- if (cfg.globalEnums) {
- // ### FIXME!!
- // make the following string table an index-based string search!
- // ###
- stream << whitespace() << "enum " << enumName(entry->param) << " { " << values.join(QStringLiteral(", ")) << " };" << endl;
- stream << whitespace() << "static const char* const " << enumName(entry->param) << "ToString[];" << endl;
- } else {
- stream << whitespace() << "class " << enumName(entry->param) << endl;
- stream << whitespace() << "{" << endl;
- stream << whitespace() << " public:" << endl;
- stream << whitespace() << " enum type { " << values.join(QStringLiteral(", ")) << ", COUNT };" << endl;
- stream << whitespace() << " static const char* const enumToString[];" << endl;
- stream << whitespace() << "};" << endl;
- }
-}
-
-void KConfigHeaderGenerator::implementEnums()
-{
- if (!parseResult.entries.size()) {
- return;
- }
-
- for (const auto entry : qAsConst(parseResult.entries)) {
- const CfgEntry::Choices &choices = entry->choices;
- const QStringList values = entry->paramValues;
-
- implementChoiceEnums(entry, choices);
- implementValueEnums(entry, values);
- }
- stream << endl;
-}
-
-void KConfigHeaderGenerator::createSignals()
-{
- // Signal definition.
- const bool hasSignals = !parseResult.signalList.isEmpty();
-
- unsigned val = 1 << parseResult.signalList.size();
- if (!val) {
- cerr << "Too many signals to create unique bit masks" << endl;
- exit(1);
- }
-
- if (!hasSignals) {
- return;
- }
-
- stream << "\n enum {" << endl;
- val = 1;
-
- // HACK: Use C-Style for add a comma in all but the last element,
- // just to make the source generated code equal to the old one.
- // When we are sure, revert this to a range-based-for and just add
- // a last comma, as it's valid c++.
- for (int i = 0, end = parseResult.signalList.size(); i < end; i++) {
- auto signal = parseResult.signalList.at(i);
- stream << whitespace() << " " << signalEnumName(signal.name) << " = 0x" << hex << val;
- if (i != end-1) {
- stream << "," << endl;
- }
-
- val <<= 1;
- }
- stream << endl;
- stream << whitespace() << "};" << dec << endl << endl;
-
- stream << " Q_SIGNALS:";
- for (const Signal &signal : qAsConst(parseResult.signalList)) {
- stream << endl;
- if (!signal.label.isEmpty()) {
- stream << whitespace() << "/**" << endl;
- stream << whitespace() << " " << signal.label << endl;
- stream << whitespace() << "*/" << endl;
- }
- stream << whitespace() << "void " << signal.name << "(";
- QList<Param>::ConstIterator it, itEnd = signal.arguments.constEnd();
- for (it = signal.arguments.constBegin(); it != itEnd;) {
- Param argument = *it;
- QString type = param(argument.type);
- if (cfg.useEnumTypes && argument.type == QLatin1String("Enum")) {
- for (auto *entry : qAsConst(parseResult.entries)) {
- if (entry->name == argument.name) {
- type = enumType(entry, cfg.globalEnums);
- break;
- }
- }
- }
- stream << type << " " << argument.name;
- if (++it != itEnd) {
- stream << ", ";
- }
- }
- stream << ");" << endl;
- }
- stream << endl;
-
- stream << " private:" << endl;
- stream << whitespace() << "void itemChanged(quint64 flags);" << endl;
- stream << endl;
-}
-
-void KConfigHeaderGenerator::createDPointer()
-{
- if (!cfg.dpointer) {
- return;
- }
-
- // use a private class for both member variables and items
- stream << " private:" << endl;
- for (const auto &entry : qAsConst(parseResult.entries)) {
- if (cfg.allDefaultGetters || cfg.defaultGetters.contains(entry->name)) {
- stream << whitespace() << "";
- if (cfg.staticAccessors) {
- stream << "static ";
- }
- stream << cppType(entry->type) << " " << getDefaultFunction(entry->name) << "_helper(";
- if (!entry->param.isEmpty()) {
- stream << " " << cppType(entry->paramType) << " i ";
- }
- stream << ")" << Const << ";" << endl;
- }
- }
- stream << whitespace() << "" << cfg.className << "Private *d;" << endl;
-}
-
-void KConfigHeaderGenerator::createConstructor()
-{
- if (cfg.singleton) {
- stream << whitespace() << "static " << cfg.className << " *self();" << endl;
- if (parseResult.cfgFileNameArg) {
- stream << whitespace() << "static void instance(const QString& cfgfilename);" << endl;
- stream << whitespace() << "static void instance(KSharedConfig::Ptr config);" << endl;
- }
- return;
- }
-
- stream << whitespace() << "" << cfg.className << "(";
- if (parseResult.cfgFileNameArg) {
- if (cfg.forceStringFilename)
- stream << " const QString &cfgfilename" << (parseResult.parameters.isEmpty() ? " = QString()" : ", ");
- else
- stream << " KSharedConfig::Ptr config" << (parseResult.parameters.isEmpty() ? " = KSharedConfig::openConfig()" : ", ");
- }
-
- bool first = true;
- for (const auto parameter : qAsConst(parseResult.parameters)) {
- if (first) {
- first = false;
- } else {
- stream << ",";
- }
-
- stream << " " << param(parameter.type) << " " << parameter.name;
- }
-
- if (cfg.parentInConstructor) {
- if (parseResult.cfgFileNameArg || !parseResult.parameters.isEmpty()) {
- stream << ",";
- }
- stream << " QObject *parent = nullptr";
- }
- stream << " );" << endl;
-}
-
-void KConfigHeaderGenerator::createDestructor()
-{
- stream << whitespace() << "~" << cfg.className << "();" << endl << endl;
-}
-
-void KConfigHeaderGenerator::createForwardDeclarations()
-{
- // Private class declaration
- if (cfg.dpointer) {
- stream << "class " << cfg.className << "Private;" << endl << endl;
- }
-}
-
-void KConfigHeaderGenerator::createProperties(const CfgEntry *entry, const QString& returnType)
-{
- if (!cfg.generateProperties) {
- return;
- }
- stream << whitespace() << "Q_PROPERTY(" << returnType << ' ' << getFunction(entry->name);
- stream << " READ " << getFunction(entry->name);
-
- if (cfg.allMutators || cfg.mutators.contains(entry->name)) {
- const QString signal = changeSignalName(entry->name);
- stream << " WRITE " << setFunction(entry->name);
- stream << " 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;
- parseResult.signalList.append(s);
- } else {
- stream << " CONSTANT";
- }
- stream << ")" << endl;
-}
-
-void KConfigHeaderGenerator::createSetters(const CfgEntry *entry)
-{
- // Manipulator
- if (!cfg.allMutators && !cfg.mutators.contains(entry->name)) {
- return;
- }
-
- stream << whitespace() << "/**" << endl;
- stream << whitespace() << " Set " << entry->label << endl;
- stream << whitespace() << "*/" << endl;
-
- if (cfg.staticAccessors) {
- stream << whitespace() << "static" << endl;
- }
-
- stream << whitespace() << "void " << setFunction(entry->name) << "( ";
- if (!entry->param.isEmpty()) {
- stream <<cppType(entry->paramType) << " i, ";
- }
-
- stream << (cfg.useEnumTypes && entry->type == QLatin1String("Enum")
- ? enumType(entry, cfg.globalEnums)
- : param(entry->type));
-
- stream << " v )";
-
- // function body inline only if not using dpointer
- // for BC mode
- if (!cfg.dpointer) {
- stream << endl;
- startScope();
- memberMutatorBody(entry);
- endScope();
- stream << endl;
- } else {
- stream << ";" << endl << endl;
- }
-}
-
-void KConfigHeaderGenerator::createGetters(const CfgEntry *entry, const QString& returnType)
-{
- // Accessor
- stream << whitespace() << "/**" << endl;
- stream << whitespace() << " Get " << entry->label << endl;
- stream << whitespace() << "*/" << endl;
- if (cfg.staticAccessors) {
- stream << whitespace() << "static" << endl;
- }
- stream << whitespace() << "";
- stream << returnType;
- stream << " " << getFunction(entry->name) << "(";
- if (!entry->param.isEmpty()) {
- stream << " " << cppType(entry->paramType) << " i ";
- }
- stream << ")" << Const;
-
- // function body inline only if not using dpointer
- // for BC mode
- if (!cfg.dpointer) {
- stream << endl;
- startScope();
- stream << whitespace() << memberAccessorBody(entry, cfg.globalEnums);
- endScope();
- stream << endl;
- } else {
- stream << ";" << endl << endl;
- }
-}
-
-void KConfigHeaderGenerator::createItemAcessors(const CfgEntry *entry, const QString& returnType)
-{
- // Item accessor
- if (!cfg.itemAccessors) {
- return;
- }
- stream << whitespace() << "/**" << endl;
- stream << whitespace() << " Get Item object corresponding to " << entry->name << "()"
- << endl;
- stream << whitespace() << "*/" << endl;
- stream << whitespace() << "Item" << itemType(entry->type) << " *"
- << getFunction(entry->name) << "Item(";
- if (!entry->param.isEmpty()) {
- stream << " " << cppType(entry->paramType) << " i ";
- }
- stream << ")";
- if (!cfg.dpointer) {
- stream << endl;
- startScope();
- stream << whitespace() << itemAccessorBody(entry, cfg);
- endScope();
- } else {
- stream << ";" << endl;
- }
-
- stream <<endl;
-}
-
-void KConfigHeaderGenerator::createDefaultValueMember(const CfgEntry *entry)
-{
- // Default value Accessor
- if (! ((cfg.allDefaultGetters || cfg.defaultGetters.contains(entry->name)) && !entry->defaultValue.isEmpty())) {
- return;
- }
- stream << whitespace() << "/**" << endl;
- stream << whitespace() << " Get " << entry->label << " default value" << endl;
- stream << whitespace() << "*/" << endl;
- if (cfg.staticAccessors) {
- stream << whitespace() << "static" << endl;
- }
- stream << whitespace() << "";
- if (cfg.useEnumTypes && entry->type == QLatin1String("Enum")) {
- stream << enumType(entry, cfg.globalEnums);
- } else {
- stream << cppType(entry->type);
- }
- stream << " " << getDefaultFunction(entry->name) << "(";
- if (!entry->param.isEmpty()) {
- stream << " " << cppType(entry->paramType) << " i ";
- }
- stream << ")" << Const << endl;
- stream << whitespace() << "{" << endl;
- stream << whitespace() << " return ";
- if (cfg.useEnumTypes && entry->type == QLatin1String("Enum")) {
- stream << "static_cast<" << enumType(entry, cfg.globalEnums) << ">(";
- }
- stream << getDefaultFunction(entry->name) << "_helper(";
- if (!entry->param.isEmpty()) {
- stream << " i ";
- }
- stream << ")";
- if (cfg.useEnumTypes && entry->type == QLatin1String("Enum")) {
- stream << ")";
- }
- stream << ";" << endl;
- stream << whitespace() << "}" << endl;
- stream << endl;
-}
-
-void KConfigHeaderGenerator::createSingleton()
-{
- // Private constructor for singleton
- if (!cfg.singleton) {
- return;
- }
-
- stream << whitespace() << "" << cfg.className << "(";
- if (parseResult.cfgFileNameArg) {
- stream << "KSharedConfig::Ptr config";
- }
- if (cfg.parentInConstructor) {
- if (parseResult.cfgFileNameArg) {
- stream << ", ";
- }
- stream << "QObject *parent = nullptr";
- }
- stream << ");" << endl;
- stream << whitespace() << "friend class " << cfg.className << "Helper;" << endl << endl;
-}
-
-void KConfigHeaderGenerator::createNonDPointerHelpers()
-{
- if (cfg.memberVariables == QLatin1String("dpointer")) {
- return;
- }
-
- QString group;
- for (auto *entry : qAsConst(parseResult.entries)) {
- if (entry->group != group) {
- group = entry->group;
- stream << endl;
- stream << whitespace() << "// " << group << endl;
- }
- stream << whitespace() << "" << cppType(entry->type) << " " << varName(entry->name, cfg);
- if (!entry->param.isEmpty()) {
- stream << QStringLiteral("[%1]").arg(entry->paramMax + 1);
- }
- stream << ";" << endl;
-
- if (cfg.allDefaultGetters || cfg.defaultGetters.contains(entry->name)) {
- stream << whitespace() << "";
- if (cfg.staticAccessors) {
- stream << "static ";
- }
- stream << cppType(entry->type) << " " << getDefaultFunction(entry->name) << "_helper(";
- if (!entry->param.isEmpty()) {
- stream << " " << cppType(entry->paramType) << " i ";
- }
- stream << ")" << Const << ";" << endl;
- }
- }
-
- stream << endl << " private:" << endl;
- if (cfg.itemAccessors) {
- for (auto *entry : qAsConst(parseResult.entries)) {
- stream << whitespace() << "Item" << itemType(entry->type) << " *" << itemVar(entry, cfg);
- if (!entry->param.isEmpty()) {
- stream << QStringLiteral("[%1]").arg(entry->paramMax + 1);
- }
- stream << ";" << endl;
- }
- }
-
- if (parseResult.hasNonModifySignals) {
- stream << whitespace() << "uint " << varName(QStringLiteral("settingsChanged"), cfg) << ";" << endl;
- }
-}
diff --git a/src/kconfig_compiler/KConfigHeaderGenerator.h b/src/kconfig_compiler/KConfigHeaderGenerator.h
deleted file mode 100644
index 30f09ac4..00000000
--- a/src/kconfig_compiler/KConfigHeaderGenerator.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- This file is part of KDE.
-
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 KCONFIGHEADERGENERATOR_H
-#define KCONFIGHEADERGENERATOR_H
-
-#include "KConfigCodeGeneratorBase.h"
-#include "KConfigCommonStructs.h"
-
-#include <QString>
-#include <QList>
-
-class KConfigXTParameters;
-class CfgEntry;
-class QTextStream;
-struct ParseResult;
-
-class KConfigHeaderGenerator : public KConfigCodeGeneratorBase {
-public:
- KConfigHeaderGenerator(
- const QString& inputFile,
- const QString& baseDir,
- const KConfigXTParameters &parameters,
- ParseResult &parseResult);
-
- void start() override;
-
-private:
- void startHeaderGuards();
- void endHeaderGuards();
-
- void implementEnums();
- void implementChoiceEnums(const CfgEntry *entry, const CfgEntry::Choices &choices);
- void implementValueEnums(const CfgEntry *entry, const QStringList &values);
-
- void doClassDefinition();
- void createHeaders();
- void createDPointer();
- void createNonDPointerHelpers();
-
- void createConstructor();
- void createDestructor();
- void createForwardDeclarations();
- void createSingleton();
- void createSignals();
-
- void createSetters(const CfgEntry *entry);
- void createItemAcessors(const CfgEntry *entry, const QString& returnType);
- void createGetters(const CfgEntry *entry, const QString& returnType);
- void createProperties(const CfgEntry *entry, const QString& returnType);
- void createDefaultValueMember(const CfgEntry *entry);
-};
-
-#endif
diff --git a/src/kconfig_compiler/KConfigSourceGenerator.cpp b/src/kconfig_compiler/KConfigSourceGenerator.cpp
deleted file mode 100644
index 1949b420..00000000
--- a/src/kconfig_compiler/KConfigSourceGenerator.cpp
+++ /dev/null
@@ -1,657 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 "KConfigSourceGenerator.h"
-#include "KConfigCommonStructs.h"
-
-
-KConfigSourceGenerator::KConfigSourceGenerator(
- const QString& inputFile,
- const QString& baseDir,
- const KConfigXTParameters &cfg,
- ParseResult &parseResult)
- : KConfigCodeGeneratorBase(inputFile, baseDir, baseDir + cfg.baseName + QLatin1Char('.') + cfg.sourceExtension, cfg, parseResult)
-{
-}
-
-void KConfigSourceGenerator::start()
-{
- KConfigCodeGeneratorBase::start();
- stream << endl;
- createHeaders();
-
- if (!cfg.nameSpace.isEmpty()) {
- stream << "using namespace " << cfg.nameSpace << ";";
- stream << endl << endl;
- }
-
- createPrivateDPointerImplementation();
- createSingletonImplementation();
- createPreamble();
- doConstructor();
- doGetterSetterDPointerMode();
- createDefaultValueGetterSetter();
- createDestructor();
- createNonModifyingSignalsHelper();
- createSignalFlagsHandler();
- includeMoc();
-}
-
-void KConfigSourceGenerator::createHeaders()
-{
- QString headerName = cfg.baseName + QLatin1Char('.') + cfg.headerExtension;
-
- // TODO: Make addQuotes return a string instead of replacing it inplace.
- addQuotes(headerName);
-
- addHeaders({ headerName });
- stream << endl;
-
- addHeaders(cfg.sourceIncludes);
- if (cfg.setUserTexts && cfg.translationSystem == KConfigXTParameters::KdeTranslation) {
- addHeaders({QStringLiteral("klocalizedstring.h")});
- stream << endl;
- }
-
- // Header required by singleton implementation
- if (cfg.singleton) {
- addHeaders({QStringLiteral("qglobal.h"), QStringLiteral("QFile")});
-
- // HACK: Add single line to fix test.
- if (cfg.singleton && parseResult.cfgFileNameArg) {
- stream << endl;
- }
- }
-
- if (cfg.singleton && parseResult.cfgFileNameArg) {
- addHeaders({QStringLiteral("QDebug")});
- }
-
- if (cfg.singleton) {
- stream << endl;
- }
-}
-
-void KConfigSourceGenerator::createPrivateDPointerImplementation()
-{
- // private class implementation
- if (!cfg.dpointer) {
- return;
- }
-
- QString group;
- beginNamespaces();
- stream << "class " << cfg.className << "Private" << endl;
- stream << "{" << endl;
- stream << " public:" << endl;
-
- // Create Members
- for (auto *entry : qAsConst(parseResult.entries)) {
- if (entry->group != group) {
- group = entry->group;
- stream << endl;
- stream << " // " << group << endl;
- }
- stream << " " << cppType(entry->type) << " " << varName(entry->name, cfg);
- if (!entry->param.isEmpty()) {
- stream << QStringLiteral("[%1]").arg(entry->paramMax + 1);
- }
- stream << ";" << endl;
- }
- stream << endl << " // items" << endl;
-
- // Create Items.
- for (auto *entry : qAsConst(parseResult.entries)) {
- const QString declType = entry->signalList.isEmpty()
- ? QString(cfg.inherits + QStringLiteral("::Item") + itemType(entry->type))
- : QStringLiteral("KConfigCompilerSignallingItem");
-
- stream << " " << declType << " *" << itemVar( entry, cfg );
- if (!entry->param.isEmpty()) {
- stream << QStringLiteral("[%1]").arg(entry->paramMax + 1);
- }
- stream << ";" << endl;
- }
-
- if (parseResult.hasNonModifySignals) {
- stream << " uint " << varName(QStringLiteral("settingsChanged"), cfg) << ";" << endl;
- }
-
- stream << "};" << endl << endl;
- endNamespaces();
-}
-
-void KConfigSourceGenerator::createSingletonImplementation()
-{
- // Singleton implementation
- if (!cfg.singleton) {
- return;
- }
-
- beginNamespaces();
- stream << "class " << cfg.className << "Helper" << endl;
- stream << '{' << endl;
- stream << " public:" << endl;
- stream << " " << cfg.className << "Helper() : q(nullptr) {}" << endl;
- stream << " ~" << cfg.className << "Helper() { delete q; }" << endl;
- stream << " " << cfg.className << "Helper(const " << cfg.className << "Helper&) = delete;" << endl;
- stream << " " << cfg.className << "Helper& operator=(const " << cfg.className << "Helper&) = delete;" << endl;
- stream << " " << cfg.className << " *q;" << endl;
- stream << "};" << endl;
- endNamespaces();
-
- stream << "Q_GLOBAL_STATIC(" << cfg.className << "Helper, s_global" << cfg.className << ")" << endl;
-
- stream << cfg.className << " *" << cfg.className << "::self()" << endl;
- stream << "{" << endl;
- if (parseResult.cfgFileNameArg) {
- stream << " if (!s_global" << cfg.className << "()->q)" << endl;
- stream << " qFatal(\"you need to call " << cfg.className << "::instance before using\");" << endl;
- } else {
- stream << " if (!s_global" << cfg.className << "()->q) {" << endl;
- stream << " new " << cfg.className << ';' << endl;
- stream << " s_global" << cfg.className << "()->q->read();" << endl;
- stream << " }" << endl << endl;
- }
- stream << " return s_global" << cfg.className << "()->q;" << endl;
- stream << "}" << endl << endl;
-
- if (parseResult.cfgFileNameArg) {
- auto instance = [this] (const QString &type, const QString &arg, bool isString) {
- stream << "void " << cfg.className << "::instance(" << type << " " << arg << ")" << endl;
- stream << "{" << endl;
- stream << " if (s_global" << cfg.className << "()->q) {" << endl;
- stream << " qDebug() << \"" << cfg.className << "::instance called after the first use - ignoring\";" << endl;
- stream << " return;" << endl;
- stream << " }" << endl;
- stream << " new " << cfg.className << "(";
- if (isString) {
- stream << "KSharedConfig::openConfig(" << arg << ")";
- } else {
- stream << "std::move(" << arg << ")";
- }
- stream << ");" << endl;
- stream << " s_global" << cfg.className << "()->q->read();" << endl;
- stream << "}" << endl << endl;
- };
- instance(QStringLiteral("const QString&"), QStringLiteral("cfgfilename"), true);
- instance(QStringLiteral("KSharedConfig::Ptr"), QStringLiteral("config"), false);
- }
-}
-
-void KConfigSourceGenerator::createPreamble()
-{
- QString cppPreamble;
- for (const auto entry : qAsConst(parseResult.entries)) {
- if (entry->paramValues.isEmpty()) {
- continue;
- }
-
- cppPreamble += QStringLiteral("const char* const ") + cfg.className + QStringLiteral("::") + enumName(entry->param);
- cppPreamble += cfg.globalEnums
- ? QStringLiteral("ToString[] = { \"") + entry->paramValues.join(QStringLiteral("\", \"")) + QStringLiteral("\" };\n")
- : QStringLiteral("::enumToString[] = { \"") + entry->paramValues.join(QStringLiteral("\", \"")) + QStringLiteral("\" };\n");
- }
-
- if (!cppPreamble.isEmpty()) {
- stream << cppPreamble << endl;
- }
-}
-
-void KConfigSourceGenerator::createConstructorParameterList()
-{
- if (parseResult.cfgFileNameArg) {
- if (!cfg.forceStringFilename) {
- stream << " KSharedConfig::Ptr config";
- } else {
- stream << " const QString& config";
- }
- stream << (parseResult.parameters.isEmpty() ? "" : ",");
- }
-
- for (QList<Param>::ConstIterator it = parseResult.parameters.constBegin();
- it != parseResult.parameters.constEnd(); ++it) {
- if (it != parseResult.parameters.constBegin()) {
- stream << ",";
- }
- stream << " " << param((*it).type) << " " << (*it).name;
- }
-
- if (cfg.parentInConstructor) {
- if (parseResult.cfgFileNameArg || !parseResult.parameters.isEmpty()) {
- stream << ",";
- }
- stream << " QObject *parent";
- }
-
-}
-
-void KConfigSourceGenerator::createParentConstructorCall()
-{
- stream << cfg.inherits << "(";
- if (!parseResult.cfgFileName.isEmpty()) {
- stream << " QStringLiteral( \"" << parseResult.cfgFileName << "\" ";
- }
- if (parseResult.cfgFileNameArg) {
- if (! cfg.forceStringFilename) {
- stream << " std::move( config ) ";
- } else {
- stream << " config ";
- }
- }
- if (!parseResult.cfgFileName.isEmpty()) {
- stream << ") ";
- }
- stream << ")" << endl;
-}
-
-void KConfigSourceGenerator::createInitializerList()
-{
- for (const auto &parameter : qAsConst(parseResult.parameters)) {
- stream << " , mParam" << parameter.name << "(" << parameter.name << ")" << endl;
- }
-
- if (parseResult.hasNonModifySignals && !cfg.dpointer) {
- stream << " , " << varName(QStringLiteral("settingsChanged"), cfg) << "(0)" << endl;
- }
-}
-
-void KConfigSourceGenerator::createEnums(const CfgEntry *entry)
-{
- if (entry->type != QLatin1String("Enum")) {
- return;
- }
- stream << " QList<" << cfg.inherits << "::ItemEnum::Choice> values" << entry->name << ";" << endl;
-
- for (const auto &choice : qAsConst(entry->choices.choices)) {
- stream << " {" << endl;
- stream << " " << cfg.inherits << "::ItemEnum::Choice choice;" << endl;
- stream << " choice.name = QStringLiteral(\"" << choice.name << "\");" << endl;
- if (cfg.setUserTexts) {
- if (!choice.label.isEmpty()) {
- stream << " choice.label = "
- << translatedString(cfg, choice.label, choice.context)
- << ";" << endl;
- }
- if (!choice.toolTip.isEmpty()) {
- stream << " choice.toolTip = "
- << translatedString(cfg, choice.toolTip, choice.context)
- << ";" << endl;
- }
- if (!choice.whatsThis.isEmpty()) {
- stream << " choice.whatsThis = "
- << translatedString(cfg, choice.whatsThis, choice.context)
- << ";" << endl;
- }
- }
- stream << " values" << entry->name << ".append( choice );" << endl;
- stream << " }" << endl;
- }
-}
-
-void KConfigSourceGenerator::createNormalEntry(const CfgEntry *entry, const QString& key)
-{
- stream << " " << itemPath(entry, cfg) << " = "
- << newItem(entry, key, entry->defaultValue, cfg) << endl;
-
- if (!entry->min.isEmpty()) {
- stream << " " << itemPath(entry, cfg) << "->setMinValue(" << entry->min << ");" << endl;
- }
- if (!entry->max.isEmpty()) {
- stream << " " << itemPath(entry, cfg) << "->setMaxValue(" << entry->max << ");" << endl;
- }
-
- if (cfg.setUserTexts) {
- stream << userTextsFunctions(entry, cfg);
- }
-
- if (cfg.allNotifiers || cfg.notifiers.contains(entry->name)) {
- stream << " " << itemPath(entry, cfg) << "->setWriteFlags(KConfigBase::Notify);" << endl;
- }
-
- stream << " addItem( " << itemPath(entry, cfg);
- QString quotedName = entry->name;
- addQuotes(quotedName);
- if (quotedName != key) {
- stream << ", QStringLiteral( \"" << entry->name << "\" )";
- }
- stream << " );" << endl;
-}
-
-void KConfigSourceGenerator::createIndexedEntry(const CfgEntry *entry, const QString& key)
-{
- for (int i = 0; i <= entry->paramMax; i++) {
- QString itemVarStr(itemPath(entry, cfg) + QStringLiteral("[%1]").arg(i));
-
- QString defaultStr = !entry->paramDefaultValues[i].isEmpty() ? entry->paramDefaultValues[i]
- : !entry->defaultValue.isEmpty() ? paramString(entry->defaultValue, entry, i)
- : defaultValue(entry->type);
-
- stream << " " << itemVarStr << " = "
- << newItem(entry, paramString(key, entry, i), defaultStr, cfg, QStringLiteral("[%1]").arg(i)) << endl;
-
- if (cfg.setUserTexts) {
- stream << userTextsFunctions(entry, cfg, itemVarStr, entry->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!.
- const bool isEnum = entry->paramType == QLatin1String("Enum");
- const QString arg = isEnum ? entry->paramValues[i] : QString::number(i);
-
- QString paramName = entry->paramName;
-
- stream << " addItem( " << itemVarStr << ", QStringLiteral( \"";
- stream << paramName.replace(QStringLiteral("$(") + entry->param + QLatin1Char(')'), QLatin1String("%1")).arg( arg );
- stream << "\" ) );" << endl;
- }
-}
-
-void KConfigSourceGenerator::handleCurrentGroupChange(const CfgEntry *entry)
-{
- if (entry->group == mCurrentGroup) {
- return;
- }
-
- // HACK: This fixes one spacing line in the diff. Remove this in the future and adapt the testcases.
- static bool first = true;
- if (!entry->group.isEmpty()) {
- if (!first) {
- stream << endl;
- }
- first = false;
- }
-
- mCurrentGroup = entry->group;
- stream << " setCurrentGroup( " << paramString(mCurrentGroup, parseResult.parameters) << " );";
- stream << endl << endl;
-}
-
-void KConfigSourceGenerator::doConstructor()
-{
- // Constructor
- stream << cfg.className << "::" << cfg.className << "(";
- createConstructorParameterList();
- stream << " )" << endl;
- stream << " : ";
- createParentConstructorCall();
- createInitializerList();
-
- stream << "{" << endl;
-
- if (cfg.parentInConstructor) {
- stream << " setParent(parent);" << endl;
- }
-
- if (cfg.dpointer) {
- stream << " d = new " << cfg.className << "Private;" << endl;
- if (parseResult.hasNonModifySignals) {
- stream << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " = 0;" << endl;
- }
- }
-
- // Needed in case the singleton class is used as baseclass for
- // another singleton.
- if (cfg.singleton) {
- stream << " Q_ASSERT(!s_global" << cfg.className << "()->q);" << endl;
- stream << " s_global" << cfg.className << "()->q = this;" << endl;
- }
-
- if (!parseResult.signalList.isEmpty()) {
- // this cast to base-class pointer-to-member is valid C++
- // https://stackoverflow.com/questions/4272909/is-it-safe-to-upcast-a-method-pointer-and-use-it-with-base-class-pointer/
- stream << " KConfigCompilerSignallingItem::NotifyFunction notifyFunction ="
- << " static_cast<KConfigCompilerSignallingItem::NotifyFunction>(&"
- << cfg.className << "::itemChanged);" << endl;
-
- stream << endl;
- }
-
- for (auto *entry : qAsConst(parseResult.entries)) {
- handleCurrentGroupChange(entry);
-
- const QString key = paramString(entry->key, parseResult.parameters);
- if (!entry->code.isEmpty()) {
- stream << entry->code << endl;
- }
- createEnums(entry);
-
- if (!cfg.dpointer) {
- stream << itemDeclaration(entry, cfg);
- }
-
- if (entry->param.isEmpty()) {
- createNormalEntry(entry, key);
- } else {
- createIndexedEntry(entry, key);
- }
- }
-
- stream << "}" << endl << endl;
-}
-
-void KConfigSourceGenerator::createGetterDPointerMode(const CfgEntry *entry)
-{
- // Accessor
- if (cfg.useEnumTypes && entry->type == QLatin1String("Enum")) {
- stream << enumType(entry, cfg.globalEnums);
- } else {
- stream << cppType(entry->type);
- }
-
- stream << " " << getFunction(entry->name, cfg.className) << "(";
- if (!entry->param.isEmpty()) {
- stream << " " << cppType(entry->paramType) << " i ";
- }
- stream << ")" << Const << endl;
-
- // function body inline only if not using dpointer
- // for BC mode
- startScope();
- // HACK: Fix memberAccessorBody
- stream << " " << memberAccessorBody(entry, cfg.globalEnums);
- endScope();
- stream << endl;
-}
-
-void KConfigSourceGenerator::createSetterDPointerMode(const CfgEntry *entry)
-{
- // Manipulator
- if (!(cfg.allMutators || cfg.mutators.contains(entry->name))) {
- return;
- }
-
- stream << "void " << setFunction(entry->name, cfg.className) << "( ";
- if (!entry->param.isEmpty()) {
- stream << cppType(entry->paramType) << " i, ";
- }
-
- if (cfg.useEnumTypes && entry->type == QLatin1String("Enum")) {
- stream << enumType(entry, cfg.globalEnums);
- } else {
- stream << param(entry->type);
- }
- stream << " v )" << endl;
-
- // function body inline only if not using dpointer
- // for BC mode
- startScope();
- memberMutatorBody(entry);
- endScope();
- stream << endl;
-}
-
-void KConfigSourceGenerator::createItemGetterDPointerMode(const CfgEntry *entry)
-{
- // Item accessor
- if (!cfg.itemAccessors) {
- return;
- }
- stream << endl;
- stream << cfg.inherits << "::Item" << itemType(entry->type) << " *"
- << getFunction(entry->name, cfg.className) << "Item(";
- if (!entry->param.isEmpty()) {
- stream << " " << cppType(entry->paramType) << " i ";
- }
- stream << ")" << endl;
- startScope();
- stream << " " << itemAccessorBody(entry, cfg);
- endScope();
-}
-
-void KConfigSourceGenerator::doGetterSetterDPointerMode()
-{
- if (!cfg.dpointer) {
- return;
- }
-
- // setters and getters go in Cpp if in dpointer mode
- for (auto *entry : qAsConst(parseResult.entries)) {
- createSetterDPointerMode(entry);
- createGetterDPointerMode(entry);
- createItemGetterDPointerMode(entry);
- stream << endl;
- }
-}
-
-void KConfigSourceGenerator::createDefaultValueGetterSetter()
-{
- // default value getters always go in Cpp
- for (auto *entry : qAsConst(parseResult.entries)) {
- QString n = entry->name;
- QString t = entry->type;
-
- // Default value Accessor, as "helper" function
- if ((cfg.allDefaultGetters || cfg.defaultGetters.contains(n)) && !entry->defaultValue.isEmpty()) {
- stream << cppType(t) << " " << getDefaultFunction(n, cfg.className) << "_helper(";
- if (!entry->param.isEmpty()) {
- stream << " " << cppType(entry->paramType) << " i ";
- }
- stream << ")" << Const << endl;
- startScope();
- stream << memberGetDefaultBody(entry) << endl;
- endScope();
- stream << endl;
- }
- }
-}
-
-void KConfigSourceGenerator::createDestructor()
-{
- stream << cfg.className << "::~" << cfg.className << "()" << endl;
- startScope();
- if (cfg.dpointer) {
- stream << " delete d;" << endl;
- }
- if (cfg.singleton) {
- stream << " s_global" << cfg.className << "()->q = nullptr;" << endl;
- }
- endScope();
- stream << endl;
-}
-
-void KConfigSourceGenerator::createNonModifyingSignalsHelper()
-{
- if (!parseResult.hasNonModifySignals) {
- return;
- }
- stream << "bool " << cfg.className << "::" << "usrSave()" << endl;
- startScope();
- stream << " const bool res = " << cfg.inherits << "::usrSave();" << endl;
- stream << " if (!res) return false;" << endl << endl;
- for (const Signal &signal : qAsConst(parseResult.signalList)) {
- if (signal.modify) {
- continue;
- }
-
- stream << " if ( " << varPath(QStringLiteral("settingsChanged"), cfg) << " & " << signalEnumName(signal.name) << " )" << endl;
- stream << " Q_EMIT " << signal.name << "(";
- QList<Param>::ConstIterator it, itEnd = signal.arguments.constEnd();
- for (it = signal.arguments.constBegin(); it != itEnd;) {
- Param argument = *it;
- bool cast = false;
- if (cfg.useEnumTypes && argument.type == QLatin1String("Enum")) {
- for (int i = 0, end = parseResult.entries.count(); i < end; ++i) {
- if (parseResult.entries.at(i)->name == argument.name) {
- stream << "static_cast<" << enumType(parseResult.entries.at(i), cfg.globalEnums) << ">(";
- cast = true;
- break;
- }
- }
- }
- stream << varPath(argument.name, cfg);
- if (cast) {
- stream << ")";
- }
- if (++it != itEnd) {
- stream << ", ";
- }
- }
-
- stream << ");" << endl;
- }
-
- stream << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " = 0;" << endl;
- stream << " return true;" << endl;
- endScope();
-}
-
-void KConfigSourceGenerator::createSignalFlagsHandler()
-{
- if (parseResult.signalList.isEmpty()) {
- return;
- }
-
- stream << endl;
- stream << "void " << cfg.className << "::" << "itemChanged(quint64 flags) {" << endl;
- if (parseResult.hasNonModifySignals)
- stream << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " |= flags;" << endl;
-
- if (!parseResult.signalList.isEmpty())
- stream << endl;
-
- for (const Signal &signal : qAsConst(parseResult.signalList)) {
- if (signal.modify) {
- stream << " if ( flags & " << signalEnumName(signal.name) << " ) {" << endl;
- stream << " Q_EMIT " << signal.name << "();" << endl;
- stream << " }" << endl;
- }
- }
-
- stream << "}" << endl;
-}
-
-void KConfigSourceGenerator::includeMoc() {
- const QString mocFileName = cfg.baseName + QStringLiteral(".moc");
-
- if (parseResult.signalList.count() || cfg.generateProperties) {
- // Add includemoc if they are signals defined.
- stream << endl;
- stream << "#include \"" << mocFileName << "\"" << endl;
- stream << endl;
- }
-}
diff --git a/src/kconfig_compiler/KConfigSourceGenerator.h b/src/kconfig_compiler/KConfigSourceGenerator.h
deleted file mode 100644
index 77409329..00000000
--- a/src/kconfig_compiler/KConfigSourceGenerator.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- This file is part of KDE.
-
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 KCONFIGSOURCEGENERATOR_H
-#define KCONFIGSOURCEGENERATOR_H
-
-#include "KConfigCodeGeneratorBase.h"
-#include "KConfigCommonStructs.h"
-
-#include <QString>
-#include <QList>
-
-class KConfigXTParameters;
-class CfgEntry;
-class QTextStream;
-struct ParseResult;
-
-class KConfigSourceGenerator : public KConfigCodeGeneratorBase {
-public:
- KConfigSourceGenerator(
- const QString& inputFile,
- const QString& baseDir,
- const KConfigXTParameters &parameters,
- ParseResult &parseResult);
-
- void start() override;
-
-private:
- // Those are fairly self contained functions.
- void createHeaders();
- void createPrivateDPointerImplementation();
- void createSingletonImplementation();
- void createPreamble();
- void createDestructor();
- void createConstructorParameterList();
- void createParentConstructorCall();
- void createInitializerList();
- void createDefaultValueGetterSetter();
- void createNonModifyingSignalsHelper();
- void createSignalFlagsHandler();
- void includeMoc();
-
- // Constructor related methods
- // the `do` methods have related helper functions that are only related
- // to it. So we can break the function into many smaller ones and create
- // logic inside of the `do` function.
- void doConstructor();
- void createEnums(const CfgEntry *entry);
- void createNormalEntry(const CfgEntry *entry, const QString& key);
- void createIndexedEntry(const CfgEntry *entry, const QString& key);
- void handleCurrentGroupChange(const CfgEntry *entry);
-
- void doGetterSetterDPointerMode();
- void createGetterDPointerMode(const CfgEntry *entry);
- void createSetterDPointerMode(const CfgEntry *entry);
- void createItemGetterDPointerMode(const CfgEntry *entry);
-
-private:
- QString mCurrentGroup;
-};
-
-#endif
diff --git a/src/kconfig_compiler/KConfigXTParameters.cpp b/src/kconfig_compiler/KConfigXTParameters.cpp
deleted file mode 100644
index 1d488e9e..00000000
--- a/src/kconfig_compiler/KConfigXTParameters.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 "KConfigXTParameters.h"
-
-// TODO: Remove this.
-#undef QT_NO_CAST_FROM_ASCII
-
-#include <QDebug>
-#include <QFileInfo>
-
-namespace
-{
-QTextStream cout(stdout);
-QTextStream cerr(stderr);
-}
-
-KConfigXTParameters::KConfigXTParameters(const QString &codegenFilename)
-{
- if (!codegenFilename.endsWith(QLatin1String(".kcfgc"))) {
- cerr << "Codegen options file must have extension .kcfgc" << endl;
- exit(1);
- }
-
- baseName = QFileInfo(codegenFilename).fileName();
- baseName = baseName.left(baseName.length() - 6);
-
- // 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 += QLatin1Char(' ');
- }
- parentInConstructor = codegenConfig.value(QStringLiteral("ParentInConstructor"), false).toBool();
- 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();
-}
diff --git a/src/kconfig_compiler/KConfigXTParameters.h b/src/kconfig_compiler/KConfigXTParameters.h
deleted file mode 100644
index db2cbcb5..00000000
--- a/src/kconfig_compiler/KConfigXTParameters.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- This file is part of KDE.
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
- Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
- Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2003 Zack Rusin <zack@kde.org>
- Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
- Copyright (c) 2008 Allen Winter <winter@kde.org>
- Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org)
-
- 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 KCOFIGXTPARAMETERS_H
-#define KCOFIGXTPARAMETERS_H
-
-#include <QSettings>
-#include <QString>
-#include <QStringList>
-
-/**
- Configuration Compiler Configuration
-*/
-class KConfigXTParameters
-{
-public:
- KConfigXTParameters(const QString &codegenFilename);
-
-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 parentInConstructor; // The class has the optional parent parameter in its constructor
- 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;
- QString baseName;
-};
-
-#endif
diff --git a/src/kconfig_compiler/kconfig_compiler.cpp b/src/kconfig_compiler/kconfig_compiler.cpp
index 00699c36..848595f2 100644
--- a/src/kconfig_compiler/kconfig_compiler.cpp
+++ b/src/kconfig_compiler/kconfig_compiler.cpp
@@ -34,19 +34,15 @@
#include <QDomAttr>
#include <QRegularExpression>
#include <QStringList>
-#include <QCommandLineParser>
-#include <QCommandLineOption>
+
+#include <qcommandlineparser.h>
+#include <qcommandlineoption.h>
#include <ostream>
#include <iostream>
#include <stdlib.h>
#include "../../kconfig_version.h"
-#include "KConfigXTParameters.h"
-#include "KConfigCommonStructs.h"
-#include "KConfigHeaderGenerator.h"
-#include "KConfigSourceGenerator.h"
-#include "KCFGXmlParser.h"
namespace
{
@@ -54,7 +50,444 @@ QTextStream cout(stdout);
QTextStream cerr(stderr);
}
-QString varName(const QString &n, const KConfigXTParameters &cfg)
+QStringList allNames;
+QRegularExpression *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 += ' ';
+ }
+ parentInConstructor = codegenConfig.value(QStringLiteral("ParentInConstructor"), false).toBool();
+ 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 parentInConstructor; // The class has the optional parent parameter in its constructor
+ 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<SignalArguments> 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<Choice> &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<Choice> 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<Signal> &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<Choice> &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<Signal> &value)
+ {
+ mSignalList = value;
+ }
+ QList<Signal> signalList() const
+ {
+ return mSignalList;
+ }
+
+ bool hidden() const
+ {
+ return mHidden;
+ }
+
+ void dump() const
+ {
+ cerr << "<entry>" << 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 << "</entry>" << 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<Signal> 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) {
@@ -67,7 +500,7 @@ QString varName(const QString &n, const KConfigXTParameters &cfg)
return result;
}
-QString varPath(const QString &n, const KConfigXTParameters &cfg)
+static QString varPath(const QString &n, const CfgConfig &cfg)
{
QString result;
if (cfg.dpointer) {
@@ -78,14 +511,14 @@ QString varPath(const QString &n, const KConfigXTParameters &cfg)
return result;
}
-QString enumName(const QString &n)
+static QString enumName(const QString &n)
{
QString result = QLatin1String("Enum") + n;
result[4] = result[4].toUpper();
return result;
}
-QString enumName(const QString &n, const CfgEntry::Choices &c)
+static QString enumName(const QString &n, const CfgEntry::Choices &c)
{
QString result = c.name();
if (result.isEmpty()) {
@@ -95,11 +528,11 @@ QString enumName(const QString &n, const CfgEntry::Choices &c)
return result;
}
-QString enumType(const CfgEntry *e, bool globalEnums)
+static QString enumType(const CfgEntry *e, bool globalEnums)
{
- QString result = e->choices.name();
+ QString result = e->choices().name();
if (result.isEmpty()) {
- result = QLatin1String("Enum") + e->name;
+ result = QLatin1String("Enum") + e->name();
if (!globalEnums) {
result += QLatin1String("::type");
}
@@ -108,7 +541,7 @@ QString enumType(const CfgEntry *e, bool globalEnums)
return result;
}
-QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
+static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
{
QString result = c.name();
if (result.isEmpty()) {
@@ -122,7 +555,7 @@ QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
return result;
}
-QString setFunction(const QString &n, const QString &className)
+static QString setFunction(const QString &n, const QString &className = QString())
{
QString result = QLatin1String("set") + n;
result[3] = result[3].toUpper();
@@ -133,12 +566,12 @@ QString setFunction(const QString &n, const QString &className)
return result;
}
-QString changeSignalName(const QString &n)
+static QString changeSignalName(const QString &n)
{
return n+QStringLiteral("Changed");
}
-QString getDefaultFunction(const QString &n, const QString &className)
+static QString getDefaultFunction(const QString &n, const QString &className = QString())
{
QString result = QLatin1String("default") + n + QLatin1String("Value");
result[7] = result[7].toUpper();
@@ -149,7 +582,7 @@ QString getDefaultFunction(const QString &n, const QString &className)
return result;
}
-QString getFunction(const QString &n, const QString &className)
+static QString getFunction(const QString &n, const QString &className = QString())
{
QString result = n;
result[0] = result[0].toLower();
@@ -160,7 +593,7 @@ QString getFunction(const QString &n, const QString &className)
return result;
}
-void addQuotes(QString &s)
+static void addQuotes(QString &s)
{
if (!s.startsWith(QLatin1Char('"'))) {
s.prepend(QLatin1Char('"'));
@@ -180,7 +613,7 @@ static QString quoteString(const QString &s)
return QLatin1Char('\"') + r + QLatin1Char('\"');
}
-QString literalString(const QString &s)
+static QString literalString(const QString &s)
{
bool isAscii = true;
for (int i = s.length(); i--;)
@@ -195,8 +628,20 @@ QString literalString(const QString &s)
}
}
+static QString dumpNode(const QDomNode &node)
+{
+ QString msg;
+ QTextStream s(&msg, QIODevice::WriteOnly);
+ node.save(s, 0);
-QString signalEnumName(const QString &signalName)
+ msg = msg.simplified();
+ if (msg.length() > 40) {
+ return msg.left(37) + QLatin1String("...");
+ }
+ return msg;
+}
+
+static QString signalEnumName(const QString &signalName)
{
QString result;
result = QLatin1String("signal") + signalName;
@@ -205,8 +650,345 @@ QString signalEnumName(const QString &signalName)
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;
+ }
-bool isUnsigned(const QString &type)
+ if (type == QLatin1String("UrlList")) {
+ cpp << " QList<QUrl> 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()) {
+ const QRegularExpression colorRe(QRegularExpression::anchoredPattern(
+ QStringLiteral("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?")));
+
+ if (colorRe.match(defaultValue).hasMatch()) {
+ defaultValue = QLatin1String("QColor( ") + defaultValue + QLatin1String(" )");
+ } else {
+ defaultValue = QLatin1String("QColor( \"") + defaultValue + QLatin1String("\" )");
+ }
+
+ } else if (type == QLatin1String("Enum")) {
+ QList<CfgEntry::Choice>::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<int> 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<Signal> 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<CfgEntry::Choice> 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 <choice> 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! <name> 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->match(name).hasMatch()) {
+ 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;
@@ -386,47 +1168,47 @@ QString itemType(const QString &type)
return t;
}
-QString itemDeclaration(const CfgEntry *e, const KConfigXTParameters &cfg)
+static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg)
{
if (cfg.itemAccessors) {
return QString();
}
QString type;
- if (!e->signalList.isEmpty()) {
+ if (!e->signalList().isEmpty()) {
type = QStringLiteral("KConfigCompilerSignallingItem");
} else {
- type = cfg.inherits + "::Item" + itemType(e->type);
+ type = cfg.inherits + "::Item" + itemType(e->type());
}
- QString fCap = e->name;
+ QString fCap = e->name();
fCap[0] = fCap[0].toUpper();
return " " + type + " *item" + fCap +
- ( (!e->param.isEmpty())?(QStringLiteral("[%1]").arg(e->paramMax+1)) : QString()) + ";\n";
+ ( (!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
-QString itemVar(const CfgEntry *e, const KConfigXTParameters &cfg)
+static QString itemVar(const CfgEntry *e, const CfgConfig &cfg)
{
QString result;
if (cfg.itemAccessors) {
if (!cfg.dpointer) {
- result = 'm' + e->name + "Item";
+ result = 'm' + e->name() + "Item";
result[1] = result[1].toUpper();
} else {
- result = e->name + "Item";
+ result = e->name() + "Item";
result[0] = result[0].toLower();
}
} else {
- result = "item" + e->name;
+ result = "item" + e->name();
result[4] = result[4].toUpper();
}
return result;
}
-QString itemPath(const CfgEntry *e, const KConfigXTParameters &cfg)
+static QString itemPath(const CfgEntry *e, const CfgConfig &cfg)
{
QString result;
if (cfg.dpointer) {
@@ -438,18 +1220,18 @@ QString itemPath(const CfgEntry *e, const KConfigXTParameters &cfg)
}
QString newItem(const CfgEntry* entry, const QString &key, const QString& defaultValue,
- const KConfigXTParameters &cfg, const QString &param) {
+ const CfgConfig &cfg, const QString &param = QString()) {
- QList<Signal> sigs = entry->signalList;
+ QList<Signal> 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;
+ 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 (entry->type() == QLatin1String("Enum")) {
+ t += ", values" + entry->name();
}
if (!defaultValue.isEmpty()) {
t += QLatin1String(", ") + defaultValue;
@@ -473,11 +1255,11 @@ QString newItem(const CfgEntry* entry, const QString &key, const QString& defaul
QString paramString(const QString &s, const CfgEntry *e, int i)
{
QString result = s;
- QString needle = "$(" + e->param + ')';
+ QString needle = "$(" + e->param() + ')';
if (result.contains(needle)) {
QString tmp;
- if (e->paramType == QLatin1String("Enum")) {
- tmp = e->paramValues.at(i);
+ if (e->paramType() == QLatin1String("Enum")) {
+ tmp = e->paramValues().at(i);
} else {
tmp = QString::number(i);
}
@@ -507,12 +1289,12 @@ QString paramString(const QString &group, const QList<Param> &parameters)
return "QStringLiteral( \"" + paramString + "\" )" + arguments;
}
-QString translatedString(const KConfigXTParameters &cfg, const QString &string, const QString &context, const QString &param, const QString &paramValue)
+QString translatedString(const CfgConfig &cfg, const QString &string, const QString &context = QString(), const QString &param = QString(), const QString &paramValue = QString())
{
QString result;
switch (cfg.translationSystem) {
- case KConfigXTParameters::QtTranslation:
+ case CfgConfig::QtTranslation:
if (!context.isEmpty()) {
result += "/*: " + context + " */ QCoreApplication::translate(\"";
} else {
@@ -521,7 +1303,7 @@ QString translatedString(const KConfigXTParameters &cfg, const QString &string,
result += cfg.className + "\", ";
break;
- case KConfigXTParameters::KdeTranslation:
+ case CfgConfig::KdeTranslation:
if (!cfg.translationDomain.isEmpty() && !context.isEmpty()) {
result += "i18ndc(" + quoteString(cfg.translationDomain) + ", " + quoteString(context) + ", ";
} else if (!cfg.translationDomain.isEmpty()) {
@@ -548,36 +1330,62 @@ QString translatedString(const KConfigXTParameters &cfg, const QString &string,
}
/* int i is the value of the parameter */
-QString userTextsFunctions(const CfgEntry *e, const KConfigXTParameters &cfg, QString itemVarStr, const QString &i)
+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()) {
+ if (!e->label().isEmpty()) {
txt += " " + itemVarStr + "->setLabel( ";
- txt += translatedString(cfg, e->label, e->labelContext, e->param, i);
+ txt += translatedString(cfg, e->label(), e->labelContext(), e->param(), i);
txt += QLatin1String(" );\n");
}
- if (!e->toolTip.isEmpty()) {
+ if (!e->toolTip().isEmpty()) {
txt += " " + itemVarStr + "->setToolTip( ";
- txt += translatedString(cfg, e->toolTip, e->toolTipContext, e->param, i);
+ txt += translatedString(cfg, e->toolTip(), e->toolTipContext(), e->param(), i);
txt += QLatin1String(" );\n");
}
- if (!e->whatsThis.isEmpty()) {
+ if (!e->whatsThis().isEmpty()) {
txt += " " + itemVarStr + "->setWhatsThis( ";
- txt += translatedString(cfg, e->whatsThis, e->whatsThisContext, e->param, i);
+ 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
-//TODO: Fix add Debug Method, it should also take the debug string.
-void addDebugMethod(QTextStream &out, const KConfigXTParameters &cfg, const QString &n)
+
+void addDebugMethod(QTextStream &out, const CfgConfig &cfg, const QString &n)
{
if (cfg.qCategoryLoggingName.isEmpty()) {
out << " qDebug() << \"" << setFunction(n);
@@ -586,30 +1394,101 @@ void addDebugMethod(QTextStream &out, const KConfigXTParameters &cfg, const QStr
}
}
+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(const CfgEntry *e)
+QString memberGetDefaultBody(CfgEntry *e)
{
- QString result = e->code;
+ QString result = e->code();
QTextStream out(&result, QIODevice::WriteOnly);
out << endl;
- if (!e->param.isEmpty()) {
+ if (!e->param().isEmpty()) {
out << " switch (i) {" << endl;
- for (int i = 0; i <= e->paramMax; ++i) {
- if (!e->paramDefaultValues[i].isEmpty()) {
- out << " case " << i << ": return " << e->paramDefaultValues[i] << ';' << endl;
+ for (int i = 0; i <= e->paramMax(); ++i) {
+ if (!e->paramDefaultValue(i).isEmpty()) {
+ out << " case " << i << ": return " << e->paramDefaultValue(i) << ';' << endl;
}
}
- QString defaultValue = e->defaultValue;
-
out << " default:" << endl;
- out << " return " << defaultValue.replace("$(" + e->param + ')', QLatin1String("i")) << ';' << endl;
+ out << " return " << e->defaultValue().replace("$(" + e->param() + ')', QLatin1String("i")) << ';' << endl;
out << " }" << endl;
} else {
- out << " return " << e->defaultValue << ';';
+ out << " return " << e->defaultValue() << ';';
}
return result;
@@ -618,13 +1497,13 @@ QString memberGetDefaultBody(const CfgEntry *e)
// returns the item accesor implementation
// which should go in the h file if inline
// or the cpp file if not inline
-QString itemAccessorBody(const CfgEntry *e, const KConfigXTParameters &cfg)
+QString itemAccessorBody(CfgEntry *e, const CfgConfig &cfg)
{
QString result;
QTextStream out(&result, QIODevice::WriteOnly);
out << "return " << itemPath(e, cfg);
- if (!e->param.isEmpty()) {
+ if (!e->param().isEmpty()) {
out << "[i]";
}
out << ";" << endl;
@@ -650,29 +1529,30 @@ QString indent(QString text, int spaces)
return result;
}
-bool hasErrors(KCFGXmlParser &parser, const ParseResult& parseResult, const KConfigXTParameters &cfg)
+// 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 (cfg.className.isEmpty()) {
- cerr << "Class name missing" << endl;
- return true;
- }
-
- if (cfg.singleton && !parseResult.parameters.isEmpty()) {
- cerr << "Singleton class can not have parameters" << endl;
- return true;
- }
-
- if (!parseResult.cfgFileName.isEmpty() && parseResult.cfgFileNameArg) {
- cerr << "Having both a fixed filename and a filename as argument is not possible." << endl;
- return true;
+ if (!p_ns.isEmpty()) {
+ const QStringList nameSpaces = p_ns.split(QStringLiteral("::"));
+ for (const QString &ns : nameSpaces) {
+ p_out << "namespace " << ns << " {" << endl;
+ }
+ p_out << endl;
}
+}
- if (parseResult.entries.isEmpty()) {
- cerr << "No entries." << endl;
- return true;
+// 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;
}
-
- return false;
}
int main(int argc, char **argv)
@@ -681,22 +1561,22 @@ int main(int argc, char **argv)
app.setApplicationName(QStringLiteral("kconfig_compiler"));
app.setApplicationVersion(QStringLiteral(KCONFIG_VERSION_STRING));
- QString inputFilename, codegenFilename;
+ validNameRegexp = new QRegularExpression(QRegularExpression::anchoredPattern(
+ QStringLiteral("[a-zA-Z_][a-zA-Z0-9_]*")));
- QCommandLineOption targetDirectoryOption(QStringList { QStringLiteral("d"), QStringLiteral("directory") },
- QCoreApplication::translate("main", "Directory to generate files in [.]"),
- QCoreApplication::translate("main", "directory"), QStringLiteral("."));
-
- QCommandLineOption licenseOption (
- QStringList { QStringLiteral("l"), QStringLiteral("license") },
- QCoreApplication::translate("main", "Display software license."));
+ 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();
@@ -704,7 +1584,7 @@ int main(int argc, char **argv)
parser.process(app);
if (parser.isSet(licenseOption)) {
- cout << "Copyright 2003 Cornelius Schumacher, Waldo Bastian, Zack Rusin," << endl;
+ 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;
@@ -715,18 +1595,16 @@ int main(int argc, char **argv)
const QStringList args = parser.positionalArguments();
if (args.count() < 2) {
- cerr << "Too few arguments." << endl;
- return 1;
+ cerr << "Too few arguments." << endl;
+ return 1;
}
-
if (args.count() > 2) {
- cerr << "Too many arguments." << endl;
- return 1;
+ cerr << "Too many arguments." << endl;
+ return 1;
}
inputFilename = args.at(0);
codegenFilename = args.at(1);
- // TODO: Transform baseDir into a helper.
QString baseDir = parser.value(targetDirectoryOption);
#ifdef Q_OS_WIN
@@ -736,34 +1614,1124 @@ int main(int argc, char **argv)
#endif
baseDir.append("/");
- KConfigXTParameters cfg(codegenFilename);
+ 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);
- KCFGXmlParser xmlParser(cfg, inputFilename);
-
- // The Xml Parser aborts in the case of an error, so if we get
- // to parseResult, we have a working Xml file.
- xmlParser.start();
+ QFile input(inputFilename);
- ParseResult parseResult = xmlParser.getParseResult();
+ 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;
+ }
- if (hasErrors(xmlParser, parseResult, cfg)) {
+ QDomElement cfgElement = doc.documentElement();
+
+ if (cfgElement.isNull()) {
+ cerr << "No document in kcfg file" << endl;
return 1;
}
- // TODO: Move this to somewhere saner.
- for (const auto &signal : qAsConst(parseResult.signalList)) {
- parseResult.hasNonModifySignals |= !signal.modify;
+ QString cfgFileName;
+ bool cfgFileNameArg = false;
+ QList<Param> parameters;
+ QList<Signal> signalList;
+ QStringList includes;
+
+ QList<CfgEntry *> 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;
}
- // remove '.kcfg' from the name.
- const QString baseName = inputFilename.mid(0, inputFilename.size()-5);
- KConfigHeaderGenerator headerGenerator(baseName, baseDir, cfg, parseResult);
- headerGenerator.start();
- headerGenerator.save();
+ 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 <qglobal.h>" << endl;
+ }
+
+ if (cfg.inherits == QLatin1String("KCoreConfigSkeleton")) {
+ h << "#include <kcoreconfigskeleton.h>" << endl;
+ } else {
+ h << "#include <kconfigskeleton.h>" << endl;
+ }
+
+ h << "#include <QCoreApplication>" << endl;
+ h << "#include <QDebug>" << 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<CfgEntry *>::ConstIterator itEntry;
+ for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) {
+ const CfgEntry::Choices &choices = (*itEntry)->choices();
+ const QList<CfgEntry::Choice> chlist = choices.choices;
+ if (!chlist.isEmpty()) {
+ QStringList values;
+ QList<CfgEntry::Choice>::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<Param>::ConstIterator it = parameters.constBegin();
+ it != parameters.constEnd(); ++it) {
+ if (it != parameters.constBegin()) {
+ h << ",";
+ }
+ h << " " << param((*it).type) << " " << (*it).name;
+ }
+ if (cfg.parentInConstructor) {
+ if (cfgFileNameArg || !parameters.isEmpty()) {
+ h << ",";
+ }
+ h << " QObject *parent = nullptr";
+ }
+ 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 << ' ' << getFunction(n);
+ h << " READ " << getFunction(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<Signal>::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" <<
+ #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
+ hex
+ #else
+ Qt::hex
+ #endif
+ << val;
+ if (++it != itEnd) {
+ h << ",";
+ }
+ h << endl;
+ }
+ h << " };" <<
+ #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
+ dec
+ #else
+ Qt::dec
+ #endif
+ << 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<SignalArguments>::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";
+ }
+ if (cfg.parentInConstructor) {
+ if (cfgFileNameArg) {
+ h << ", ";
+ }
+ h << "QObject *parent = nullptr";
+ }
+ 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<Param>::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 \"" << 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 <klocalizedstring.h>" << endl << endl;
+ }
+
+ // Header required by singleton implementation
+ if (cfg.singleton) {
+ cpp << "#include <qglobal.h>" << endl << "#include <QFile>" << endl << endl;
+ }
+ if (cfg.singleton && cfgFileNameArg) {
+ cpp << "#include <QDebug>" << 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 isString) {
+ 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 (isString) {
+ cpp << "KSharedConfig::openConfig(" << arg << ")";
+ } else {
+ cpp << "std::move(" << 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<Param>::ConstIterator it = parameters.constBegin();
+ it != parameters.constEnd(); ++it) {
+ if (it != parameters.constBegin()) {
+ cpp << ",";
+ }
+ cpp << " " << param((*it).type) << " " << (*it).name;
+ }
+
+ if (cfg.parentInConstructor) {
+ if (cfgFileNameArg || !parameters.isEmpty()) {
+ cpp << ",";
+ }
+ cpp << " QObject *parent";
+ }
+ cpp << " )" << endl;
+
+ cpp << " : " << cfg.inherits << "(";
+ if (!cfgFileName.isEmpty()) {
+ cpp << " QStringLiteral( \"" << cfgFileName << "\" ";
+ }
+ if (cfgFileNameArg) {
+ if (! cfg.forceStringFilename) {
+ cpp << " std::move( config ) ";
+ } else {
+ cpp << " config ";
+ }
+ }
+ if (!cfgFileName.isEmpty()) {
+ cpp << ") ";
+ }
+ cpp << ")" << endl;
+
+ // Store parameters
+ for (QList<Param>::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.parentInConstructor) {
+ cpp << " setParent(parent);" << 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++
+ // https://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<KConfigCompilerSignallingItem::NotifyFunction>(&"
+ << 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<CfgEntry::Choice> choices = (*itEntry)->choices().choices;
+ QList<CfgEntry::Choice>::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<SignalArguments>::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;
+ }
- KConfigSourceGenerator sourceGenerator(baseName, baseDir, cfg, parseResult);
- sourceGenerator.start();
- sourceGenerator.save();
+ // clear entries list
+ qDeleteAll(entries);
- qDeleteAll(parseResult.entries);
+ implementation.close();
}