diff options
Diffstat (limited to 'src/kconfig_compiler/kconfig_compiler.cpp')
| -rw-r--r-- | src/kconfig_compiler/kconfig_compiler.cpp | 2338 | 
1 files changed, 2338 insertions, 0 deletions
| diff --git a/src/kconfig_compiler/kconfig_compiler.cpp b/src/kconfig_compiler/kconfig_compiler.cpp new file mode 100644 index 00000000..ae192eec --- /dev/null +++ b/src/kconfig_compiler/kconfig_compiler.cpp @@ -0,0 +1,2338 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*- +/* +    This file is part of KDE. + +    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> + +    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. +*/ + +// Compiling this file with this flag is just crazy +#undef QT_NO_CAST_FROM_ASCII + +#include <QtCore/QCoreApplication> +#include <QtCore/QFile> +#include <QtCore/QFileInfo> +#include <QtCore/QSettings> +#include <QtCore/QTextStream> +#include <QtXml/QDomAttr> +#include <QtCore/QRegExp> +#include <QtCore/QStringList> + +#include <ostream> +#include <iostream> +#include <stdlib.h> + +namespace +{ +  QTextStream cout(stdout); +  QTextStream cerr(stderr); +} + +static void parseArgs(const QStringList &args, QString &directory, QString &file1, QString &file2) +{ +    int fileCount = 0; +    directory = QChar::fromLatin1('.'); + +    for (int i = 1; i < args.count(); ++i) { +        if (args.at(i) == QLatin1String("-d") ||  args.at(i) == QLatin1String("--directory")) { +            if (i + 1 > args.count()) { +                cerr << args.at(i) << " needs an argument" << endl; +                exit(1); +            } +            directory = args.at(++i); +        } else if (args.at(i).startsWith(QLatin1String("-d"))) { +            directory = args.at(i).mid(2); +        } else if (args.at(i) == QLatin1String("--help") || args.at(i) == QLatin1String("-h")) { +            cout << "Options:" << endl; +            cout << "  -L --license              Display software license" << endl; +            cout << "  -d, --directory <dir>     Directory to generate files in [.]" << endl; +            cout << "  -h, --help                Display this help" << endl; +            cout << endl; +            cout << "Arguments:" << endl; +            cout << "      file.kcfg                 Input kcfg XML file" << endl; +            cout << "      file.kcfgc                Code generation options file" << endl; +            exit(0); +        } else if (args.at(i) == QLatin1String("--license") || args.at(i) == QLatin1String("-L")) { +            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; +            cout << "under the terms of the GNU Library Public License." << endl; +            cout << "For more information about these matters, see the file named COPYING." << endl; +            exit(0); +        } else if (args.at(i).startsWith(QLatin1Char('-'))) { +            cerr << "Unknown option: " << args.at(i) << endl; +            exit(1); +        } else if (fileCount == 0) { +            file1 = args.at(i); +            ++fileCount; +        } else if (fileCount == 1) { +            file2 = args.at(i); +            ++fileCount; +        } else { +            cerr << "Too many arguments" << endl; +            exit(1); +        } +    } +    if (fileCount < 2) { +        cerr << "Too few arguments" << endl; +        exit(1); +    } +} + +QStringList allNames; +QRegExp *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("NameSpace").toString(); +    className = codegenConfig.value("ClassName").toString(); +    if ( className.isEmpty() ) { +      cerr << "Class name missing" << endl; +      exit(1); +    } +    inherits = codegenConfig.value("Inherits").toString(); +    if ( inherits.isEmpty() ) inherits = "KConfigSkeleton"; +    visibility = codegenConfig.value("Visibility").toString(); +    if ( !visibility.isEmpty() ) visibility += ' '; +    forceStringFilename = codegenConfig.value("ForceStringFilename", false).toBool(); +    singleton = codegenConfig.value("Singleton", false).toBool(); +    staticAccessors = singleton; +    customAddons = codegenConfig.value("CustomAdditions", false).toBool(); +    memberVariables = codegenConfig.value("MemberVariables").toString(); +    dpointer = (memberVariables == "dpointer"); +    headerIncludes = codegenConfig.value("IncludeFiles", QStringList()).toStringList(); +    sourceIncludes = codegenConfig.value("SourceIncludeFiles", QStringList()).toStringList(); +    mutators = codegenConfig.value("Mutators", QStringList()).toStringList(); +    allMutators = ((mutators.count() == 1) && (mutators.at(0).toLower() == "true")); +    itemAccessors = codegenConfig.value("ItemAccessors", false).toBool(); +    setUserTexts = codegenConfig.value("SetUserTexts", false).toBool(); +    defaultGetters = codegenConfig.value("DefaultValueGetters", QStringList()).toStringList(); +    allDefaultGetters = (defaultGetters.count() == 1) && (defaultGetters.at(0).toLower() == "true"); +    globalEnums = codegenConfig.value("GlobalEnums", false).toBool(); +    useEnumTypes = codegenConfig.value("UseEnumTypes", false).toBool(); + +    const QString trString = codegenConfig.value("TranslationSystem").toString().toLower(); +    if ( trString == "kde" ) { +        translationSystem = KdeTranslation; +    } else { +        if ( !trString.isEmpty() && trString != "qt" ) { +            cerr << "Unknown translation system, falling back to Qt tr()" << endl; +        } +        translationSystem = QtTranslation; +    } +  } + +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 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; +  bool allMutators; +  bool setUserTexts; +  bool allDefaultGetters; +  bool dpointer; +  bool globalEnums; +  bool useEnumTypes; +  bool itemAccessors; +  TranslationSystem translationSystem; +}; + + +struct SignalArguments +{ +      QString type; +      QString variableName; +}; + +class Signal { +public: +  QString name; +  QString label; +  QList<SignalArguments> arguments; +}; + + + + +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), 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 ) { +    result = QChar::fromLatin1('m') + n; +    result[1] = result[1].toUpper(); +  } +  else { +    result = n; +    result[0] = result[0].toLower(); +  } +  return result; +} + +static QString varPath(const QString &n, const CfgConfig &cfg) +{ +  QString result; +  if ( cfg.dpointer ) { +    result = "d->"+varName(n, cfg); +  } +  else { +    result = varName(n, cfg); +  } +  return result; +} + +static QString enumName(const QString &n) +{ +  QString result = QString::fromLatin1("Enum") + n; +  result[4] = result[4].toUpper(); +  return result; +} + +static QString enumName(const QString &n, const CfgEntry::Choices &c) +{ +  QString result = c.name(); +  if ( result.isEmpty() ) +  { +    result = QString::fromLatin1("Enum") + n; +    result[4] = result[4].toUpper(); +  } +  return result; +} + +static QString enumType(const CfgEntry *e, bool globalEnums) +{ +  QString result = e->choices().name(); +  if ( result.isEmpty() ) +  { +    result = QString::fromLatin1("Enum") + e->name(); +    if( !globalEnums ) +        result += QString::fromLatin1("::type"); +    result[4] = result[4].toUpper(); +  } +  return result; +} + +static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c) +{ +  QString result = c.name(); +  if ( result.isEmpty() ) +  { +    result = QString::fromLatin1("Enum") + n + QString::fromLatin1("::"); +    result[4] = result[4].toUpper(); +  } +  else if ( c.external() ) +    result = c.externalQualifier(); +  else +    result.clear(); +  return result; +} + +static QString setFunction(const QString &n, const QString &className = QString()) +{ +  QString result = QString::fromLatin1("set") + n; +  result[3] = result[3].toUpper(); + +  if ( !className.isEmpty() ) +    result = className + QString::fromLatin1("::") + result; +  return result; +} + +static QString getDefaultFunction(const QString &n, const QString &className = QString()) +{ +  QString result = QString::fromLatin1("default") +  n + QString::fromLatin1("Value"); +  result[7] = result[7].toUpper(); + +  if ( !className.isEmpty() ) +    result = className + QString::fromLatin1("::") + result; +  return result; +} + +static QString getFunction(const QString &n, const QString &className = QString()) +{ +  QString result = n; +  result[0] = result[0].toLower(); + +  if ( !className.isEmpty() ) +    result = className + QString::fromLatin1("::") + result; +  return result; +} + + +static void addQuotes( QString &s ) +{ +  if ( !s.startsWith( QLatin1Char('"') ) ) +    s.prepend( QLatin1Char('"') ); +  if ( !s.endsWith( QLatin1Char('"') ) ) +    s.append( QLatin1Char('"') ); +} + +static QString quoteString( const QString &s ) +{ +  QString r = s; +  r.replace( QLatin1Char('\\'), QLatin1String("\\\\") ); +  r.replace( QLatin1Char('\"'), QLatin1String("\\\"") ); +  r.remove( QLatin1Char('\r') ); +  r.replace( QLatin1Char('\n'), QLatin1String("\\n\"\n\"") ); +  return QLatin1Char('\"') + r + QLatin1Char('\"'); +} + +static QString literalString( const QString &s ) +{ +  bool isAscii = true; +  for(int i = s.length(); i--;) +     if (s[i].unicode() > 127) isAscii = false; + +  if (isAscii) +     return QString::fromLatin1("QLatin1String( ") + quoteString(s) + QString::fromLatin1(" )"); +  else +     return QString::fromLatin1("QString::fromUtf8( ") + quoteString(s) + QString::fromLatin1(" )"); +} + +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) + QString::fromLatin1("..."); +  return msg; +} + +static QString filenameOnly(const QString& path) +{ +   int i = path.lastIndexOf(QRegExp(QLatin1String("[/\\]"))); +   if (i >= 0) +      return path.mid(i+1); +   return path; +} + +static QString signalEnumName(const QString &signalName) +{ +  QString result; +  result = QString::fromLatin1("signal") + signalName; +  result[6] = result[6].toUpper(); + +  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 = QString::fromLatin1("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 == "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 = QString::fromLatin1("default") + name; + +    } else if ( type == QLatin1String("Color") && !defaultValue.isEmpty() ) { +      QRegExp colorRe(QLatin1String("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?")); +      if (colorRe.exactMatch(defaultValue)) +      { +        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 = QString::fromLatin1("default") + name; +    } +} + + +CfgEntry *parseEntry( const QString &group, const QDomElement &element, const CfgConfig &cfg ) +{ +  bool defaultCode = false; +  QString type = element.attribute( "type" ); +  QString name = element.attribute( "name" ); +  QString key = element.attribute( "key" ); +  QString hidden = element.attribute( "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 == "label" ) { +      label = e.text(); +      labelContext = e.attribute( "context" ); +    } +    else if ( tag == "tooltip" ) { +      toolTip = e.text(); +      toolTipContext = e.attribute( "context" ); +    } +    else if ( tag == "whatsthis" ) { +      whatsThis = e.text(); +      whatsThisContext = e.attribute( "context" ); +    } +    else if ( tag == "min" ) minValue = e.text(); +    else if ( tag == "max" ) maxValue = e.text(); +    else if ( tag == "code" ) code = e.text(); +    else if ( tag == "parameter" ) +    { +      param = e.attribute( "name" ); +      paramType = e.attribute( "type" ); +      if ( param.isEmpty() ) { +        cerr << "Parameter must have a name: " << dumpNode(e) << endl; +        return 0; +      } +      if ( paramType.isEmpty() ) { +        cerr << "Parameter must have a type: " << dumpNode(e) << endl; +        return 0; +      } +      if ((paramType == "Int") || (paramType == "UInt")) +      { +         bool ok; +         paramMax = e.attribute("max").toInt(&ok); +         if (!ok) +         { +           cerr << "Integer parameter must have a maximum (e.g. max=\"0\"): " +                       << dumpNode(e) << endl; +           return 0; +         } +      } +      else if (paramType == "Enum") +      { +         for ( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) { +           if (e2.tagName() == "values") +           { +             for ( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) { +               if (e3.tagName() == "value") +               { +                  paramValues.append( e3.text() ); +               } +             } +             break; +           } +         } +         if (paramValues.isEmpty()) +         { +           cerr << "No values specified for parameter '" << param +                       << "'." << endl; +           return 0; +         } +         paramMax = paramValues.count()-1; +      } +      else +      { +        cerr << "Parameter '" << param << "' has type " << paramType +                    << " but must be of type int, uint or Enum." << endl; +        return 0; +      } +    } +    else if ( tag == "default" ) +    { +      if (e.attribute("param").isEmpty()) +      { +        defaultValue = e.text(); +        if (e.attribute( "code" ) == "true") +          defaultCode = true; +      } +    } +    else if ( tag == "choices" ) { +      QString name = e.attribute( "name" ); +      QString prefix = e.attribute( "prefix" ); +      QList<CfgEntry::Choice> chlist; +      for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) { +        if ( e2.tagName() == "choice" ) { +          CfgEntry::Choice choice; +          choice.name = e2.attribute( "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() == "label" ) { +              choice.label = e3.text(); +              choice.context = e3.attribute( "context" ); +            } +            if ( e3.tagName() == "tooltip" ) { +              choice.toolTip = e3.text(); +              choice.context = e3.attribute( "context" ); +            } +            if ( e3.tagName() == "whatsthis" ) { +              choice.whatsThis = e3.text(); +              choice.context = e3.attribute( "context" ); +            } +          } +          chlist.append( choice ); +        } +      } +      choices = CfgEntry::Choices( chlist, name, prefix ); +    } +   else if ( tag == "emit" ) { +    QDomNode signalNode; +    Signal signal; +    signal.name = e.attribute( "signal" ); +    signalList.append( signal); +   } +  } + + +  bool nameIsEmpty = name.isEmpty(); +  if ( nameIsEmpty && key.isEmpty() ) { +    cerr << "Entry must have a name or a key: " << dumpNode(element) << endl; +    return 0; +  } + +  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("$(")) +  { +    if (param.isEmpty()) +    { +      cerr << "Name may not be parameterized: " << name << endl; +      return 0; +    } +  } +  else +  { +    if (!param.isEmpty()) +    { +      cerr << "Name must contain '$(" << param << ")': " << name << endl; +      return 0; +    } +  } + +  if ( label.isEmpty() ) { +    label = key; +  } + +  if ( type.isEmpty() ) type = "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 == "default" ) +      { +        QString index = e.attribute("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 0; +          } +        } + +        if ((i < 0) || (i > paramMax)) +        { +          cerr << "Index '" << i << "' for default value is out of range [0, "<< paramMax<<"]." << endl; +          return 0; +        } + +        QString tmpDefaultValue = e.text(); + +        if (e.attribute( "code" ) != "true") +           preProcessDefault(tmpDefaultValue, name, type, choices, code, cfg); + +        paramDefaultValues[i] = tmpDefaultValue; +      } +    } +  } + +  if (!validNameRegexp->exactMatch(name)) +  { +    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 0; +  } + +  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 0; +  } +  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 == "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 == "UInt" )        return true; +    if ( type == "ULongLong" )   return true; +    return false; +} + +/** +  Return parameter declaration for given type. +*/ +QString param( const QString &t ) +{ +    const QString type = t.toLower(); +    if ( type == "string" )           return "const QString &"; +    else if ( type == "stringlist" )  return "const QStringList &"; +    else if ( type == "font" )        return "const QFont &"; +    else if ( type == "rect" )        return "const QRect &"; +    else if ( type == "size" )        return "const QSize &"; +    else if ( type == "color" )       return "const QColor &"; +    else if ( type == "point" )       return "const QPoint &"; +    else if ( type == "int" )         return "int"; +    else if ( type == "uint" )        return "uint"; +    else if ( type == "bool" )        return "bool"; +    else if ( type == "double" )      return "double"; +    else if ( type == "datetime" )    return "const QDateTime &"; +    else if ( type == "longlong" )    return "qint64"; +    else if ( type == "ulonglong" )   return "quint64"; +    else if ( type == "intlist" )     return "const QList<int> &"; +    else if ( type == "enum" )        return "int"; +    else if ( type == "path" )        return "const QString &"; +    else if ( type == "pathlist" )    return "const QStringList &"; +    else if ( type == "password" )    return "const QString &"; +    else if ( type == "url" )         return "const QUrl &"; +    else if ( type == "urllist" )     return "const QList<QUrl> &"; +    else { +        cerr <<"kconfig_compiler does not support type \""<< type <<"\""<<endl; +        return "QString"; //For now, but an assert would be better +    } +} + +/** +  Actual C++ storage type for given type. +*/ +QString cppType( const QString &t ) +{ +    const QString type = t.toLower(); +    if ( type == "string" )           return "QString"; +    else if ( type == "stringlist" )  return "QStringList"; +    else if ( type == "font" )        return "QFont"; +    else if ( type == "rect" )        return "QRect"; +    else if ( type == "size" )        return "QSize"; +    else if ( type == "color" )       return "QColor"; +    else if ( type == "point" )       return "QPoint"; +    else if ( type == "int" )         return "int"; +    else if ( type == "uint" )        return "uint"; +    else if ( type == "bool" )        return "bool"; +    else if ( type == "double" )      return "double"; +    else if ( type == "datetime" )    return "QDateTime"; +    else if ( type == "longlong" )    return "qint64"; +    else if ( type == "ulonglong" )   return "quint64"; +    else if ( type == "intlist" )     return "QList<int>"; +    else if ( type == "enum" )        return "int"; +    else if ( type == "path" )        return "QString"; +    else if ( type == "pathlist" )    return "QStringList"; +    else if ( type == "password" )    return "QString"; +    else if ( type == "url" )         return "QUrl"; +    else if ( type == "urllist" )     return "QList<QUrl>"; +    else { +        cerr<<"kconfig_compiler does not support type \""<< type <<"\""<<endl; +        return "QString"; //For now, but an assert would be better +    } +} + +QString defaultValue( const QString &t ) +{ +    const QString type = t.toLower(); +    if ( type == "string" )           return "\"\""; // Use empty string, not null string! +    else if ( type == "stringlist" )  return "QStringList()"; +    else if ( type == "font" )        return "QFont()"; +    else if ( type == "rect" )        return "QRect()"; +    else if ( type == "size" )        return "QSize()"; +    else if ( type == "color" )       return "QColor(128, 128, 128)"; +    else if ( type == "point" )       return "QPoint()"; +    else if ( type == "int" )         return "0"; +    else if ( type == "uint" )        return "0"; +    else if ( type == "bool" )        return "false"; +    else if ( type == "double" )      return "0.0"; +    else if ( type == "datedime" )    return "QDateTime()"; +    else if ( type == "longlong" )    return "0"; +    else if ( type == "ulonglong" )   return "0"; +    else if ( type == "intlist" )     return "QList<int>()"; +    else if ( type == "enum" )        return "0"; +    else if ( type == "path" )        return "\"\""; // Use empty string, not null string! +    else if ( type == "pathlist" )    return "QStringList()"; +    else if ( type == "password" )    return "\"\""; // Use empty string, not null string! +    else if ( type == "url" )         return "QUrl()"; +    else if ( type == "urllist" )     return "QList<QUrl>()"; +    else { +        cerr<<"Error, kconfig_compiler does not support the \""<< type <<"\" type!"<<endl; +        return "QString"; //For now, but an assert would be better +    } +} + +QString itemType( const QString &type ) +{ +  QString t; + +  t = type; +  t.replace( 0, 1, t.left( 1 ).toUpper() ); + +  return t; +} + +static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg) +{ +  if (cfg.itemAccessors) +     return QString(); + +  QString fCap = e->name(); +  fCap[0] = fCap[0].toUpper(); +  return "  "+cfg.inherits+"::Item"+itemType( e->type() ) + +         "  *item" + fCap + +         ( (!e->param().isEmpty())?(QString("[%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 result; +  if (cfg.itemAccessors) +  { +    if ( !cfg.dpointer ) +    { +      result = 'm' + e->name() + "Item"; +      result[1] = result[1].toUpper(); +    } +    else +    { +      result = e->name() + "Item"; +      result[0] = result[0].toLower(); +    } +  } +  else +  { +    result = "item" + e->name(); +    result[4] = result[4].toUpper(); +  } +  return result; +} + +static QString itemPath(const CfgEntry *e, const CfgConfig &cfg) +{ +  QString result; +  if ( cfg.dpointer ) { +    result = "d->"+itemVar(e, cfg); +  } +  else { +    result = itemVar(e, cfg); +  } +  return result; +} + +QString newItem( const QString &type, const QString &name, const QString &key, +                 const QString &defaultValue, const CfgConfig &cfg, const QString ¶m = QString()) +{ +  QString t = "new "+cfg.inherits+"::Item" + itemType( type ) + +              "( currentGroup(), " + key + ", " + varPath( name, cfg ) + param; +  if ( type == "Enum" ) t += ", values" + name; +  if ( !defaultValue.isEmpty() ) { +    t += ", "; +    if ( type == "String" ) t += defaultValue; +    else t+= defaultValue; +  } +  t += " );"; + +  return t; +} + +QString paramString(const QString &s, const CfgEntry *e, int i) +{ +  QString result = s; +  QString needle = "$("+e->param()+')'; +  if (result.contains(needle)) +  { +    QString tmp; +    if (e->paramType() == "Enum") +    { +      tmp = e->paramValues()[i]; +    } +    else +    { +      tmp = QString::number(i); +    } + +    result.replace(needle, tmp); +  } +  return result; +} + +QString paramString(const QString &group, const QList<Param> ¶meters) +{ +  QString paramString = group; +  QString arguments; +  int i = 1; +  for (QList<Param>::ConstIterator it = parameters.constBegin(); +       it != parameters.constEnd(); ++it) +  { +     if (paramString.contains("$("+(*it).name+')')) +     { +       QString tmp; +       tmp.sprintf("%%%d", i++); +       paramString.replace("$("+(*it).name+')', tmp); +       arguments += ".arg( mParam"+(*it).name+" )"; +     } +  } +  if (arguments.isEmpty()) +    return "QLatin1String( \""+group+"\" )"; + +  return "QString( QLatin1String( \""+paramString+"\" ) )"+arguments; +} + +QString translatedString(const CfgConfig &cfg, const QString &string, const QString &context = QString(), const QString ¶m = QString(), const QString ¶mValue = QString()) +{ +    QString result; + +    switch (cfg.translationSystem) { +    case CfgConfig::QtTranslation: +        if (!context.isEmpty()) { +            result+= "/*: " + context + " */ QCoreApplication::translate(\""; +        } else { +            result+= "QCoreApplication::translate(\""; +        } +        result+= cfg.className + "\", "; +        break; + +    case CfgConfig::KdeTranslation: +        if (!context.isEmpty()) { +            result+= "i18nc(" + quoteString(context) + ", "; +        } else { +            result+= "i18n("; +        } +        break; +    } + +    if (!param.isEmpty()) { +        QString resolvedString = string; +        resolvedString.replace("$("+param+')', paramValue); +        result+= quoteString(resolvedString); +    } else { +        result+= quoteString(string); +    } + +    result+= ')'; + +    return result; +} + +/* int i is the value of the parameter */ +QString userTextsFunctions( CfgEntry *e, const CfgConfig &cfg, QString itemVarStr=QString(), QString i=QString() ) +{ +  QString txt; +  if (itemVarStr.isNull()) itemVarStr=itemPath(e, cfg); +  if ( !e->label().isEmpty() ) { +    txt += "  " + itemVarStr + "->setLabel( "; +    txt += translatedString(cfg, e->label(), e->labelContext(), e->param(), i); +    txt += " );\n"; +  } +  if ( !e->toolTip().isEmpty() ) { +    txt += "  " + itemVarStr + "->setToolTip( "; +    txt += translatedString(cfg, e->toolTip(), e->toolTipContext(), e->param(), i); +    txt += " );\n"; +  } +  if ( !e->whatsThis().isEmpty() ) { +    txt += "  " + itemVarStr + "->setWhatsThis( "; +    txt += translatedString(cfg, e->whatsThis(), e->whatsThisContext(), e->param(), i); +    txt += " );\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 == "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 +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() != "0" || !isUnsigned(t)) { // skip writing "if uint<0" (#187579) +      out << "if (v < " << e->minValue() << ")" << endl; +      out << "{" << endl; +      out << "  qDebug() << \"" << setFunction(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; +    out << "  qDebug() << \"" << setFunction(n); +    out << ": value \" << v << \" is greater than the maximum value of "; +    out << e->maxValue()<< "\";" << endl; +    out << "  v = " << e->maxValue() << ";" << endl; +    out << "}" << endl << endl; +  } + +  out << "if (!" << This << "isImmutable( QString::fromLatin1( \""; +  if (!e->param().isEmpty()) +  { +    out << e->paramName().replace("$("+e->param()+")", "%1") << "\" ).arg( "; +    if ( e->paramType() == "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 << " ))" << (!e->signalList().empty() ? " {" : "") << endl; +  out << "  " << This << varPath(n, cfg); +  if (!e->param().isEmpty()) +    out << "[i]"; +  out << " = v;" << endl; + +  if ( !e->signalList().empty() ) { +    Q_FOREACH(const Signal &signal, e->signalList()) { +      out << "  " << This << varPath("settingsChanged", cfg) << " |= " << signalEnumName(signal.name) << ";" << endl; +    } +    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 result = e->code(); +  QTextStream out(&result, QIODevice::WriteOnly); +  out << endl; + +  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; +      } +    } +    out << "  default:" << endl; +    out << "    return " << e->defaultValue().replace("$("+e->param()+')', "i") << ';' << endl; +    out << "  }" << endl; +  } else { +    out << "  return " << e->defaultValue() << ';'; +  } + +  return result; +} + +// 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 result; +    QTextStream out(&result, QIODevice::WriteOnly); + +    out << "return " << itemPath(e, cfg); +    if (!e->param().isEmpty()) out << "[i]"; +    out << ";" << endl; + +    return result; +} + +//indents text adding X spaces per line +QString indent(QString text, int spaces) +{ +    QString result; +    QTextStream out(&result, QIODevice::WriteOnly); +    QTextStream in(&text, QIODevice::ReadOnly); +    QString currLine; +    while ( !in.atEnd() ) +    { +      currLine = in.readLine(); +      if (!currLine.isEmpty()) +        for (int i=0; i < spaces; i++) +          out << " "; +      out << currLine << endl; +    } +    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) +{ +  if ( !p_ns.isEmpty() ) { +    const QStringList nameSpaces = p_ns.split( "::" ); +    foreach (const QString &ns, nameSpaces ) +      p_out << "namespace " << ns << " {" << endl; +    p_out << endl; +  } +} + +// 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( "::" ) + 1; +    for ( int i = 0; i < namespaceCount; ++i ) +      p_out << "}" << endl; +    p_out << endl; +  } +} + + +int main( int argc, char **argv ) +{ +  QCoreApplication app(argc, argv); + +  validNameRegexp = new QRegExp("[a-zA-Z_][a-zA-Z0-9_]*"); + +  QString directoryName, inputFilename, codegenFilename; +  parseArgs(app.arguments(), directoryName, inputFilename, codegenFilename); + +  QString baseDir = directoryName; +#ifdef Q_OS_WIN +  if (!baseDir.endsWith('/') && !baseDir.endsWith('\\')) +#else +  if (!baseDir.endsWith('/')) +#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; +  bool hasSignals = false; + +  QList<CfgEntry*> entries; + +  for ( QDomElement e = cfgElement.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) { +    QString tag = e.tagName(); + +    if ( tag == "include" ) { +      QString includeFile = e.text(); +      if (!includeFile.isEmpty()) +        includes.append(includeFile); + +    } else if ( tag == "kcfgfile" ) { +      cfgFileName = e.attribute( "name" ); +      cfgFileNameArg = e.attribute( "arg" ).toLower() == "true"; +      for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) { +        if ( e2.tagName() == "parameter" ) { +          Param p; +          p.name = e2.attribute( "name" ); +          p.type = e2.attribute( "type" ); +          if (p.type.isEmpty()) +             p.type = "String"; +          parameters.append( p ); +        } +      } + +    } else if ( tag == "group" ) { +      QString group = e.attribute( "name" ); +      if ( group.isEmpty() ) { +        cerr << "Group without name" << endl; +        return 1; +      } +      for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) { +        if ( e2.tagName() != "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 == "signal" ) { +      QString signalName = e.attribute( "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() == "argument") { +          SignalArguments argument; +          argument.type = e2.attribute("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() == "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 + +  hasSignals = !signalList.empty(); +  QString headerFileName = baseName + ".h"; +  QString implementationFileName = baseName + ".cpp"; +  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 << "// This file is generated by kconfig_compiler 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( "::", "_" ).toUpper() + '_') : "" ) +    << cfg.className.toUpper() << "_H" << endl; +  h << "#define " << ( !cfg.nameSpace.isEmpty() ? QString (QString(cfg.nameSpace).replace( "::", "_" ).toUpper() + '_') : "" ) +    << 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.count() > 0 ) h << endl; + +  if ( !cfg.singleton && parameters.isEmpty() ) +    h << "#include <qglobal.h>" << endl; + +  if ( cfg.inherits=="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( hasSignals ) +   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( ", " ) << " };" << 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( ", " ) << ", COUNT };" << endl; +          h << "    };" << endl; +        } +      } else if ( !choices.external() ) { +        // Create a named enum +        h << "    enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << " { " << values.join( ", " ) << " };" << 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( ", " ) << " };" << endl; +        h << "    static const char* const " << enumName( (*itEntry)->param() ) << "ToString[];" << endl; +        cppPreamble += "const char* const " + cfg.className + "::" + enumName( (*itEntry)->param() ) + +           "ToString[] = { \"" + values.join( "\", \"" ) + "\" };\n"; +      } else { +        h << "    class " << enumName( (*itEntry)->param() ) << endl; +        h << "    {" << endl; +        h << "      public:" << endl; +        h << "      enum type { " << values.join( ", " ) << ", COUNT };" << endl; +        h << "      static const char* const enumToString[];" << endl; +        h << "    };" << endl; +        cppPreamble += "const char* const " + cfg.className + "::" + enumName( (*itEntry)->param() ) + +           "::enumToString[] = { \"" + values.join( "\", \"" ) + "\" };\n"; +      } +    } +  } +  if ( hasSignals ) { +   h << "\n    enum {" << endl; +   unsigned val = 1; +   QList<Signal>::ConstIterator it, itEnd = signalList.constEnd(); +   for ( it = signalList.constBegin(); it != itEnd; val <<= 1) { +     if ( !val ) { +       cerr << "Too many signals to create unique bit masks" << endl; +       exit(1); +     } +     Signal signal = *it; +     h << "      " << signalEnumName(signal.name) << " = 0x" << hex << val; +     if ( ++it != itEnd ) +      h << ","; +     h << endl; +   } +   h << " };" << dec << endl; +  } +  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; +    } +    h << " );" << endl; +  } else { +    h << "    static " << cfg.className << " *self();" << endl; +    if (cfgFileNameArg) +    { +      h << "    static void instance(const QString& cfgfilename);" << endl; +    } +  } + +  // Destructor +  h << "    ~" << cfg.className << "();" << endl << endl; + +  // global variables +  if (cfg.staticAccessors) +    This = "self()->"; +  else +    Const = " 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 == "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; +    // Accessor +    h << "    /**" << endl; +    h << "      Get " << (*itEntry)->label() << endl; +    h << "    */" << endl; +    if (cfg.staticAccessors) +      h << "    static" << endl; +    h << "    "; +    if (cfg.useEnumTypes && t == "Enum") +      h << enumType(*itEntry, cfg.globalEnums); +    else +      h << cppType(t); +    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 == "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 == "Enum") +        h << "static_cast<" << enumType(*itEntry, cfg.globalEnums) << ">("; +      h << getDefaultFunction(n) << "_helper("; +      if ( !(*itEntry)->param().isEmpty() ) +          h << " i "; +      h << ")"; +      if (cfg.useEnumTypes && t == "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. +  if( hasSignals ) { +    h << endl; +    h << "  Q_SIGNALS:"; +    Q_FOREACH(const Signal &signal, 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 == "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 << "  protected:" << endl; + +  // Private constructor for singleton +  if ( cfg.singleton ) { +    h << "    " << cfg.className << "("; +    if ( cfgFileNameArg ) +      h << "const QString& arg"; +    h << ");" << endl; +    h << "    friend class " << cfg.className << "Helper;" << endl << endl; +  } + +  if ( hasSignals ) { +    h << "    virtual bool usrWriteConfig();" << endl; +  } + +  // Member variables +  if ( !cfg.memberVariables.isEmpty() && cfg.memberVariables != "private" && cfg.memberVariables != "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 != "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 << QString("[%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 << QString("[%1]").arg( (*itEntry)->paramMax()+1 ); +        h << ";" << endl; +      } +    } +    if ( hasSignals ) +     h << "    uint " << varName("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 \"" << filenameOnly(baseName) << "_addons.h\"" <<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 << "// This file is generated by kconfig_compiler 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.count() > 0 ) 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 <QtCore/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 << QString("[%1]").arg( (*itEntry)->paramMax()+1 ); +      } +      cpp << ";" << endl; +    } +    cpp << endl << "    // items" << endl; +    for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) { +      cpp << "    "+cfg.inherits+"::Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry, cfg ); +      if ( !(*itEntry)->param().isEmpty() ) cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 ); +        cpp << ";" << endl; +    } +    if ( hasSignals ) { +      cpp << "    uint " << varName("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(0) {}" << endl; +    cpp << "    ~" << cfg.className << "Helper() { delete q; }" << 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->readConfig();" << endl; +      cpp << "  }" << endl << endl; +    } +    cpp << "  return s_global" << cfg.className << "()->q;" << endl; +    cpp << "}" << endl << endl; + +    if ( cfgFileNameArg ) { +      cpp << "void " << cfg.className << "::instance(const QString& cfgfilename)" << 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 << "(cfgfilename);" << endl; +      cpp << "  s_global" << cfg.className << "()->q->readConfig();" << endl; +      cpp << "}" << endl << endl; +    } +  } + +  if ( !cppPreamble.isEmpty() ) +    cpp << cppPreamble << endl; + +  // Constructor +  cpp << cfg.className << "::" << cfg.className << "( "; +  if ( cfgFileNameArg ) { +    if ( !cfg.singleton && ! 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; +  } +  cpp << " )" << endl; + +  cpp << "  : " << cfg.inherits << "("; +  if ( !cfgFileName.isEmpty() ) cpp << " QLatin1String( \"" << cfgFileName << "\" "; +  if ( cfgFileNameArg ) 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 ( hasSignals && !cfg.dpointer ) +    cpp << "  , " << varName("settingsChanged", cfg) << "(0)" << endl; + +  cpp << "{" << endl; + +  if (cfg.dpointer) +  { +    cpp << "  d = new " + cfg.className + "Private;" << endl; +    if (hasSignals) +      cpp << "  " << varPath("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(); + +  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() == "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 = QLatin1String(\"" << (*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)->type(), (*itEntry)->name(), 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 ); + +      cpp << "  addItem( " << itemPath( *itEntry, cfg ); +      QString quotedName = (*itEntry)->name(); +      addQuotes( quotedName ); +      if ( quotedName != key ) cpp << ", QLatin1String( \"" << (*itEntry)->name() << "\" )"; +      cpp << " );" << endl; +    } +    else +    { +      // Indexed +      for(int i = 0; i <= (*itEntry)->paramMax(); i++) +      { +        QString defaultStr; +        QString itemVarStr(itemPath( *itEntry, cfg )+QString("[%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)->type(), (*itEntry)->name(), paramString(key, *itEntry, i), defaultStr,cfg,  QString("[%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 << ", QLatin1String( \""; +        if ( (*itEntry)->paramType()=="Enum" ) +          cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg((*itEntry)->paramValues()[i] ); +        else +          cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%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 == "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 == "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.singleton ) { +    if ( cfg.dpointer ) +      cpp << "  delete d;" << endl; +    cpp << "  s_global" << cfg.className << "()->q = 0;" << endl; +  } +  cpp << "}" << endl << endl; + +  if ( hasSignals ) { +    cpp << "bool " << cfg.className << "::" << "usrWriteConfig()" << endl; +    cpp << "{" << endl; +    cpp << "  const bool res = " << cfg.inherits << "::usrWriteConfig();" << endl; +    cpp << "  if (!res) return false;" << endl << endl; +    Q_FOREACH(const Signal &signal, signalList) { +      cpp << "  if ( " << varPath("settingsChanged", cfg) << " & " << signalEnumName(signal.name) << " ) " << endl; +      cpp << "    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 == "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 << endl; +    } +    cpp << "  " << varPath("settingsChanged", cfg) << " = 0;" << endl; +    cpp << "  return true;" << endl; +    cpp << "}" << endl; +  } + +  // Add includemoc if they are signals defined. +  if( hasSignals ) { +    cpp << endl; +    cpp << "#include \"" << mocFileName << "\"" << endl; +    cpp << endl; +  } + +  // clear entries list +  qDeleteAll( entries ); + +  implementation.close(); +} | 
