aboutsummaryrefslogtreecommitdiff
path: root/src/kconfig_compiler/kconfig_compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/kconfig_compiler/kconfig_compiler.cpp')
-rw-r--r--src/kconfig_compiler/kconfig_compiler.cpp2221
1 files changed, 133 insertions, 2088 deletions
diff --git a/src/kconfig_compiler/kconfig_compiler.cpp b/src/kconfig_compiler/kconfig_compiler.cpp
index 848595f2..146ff884 100644
--- a/src/kconfig_compiler/kconfig_compiler.cpp
+++ b/src/kconfig_compiler/kconfig_compiler.cpp
@@ -34,15 +34,19 @@
#include <QDomAttr>
#include <QRegularExpression>
#include <QStringList>
-
-#include <qcommandlineparser.h>
-#include <qcommandlineoption.h>
+#include <QCommandLineParser>
+#include <QCommandLineOption>
#include <ostream>
#include <iostream>
#include <stdlib.h>
#include "../../kconfig_version.h"
+#include "KConfigParameters.h"
+#include "KConfigCommonStructs.h"
+#include "KConfigHeaderGenerator.h"
+#include "KConfigSourceGenerator.h"
+#include "KConfigXmlParser.h"
namespace
{
@@ -50,444 +54,7 @@ QTextStream cout(stdout);
QTextStream cerr(stderr);
}
-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 varName(const QString &n, const KConfigParameters &cfg)
{
QString result;
if (!cfg.dpointer) {
@@ -500,7 +67,7 @@ static QString varName(const QString &n, const CfgConfig &cfg)
return result;
}
-static QString varPath(const QString &n, const CfgConfig &cfg)
+QString varPath(const QString &n, const KConfigParameters &cfg)
{
QString result;
if (cfg.dpointer) {
@@ -511,14 +78,14 @@ static QString varPath(const QString &n, const CfgConfig &cfg)
return result;
}
-static QString enumName(const QString &n)
+QString enumName(const QString &n)
{
QString result = QLatin1String("Enum") + n;
result[4] = result[4].toUpper();
return result;
}
-static QString enumName(const QString &n, const CfgEntry::Choices &c)
+QString enumName(const QString &n, const CfgEntry::Choices &c)
{
QString result = c.name();
if (result.isEmpty()) {
@@ -528,11 +95,11 @@ static QString enumName(const QString &n, const CfgEntry::Choices &c)
return result;
}
-static QString enumType(const CfgEntry *e, bool globalEnums)
+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");
}
@@ -541,7 +108,7 @@ static QString enumType(const CfgEntry *e, bool globalEnums)
return result;
}
-static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
+QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
{
QString result = c.name();
if (result.isEmpty()) {
@@ -555,7 +122,7 @@ static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
return result;
}
-static QString setFunction(const QString &n, const QString &className = QString())
+QString setFunction(const QString &n, const QString &className)
{
QString result = QLatin1String("set") + n;
result[3] = result[3].toUpper();
@@ -566,12 +133,12 @@ static QString setFunction(const QString &n, const QString &className = QString(
return result;
}
-static QString changeSignalName(const QString &n)
+QString changeSignalName(const QString &n)
{
return n+QStringLiteral("Changed");
}
-static QString getDefaultFunction(const QString &n, const QString &className = QString())
+QString getDefaultFunction(const QString &n, const QString &className)
{
QString result = QLatin1String("default") + n + QLatin1String("Value");
result[7] = result[7].toUpper();
@@ -582,7 +149,7 @@ static QString getDefaultFunction(const QString &n, const QString &className = Q
return result;
}
-static QString getFunction(const QString &n, const QString &className = QString())
+QString getFunction(const QString &n, const QString &className)
{
QString result = n;
result[0] = result[0].toLower();
@@ -593,7 +160,7 @@ static QString getFunction(const QString &n, const QString &className = QString(
return result;
}
-static void addQuotes(QString &s)
+void addQuotes(QString &s)
{
if (!s.startsWith(QLatin1Char('"'))) {
s.prepend(QLatin1Char('"'));
@@ -613,7 +180,7 @@ static QString quoteString(const QString &s)
return QLatin1Char('\"') + r + QLatin1Char('\"');
}
-static QString literalString(const QString &s)
+QString literalString(const QString &s)
{
bool isAscii = true;
for (int i = s.length(); i--;)
@@ -628,20 +195,8 @@ static QString literalString(const QString &s)
}
}
-static QString dumpNode(const QDomNode &node)
-{
- QString msg;
- QTextStream s(&msg, QIODevice::WriteOnly);
- node.save(s, 0);
-
- msg = msg.simplified();
- if (msg.length() > 40) {
- return msg.left(37) + QLatin1String("...");
- }
- return msg;
-}
-static QString signalEnumName(const QString &signalName)
+QString signalEnumName(const QString &signalName)
{
QString result;
result = QLatin1String("signal") + signalName;
@@ -650,345 +205,8 @@ static 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;
- }
-
- 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)
+bool isUnsigned(const QString &type)
{
if (type == QLatin1String("UInt")) {
return true;
@@ -1168,47 +386,47 @@ QString itemType(const QString &type)
return t;
}
-static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg)
+QString itemDeclaration(const CfgEntry *e, const KConfigParameters &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
-static QString itemVar(const CfgEntry *e, const CfgConfig &cfg)
+QString itemVar(const CfgEntry *e, const KConfigParameters &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;
}
-static QString itemPath(const CfgEntry *e, const CfgConfig &cfg)
+QString itemPath(const CfgEntry *e, const KConfigParameters &cfg)
{
QString result;
if (cfg.dpointer) {
@@ -1220,18 +438,18 @@ static QString itemPath(const CfgEntry *e, const CfgConfig &cfg)
}
QString newItem(const CfgEntry* entry, const QString &key, const QString& defaultValue,
- const CfgConfig &cfg, const QString &param = QString()) {
+ const KConfigParameters &cfg, const QString &param) {
- 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;
@@ -1255,11 +473,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);
}
@@ -1289,12 +507,12 @@ QString paramString(const QString &group, const QList<Param> &parameters)
return "QStringLiteral( \"" + paramString + "\" )" + arguments;
}
-QString translatedString(const CfgConfig &cfg, const QString &string, const QString &context = QString(), const QString &param = QString(), const QString &paramValue = QString())
+QString translatedString(const KConfigParameters &cfg, const QString &string, const QString &context, const QString &param, const QString &paramValue)
{
QString result;
switch (cfg.translationSystem) {
- case CfgConfig::QtTranslation:
+ case KConfigParameters::QtTranslation:
if (!context.isEmpty()) {
result += "/*: " + context + " */ QCoreApplication::translate(\"";
} else {
@@ -1303,7 +521,7 @@ QString translatedString(const CfgConfig &cfg, const QString &string, const QStr
result += cfg.className + "\", ";
break;
- case CfgConfig::KdeTranslation:
+ case KConfigParameters::KdeTranslation:
if (!cfg.translationDomain.isEmpty() && !context.isEmpty()) {
result += "i18ndc(" + quoteString(cfg.translationDomain) + ", " + quoteString(context) + ", ";
} else if (!cfg.translationDomain.isEmpty()) {
@@ -1330,62 +548,36 @@ QString translatedString(const CfgConfig &cfg, const QString &string, const QStr
}
/* int i is the value of the parameter */
-QString userTextsFunctions(CfgEntry *e, const CfgConfig &cfg, QString itemVarStr = QString(), const QString &i = QString())
+QString userTextsFunctions(const CfgEntry *e, const KConfigParameters &cfg, QString itemVarStr, const QString &i)
{
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
-
-void addDebugMethod(QTextStream &out, const CfgConfig &cfg, const QString &n)
+//TODO: Fix add Debug Method, it should also take the debug string.
+void addDebugMethod(QTextStream &out, const KConfigParameters &cfg, const QString &n)
{
if (cfg.qCategoryLoggingName.isEmpty()) {
out << " qDebug() << \"" << setFunction(n);
@@ -1394,101 +586,30 @@ void addDebugMethod(QTextStream &out, const CfgConfig &cfg, const QString &n)
}
}
-QString memberMutatorBody(CfgEntry *e, const CfgConfig &cfg)
-{
- QString result;
- QTextStream out(&result, QIODevice::WriteOnly);
- QString n = e->name();
- QString t = e->type();
-
- if (!e->minValue().isEmpty()) {
- if (e->minValue() != QLatin1String("0") || !isUnsigned(t)) { // skip writing "if uint<0" (#187579)
- out << "if (v < " << e->minValue() << ")" << endl;
- out << "{" << endl;
- addDebugMethod(out, cfg, n);
- out << ": value \" << v << \" is less than the minimum value of ";
- out << e->minValue() << "\";" << endl;
- out << " v = " << e->minValue() << ";" << endl;
- out << "}" << endl;
- }
- }
-
- if (!e->maxValue().isEmpty()) {
- out << endl << "if (v > " << e->maxValue() << ")" << endl;
- out << "{" << endl;
- addDebugMethod(out, cfg, n);
- out << ": value \" << v << \" is greater than the maximum value of ";
- out << e->maxValue() << "\";" << endl;
- out << " v = " << e->maxValue() << ";" << endl;
- out << "}" << endl << endl;
- }
-
- const QString varExpression = This + varPath(n, cfg) + (e->param().isEmpty() ? QString() : QStringLiteral("[i]"));
-
- const bool hasBody = !e->signalList().empty() || cfg.generateProperties;
- out << "if (";
- if (hasBody) {
- out << "v != " << varExpression << " && ";
- }
- out << "!" << This << "isImmutable( QStringLiteral( \"";
- if (!e->param().isEmpty()) {
- out << e->paramName().replace("$(" + e->param() + ")", QLatin1String("%1")) << "\" ).arg( ";
- if (e->paramType() == QLatin1String("Enum")) {
- out << "QLatin1String( ";
-
- if (cfg.globalEnums) {
- out << enumName(e->param()) << "ToString[i]";
- } else {
- out << enumName(e->param()) << "::enumToString[i]";
- }
-
- out << " )";
- } else {
- out << "i";
- }
- out << " )";
- } else {
- out << n << "\" )";
- }
- out << " ))" << (hasBody ? " {" : "") << endl;
- out << " " << varExpression << " = v;" << endl;
-
- const auto listSignal = e->signalList();
- for (const Signal &signal : listSignal) {
- if (signal.modify) {
- out << " Q_EMIT " << This << signal.name << "();" << endl;
- } else {
- out << " " << This << varPath(QStringLiteral("settingsChanged"), cfg) << " |= " << signalEnumName(signal.name) << ";" << endl;
- }
- }
- if (hasBody) {
- out << "}" << endl;
- }
-
- return result;
-}
// returns the member get default implementation
// which should go in the h file if inline
// or the cpp file if not inline
-QString memberGetDefaultBody(CfgEntry *e)
+QString memberGetDefaultBody(const 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->paramDefaultValue(i).isEmpty()) {
- out << " case " << i << ": return " << e->paramDefaultValue(i) << ';' << endl;
+ for (int i = 0; i <= e->paramMax; ++i) {
+ if (!e->paramDefaultValues[i].isEmpty()) {
+ out << " case " << i << ": return " << e->paramDefaultValues[i] << ';' << endl;
}
}
+ QString defaultValue = e->defaultValue;
+
out << " default:" << endl;
- out << " return " << e->defaultValue().replace("$(" + e->param() + ')', QLatin1String("i")) << ';' << endl;
+ out << " return " << defaultValue.replace("$(" + e->param + ')', QLatin1String("i")) << ';' << endl;
out << " }" << endl;
} else {
- out << " return " << e->defaultValue() << ';';
+ out << " return " << e->defaultValue << ';';
}
return result;
@@ -1497,13 +618,13 @@ QString memberGetDefaultBody(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(CfgEntry *e, const CfgConfig &cfg)
+QString itemAccessorBody(const CfgEntry *e, const KConfigParameters &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;
@@ -1529,30 +650,42 @@ QString indent(QString text, int spaces)
return result;
}
-// adds as many 'namespace foo {' lines to p_out as
-// there are namespaces in p_ns
-void beginNamespaces(const QString &p_ns, QTextStream &p_out)
+bool hasErrors(KConfigXmlParser &parser, const ParseResult& parseResult, const KConfigParameters &cfg)
{
- 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 (cfg.className.isEmpty()) {
+ cerr << "Class name missing" << 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;
+ 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;
+ }
+
+ /* TODO: For some reason some configuration files prefer to have *no* entries
+ * at all in it, and the generated code is mostly bogus as KConfigXT will not
+ * handle save / load / properties, etc, nothing.
+ *
+ * The first of those files that I came across are qmakebuilderconfig.kcfg from the KDevelop
+ * project.
+ * I think we should remove the possibility of creating configuration classes from configuration
+ * files that don't really have configuration in it. but I'm changing this right now to allow
+ * kdevelop files to pass.
+ *
+ * Remove for KDE 6
+ * (to make things more interesting, it failed in a code that's never used within KDevelop... )
+ */
+ if (parseResult.entries.isEmpty()) {
+ cerr << "No entries." << endl;
+ return false;
+ }
+
+ return false;
}
int main(int argc, char **argv)
@@ -1561,22 +694,22 @@ int main(int argc, char **argv)
app.setApplicationName(QStringLiteral("kconfig_compiler"));
app.setApplicationVersion(QStringLiteral(KCONFIG_VERSION_STRING));
- validNameRegexp = new QRegularExpression(QRegularExpression::anchoredPattern(
- QStringLiteral("[a-zA-Z_][a-zA-Z0-9_]*")));
-
QString inputFilename, codegenFilename;
+ 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."));
+
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();
@@ -1584,7 +717,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;
@@ -1595,16 +728,18 @@ 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
@@ -1614,1124 +749,34 @@ int main(int argc, char **argv)
#endif
baseDir.append("/");
- if (!codegenFilename.endsWith(QLatin1String(".kcfgc"))) {
- cerr << "Codegen options file must have extension .kcfgc" << endl;
- return 1;
- }
- QString baseName = QFileInfo(codegenFilename).fileName();
- baseName = baseName.left(baseName.length() - 6);
-
- CfgConfig cfg = CfgConfig(codegenFilename);
-
- QFile input(inputFilename);
-
- QDomDocument doc;
- QString errorMsg;
- int errorRow;
- int errorCol;
- if (!doc.setContent(&input, &errorMsg, &errorRow, &errorCol)) {
- cerr << "Unable to load document." << endl;
- cerr << "Parse error in " << inputFilename << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl;
- return 1;
- }
-
- QDomElement cfgElement = doc.documentElement();
-
- if (cfgElement.isNull()) {
- cerr << "No document in kcfg file" << endl;
- return 1;
- }
-
- QString cfgFileName;
- bool cfgFileNameArg = false;
- QList<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;
- }
-
- 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;
- }
+ KConfigParameters cfg(codegenFilename);
- if (cfg.customAddons) {
- h << " // Include custom additions" << endl;
- h << " #include \"" << baseName << "_addons." << cfg.headerExtension << '"' << endl;
- }
+ KConfigXmlParser 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();
- h << "};" << endl << endl;
+ ParseResult parseResult = xmlParser.getParseResult();
- 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;
+ if (hasErrors(xmlParser, parseResult, cfg)) {
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;
- }
- }
+ // TODO: Move this to somewhere saner.
+ for (const auto &signal : qAsConst(parseResult.signalList)) {
+ parseResult.hasNonModifySignals |= !signal.modify;
}
- 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;
- }
+ // remove '.kcfg' from the name.
+ const QString baseName = inputFilename.mid(0, inputFilename.size()-5);
+ KConfigHeaderGenerator headerGenerator(baseName, baseDir, cfg, parseResult);
+ headerGenerator.start();
+ headerGenerator.save();
- // clear entries list
- qDeleteAll(entries);
+ KConfigSourceGenerator sourceGenerator(baseName, baseDir, cfg, parseResult);
+ sourceGenerator.start();
+ sourceGenerator.save();
- implementation.close();
+ qDeleteAll(parseResult.entries);
}