• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

kconfig_compiler.cpp

Go to the documentation of this file.
00001 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002 /*
00003     This file is part of KDE.
00004 
00005     Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
00006     Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
00007     Copyright (c) 2003 Zack Rusin <zack@kde.org>
00008     Copyright (c) 2006 Michaƫl Larouche <michael.larouche@kdemail.net>
00009     Copyright (c) 2008 Allen Winter <winter@kde.org>
00010 
00011     This library is free software; you can redistribute it and/or
00012     modify it under the terms of the GNU Library General Public
00013     License as published by the Free Software Foundation; either
00014     version 2 of the License, or (at your option) any later version.
00015 
00016     This library is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019     Library General Public License for more details.
00020 
00021     You should have received a copy of the GNU Library General Public License
00022     along with this library; see the file COPYING.LIB.  If not, write to
00023     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00024     Boston, MA 02110-1301, USA.
00025 */
00026 
00027 #include <QtCore/QCoreApplication>
00028 #include <QtCore/QFile>
00029 #include <QtCore/QFileInfo>
00030 #include <QtCore/QSettings>
00031 #include <QtCore/QTextStream>
00032 #include <QtXml/QDomAttr>
00033 #include <QtCore/QRegExp>
00034 #include <QtCore/QStringList>
00035 
00036 #include <ostream>
00037 #include <iostream>
00038 #include <stdlib.h>
00039 
00040 
00041 static inline std::ostream &operator<<(std::ostream &o, const QString &str)
00042 {
00043     o << str.toLocal8Bit().constData();
00044     return o;
00045 }
00046 
00047 static void parseArgs(const QStringList &args, QString &directory, QString &file1, QString &file2)
00048 {
00049     int fileCount = 0;
00050     directory = ".";
00051 
00052     for (int i = 1; i < args.count(); ++i) {
00053         if (args.at(i) == "-d" ||  args.at(i) == "--directory") {
00054             if (i + 1 > args.count()) {
00055                 std::cerr << qPrintable(args.at(i)) << " needs an argument" << std::endl;
00056                 exit(1);
00057             }
00058             directory = args.at(++i);
00059         } else if (args.at(i).startsWith("-d")) {
00060             directory = args.at(i).mid(2);
00061         } else if (args.at(i) == "--help" || args.at(i) == "-h") {
00062             std::cout << "Options:" << std::endl;
00063             std::cout << "  -L --license              Display software license" << std::endl;
00064             std::cout << "  -d, --directory <dir>     Directory to generate files in [.]" << std::endl;
00065             std::cout << "  -h, --help                Display this help" << std::endl;
00066             std::cout << std::endl;
00067             std::cout << "Arguments:" << std::endl;
00068             std::cout << "      file.kcfg                 Input kcfg XML file" << std::endl;
00069             std::cout << "      file.kcfgc                Code generation options file" << std::endl;
00070             exit(0);
00071         } else if (args.at(i) == "--license" || args.at(i) == "-L") {
00072             std::cout << "Copyright 2003 Cornelius Schumacher, Waldo Bastian, Zack Rusin," << std::endl;
00073             std::cout << "    Reinhold Kainhofer, Duncan Mac-Vicar P., Harald Fernengel" << std::endl;
00074             std::cout << "This program comes with ABSOLUTELY NO WARRANTY." << std::endl;
00075             std::cout << "You may redistribute copies of this program" << std::endl;
00076             std::cout << "under the terms of the GNU Library Public License." << std::endl;
00077             std::cout << "For more information about these matters, see the file named COPYING." << std::endl;
00078             exit(0);
00079         } else if (args.at(i).startsWith('-')) {
00080             std::cerr << "Unknown option: " << qPrintable(args.at(i)) << std::endl;
00081             exit(1);
00082         } else if (fileCount == 0) {
00083             file1 = args.at(i);
00084             ++fileCount;
00085         } else if (fileCount == 1) {
00086             file2 = args.at(i);
00087             ++fileCount;
00088         } else {
00089             std::cerr << "Too many arguments" << std::endl;
00090             exit(1);
00091         }
00092     }
00093     if (fileCount < 2) {
00094         std::cerr << "Too few arguments" << std::endl;
00095         exit(1);
00096     }
00097 }
00098 
00099 bool globalEnums;
00100 bool useEnumTypes;
00101 bool itemAccessors;
00102 bool dpointer;
00103 QStringList allNames;
00104 QRegExp *validNameRegexp;
00105 QString This;
00106 QString Const;
00107 
00108 struct SignalArguments
00109 {
00110       QString type;
00111       QString variableName;
00112 };
00113 
00114 class Signal {
00115 public:
00116   QString name;
00117   QString label;
00118   QList<SignalArguments> arguments;
00119 };
00120 
00121 class CfgEntry
00122 {
00123   public:
00124     struct Choice
00125     {
00126       QString name;
00127       QString context;
00128       QString label;
00129       QString toolTip;
00130       QString whatsThis;
00131     };
00132     class Choices
00133     {
00134       public:
00135         Choices() {}
00136         Choices( const QList<Choice> &d, const QString &n, const QString &p )
00137              : prefix(p), choices(d), mName(n)
00138         {
00139           int i = n.indexOf("::");
00140           if (i >= 0)
00141             mExternalQual = n.left(i + 2);
00142         }
00143     QString prefix;
00144         QList<Choice> choices;
00145     const QString& name() const  { return mName; }
00146     const QString& externalQualifier() const  { return mExternalQual; }
00147     bool external() const  { return !mExternalQual.isEmpty(); }
00148       private:
00149         QString mName;
00150         QString mExternalQual;
00151     };
00152 
00153     CfgEntry( const QString &group, const QString &type, const QString &key,
00154               const QString &name, const QString &context, const QString &label,
00155               const QString &toolTip, const QString &whatsThis, const QString &code,
00156               const QString &defaultValue, const Choices &choices, const QList<Signal> signalList,
00157               bool hidden )
00158       : mGroup( group ), mType( type ), mKey( key ), mName( name ),
00159         mContext( context ), mLabel( label ), mToolTip( toolTip ), mWhatsThis( whatsThis ),
00160         mCode( code ), mDefaultValue( defaultValue ), mChoices( choices ),
00161         mSignalList(signalList), mHidden( hidden )
00162     {
00163     }
00164 
00165     void setGroup( const QString &group ) { mGroup = group; }
00166     QString group() const { return mGroup; }
00167 
00168     void setType( const QString &type ) { mType = type; }
00169     QString type() const { return mType; }
00170 
00171     void setKey( const QString &key ) { mKey = key; }
00172     QString key() const { return mKey; }
00173 
00174     void setName( const QString &name ) { mName = name; }
00175     QString name() const { return mName; }
00176 
00177     void setContext( const QString &context ) { mContext = context; }
00178     QString context() const { return mContext; }
00179 
00180     void setLabel( const QString &label ) { mLabel = label; }
00181     QString label() const { return mLabel; }
00182 
00183     void setToolTip( const QString &toolTip ) { mToolTip = toolTip; }
00184     QString toolTip() const { return mToolTip; }
00185 
00186     void setWhatsThis( const QString &whatsThis ) { mWhatsThis = whatsThis; }
00187     QString whatsThis() const { return mWhatsThis; }
00188 
00189     void setDefaultValue( const QString &d ) { mDefaultValue = d; }
00190     QString defaultValue() const { return mDefaultValue; }
00191 
00192     void setCode( const QString &d ) { mCode = d; }
00193     QString code() const { return mCode; }
00194 
00195     void setMinValue( const QString &d ) { mMin = d; }
00196     QString minValue() const { return mMin; }
00197 
00198     void setMaxValue( const QString &d ) { mMax = d; }
00199     QString maxValue() const { return mMax; }
00200 
00201     void setParam( const QString &d ) { mParam = d; }
00202     QString param() const { return mParam; }
00203 
00204     void setParamName( const QString &d ) { mParamName = d; }
00205     QString paramName() const { return mParamName; }
00206 
00207     void setParamType( const QString &d ) { mParamType = d; }
00208     QString paramType() const { return mParamType; }
00209 
00210     void setChoices( const QList<Choice> &d, const QString &n, const QString &p ) { mChoices = Choices( d, n, p ); }
00211     Choices choices() const { return mChoices; }
00212 
00213     void setParamValues( const QStringList &d ) { mParamValues = d; }
00214     QStringList paramValues() const { return mParamValues; }
00215 
00216     void setParamDefaultValues( const QStringList &d ) { mParamDefaultValues = d; }
00217     QString paramDefaultValue(int i) const { return mParamDefaultValues[i]; }
00218 
00219     void setParamMax( int d ) { mParamMax = d; }
00220     int paramMax() const { return mParamMax; }
00221 
00222     void setSignalList( const QList<Signal> &value ) { mSignalList = value; }
00223     QList<Signal> signalList() const { return mSignalList; }
00224 
00225     bool hidden() const { return mHidden; }
00226 
00227     void dump() const
00228     {
00229       std::cerr << "<entry>" << std::endl;
00230       std::cerr << "  group: " << qPrintable(mGroup) << std::endl;
00231       std::cerr << "  type: " << qPrintable(mType) << std::endl;
00232       std::cerr << "  key: " << qPrintable(mKey) << std::endl;
00233       std::cerr << "  name: " << qPrintable(mName) << std::endl;
00234       std::cerr << "  context: " << qPrintable(mContext) << std::endl;
00235       std::cerr << "  label: " << qPrintable(mLabel) << std::endl;
00236 // whatsthis
00237       std::cerr << "  code: " << qPrintable(mCode) << std::endl;
00238 //      std::cerr << "  values: " << mValues.join(":") << std::endl;
00239 
00240       if (!param().isEmpty())
00241       {
00242         std::cerr << "  param name: "<< qPrintable(mParamName) << std::endl;
00243         std::cerr << "  param type: "<< qPrintable(mParamType) << std::endl;
00244         std::cerr << "  paramvalues: " << qPrintable(mParamValues.join(":")) << std::endl;
00245       }
00246       std::cerr << "  default: " << qPrintable(mDefaultValue) << std::endl;
00247       std::cerr << "  hidden: " << mHidden << std::endl;
00248       std::cerr << "  min: " << qPrintable(mMin) << std::endl;
00249       std::cerr << "  max: " << qPrintable(mMax) << std::endl;
00250       std::cerr << "</entry>" << std::endl;
00251     }
00252 
00253   private:
00254     QString mGroup;
00255     QString mType;
00256     QString mKey;
00257     QString mName;
00258     QString mContext;
00259     QString mLabel;
00260     QString mToolTip;
00261     QString mWhatsThis;
00262     QString mCode;
00263     QString mDefaultValue;
00264     QString mParam;
00265     QString mParamName;
00266     QString mParamType;
00267     Choices mChoices;
00268     QList<Signal> mSignalList;
00269     QStringList mParamValues;
00270     QStringList mParamDefaultValues;
00271     int mParamMax;
00272     bool mHidden;
00273     QString mMin;
00274     QString mMax;
00275 };
00276 
00277 class Param {
00278 public:
00279   QString name;
00280   QString type;
00281 };
00282 
00283 // returns the name of an member variable
00284 // use itemPath to know the full path
00285 // like using d-> in case of dpointer
00286 static QString varName(const QString &n)
00287 {
00288   QString result;
00289   if ( !dpointer ) {
00290     result = 'm'+n;
00291     result[1] = result[1].toUpper();
00292   }
00293   else {
00294     result = n;
00295     result[0] = result[0].toLower();
00296   }
00297   return result;
00298 }
00299 
00300 static QString varPath(const QString &n)
00301 {
00302   QString result;
00303   if ( dpointer ) {
00304     result = "d->"+varName(n);
00305   }
00306   else {
00307     result = varName(n);
00308   }
00309   return result;
00310 }
00311 
00312 static QString enumName(const QString &n)
00313 {
00314   QString result = "Enum" + n;
00315   result[4] = result[4].toUpper();
00316   return result;
00317 }
00318 
00319 static QString enumName(const QString &n, const CfgEntry::Choices &c)
00320 {
00321   QString result = c.name();
00322   if ( result.isEmpty() )
00323   {
00324     result = "Enum" + n;
00325     result[4] = result[4].toUpper();
00326   }
00327   return result;
00328 }
00329 
00330 static QString enumType(const CfgEntry *e)
00331 {
00332   QString result = e->choices().name();
00333   if ( result.isEmpty() )
00334   {
00335     result = "Enum" + e->name() + "::type";
00336     result[4] = result[4].toUpper();
00337   }
00338   return result;
00339 }
00340 
00341 static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
00342 {
00343   QString result = c.name();
00344   if ( result.isEmpty() )
00345   {
00346     result = "Enum" + n + "::";
00347     result[4] = result[4].toUpper();
00348   }
00349   else if ( c.external() )
00350     result = c.externalQualifier();
00351   else
00352     result.clear();
00353   return result;
00354 }
00355 
00356 static QString setFunction(const QString &n, const QString &className = QString())
00357 {
00358   QString result = "set"+n;
00359   result[3] = result[3].toUpper();
00360 
00361   if ( !className.isEmpty() )
00362     result = className + "::" + result;
00363   return result;
00364 }
00365 
00366 
00367 static QString getFunction(const QString &n, const QString &className = QString())
00368 {
00369   QString result = n;
00370   result[0] = result[0].toLower();
00371 
00372   if ( !className.isEmpty() )
00373     result = className + "::" + result;
00374   return result;
00375 }
00376 
00377 
00378 static void addQuotes( QString &s )
00379 {
00380   if ( !s.startsWith( '"' ) ) s.prepend( '"' );
00381   if ( !s.endsWith( '"' ) ) s.append( '"' );
00382 }
00383 
00384 static QString quoteString( const QString &s )
00385 {
00386   QString r = s;
00387   r.replace( '\\', "\\\\" );
00388   r.replace( '\"', "\\\"" );
00389   r.remove( '\r' );
00390   r.replace( '\n', "\\n\"\n\"" );
00391   return '\"' + r + '\"';
00392 }
00393 
00394 static QString literalString( const QString &s )
00395 {
00396   bool isAscii = true;
00397   for(int i = s.length(); i--;)
00398      if (s[i].unicode() > 127) isAscii = false;
00399 
00400   if (isAscii)
00401      return "QLatin1String( " + quoteString(s) + " )";
00402   else
00403      return "QString::fromUtf8( " + quoteString(s) + " )";
00404 }
00405 
00406 static QString dumpNode(const QDomNode &node)
00407 {
00408   QString msg;
00409   QTextStream s(&msg, QIODevice::WriteOnly );
00410   node.save(s, 0);
00411 
00412   msg = msg.simplified();
00413   if (msg.length() > 40)
00414     return msg.left(37)+"...";
00415   return msg;
00416 }
00417 
00418 static QString filenameOnly(const QString& path)
00419 {
00420    int i = path.lastIndexOf(QRegExp("[/\\]"));
00421    if (i >= 0)
00422       return path.mid(i+1);
00423    return path;
00424 }
00425 
00426 static QString signalEnumName(const QString &signalName)
00427 {
00428   QString result;
00429   result = "signal" + signalName;
00430   result[6] = result[6].toUpper();
00431 
00432   return result;
00433 }
00434 
00435 static void preProcessDefault( QString &defaultValue, const QString &name,
00436                                const QString &type,
00437                                const CfgEntry::Choices &choices,
00438                                QString &code )
00439 {
00440     if ( type == "String" && !defaultValue.isEmpty() ) {
00441       defaultValue = literalString(defaultValue);
00442 
00443     } else if ( type == "Path" && !defaultValue.isEmpty() ) {
00444       defaultValue = literalString( defaultValue );
00445     } else if ( type == "Url" && !defaultValue.isEmpty() ) {
00446       defaultValue = "KUrl( " + literalString(defaultValue) + ")";
00447     } else if ( ( type == "UrlList" || type == "StringList" || type == "PathList") && !defaultValue.isEmpty() ) {
00448       QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
00449       if (!code.isEmpty())
00450          cpp << endl;
00451 
00452       cpp << "  QStringList default" << name << ";" << endl;
00453       const QStringList defaults = defaultValue.split( ',' );
00454       QStringList::ConstIterator it;
00455       for( it = defaults.constBegin(); it != defaults.constEnd(); ++it ) {
00456         cpp << "  default" << name << ".append( ";
00457         if( type == "UrlList" ) {
00458           cpp << "KUrl(";       
00459         }
00460         cpp << "QString::fromUtf8( \"" << *it << "\" ) ";
00461         if( type == "UrlList" ) {
00462           cpp << ") ";
00463         }
00464         cpp << ");" << endl;
00465       }
00466       defaultValue = "default" + name;
00467 
00468     } else if ( type == "Color" && !defaultValue.isEmpty() ) {
00469       QRegExp colorRe("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?");
00470       if (colorRe.exactMatch(defaultValue))
00471       {
00472         defaultValue = "QColor( " + defaultValue + " )";
00473       }
00474       else
00475       {
00476         defaultValue = "QColor( \"" + defaultValue + "\" )";
00477       }
00478 
00479     } else if ( type == "Enum" ) {
00480       QList<CfgEntry::Choice>::ConstIterator it;
00481       for( it = choices.choices.constBegin(); it != choices.choices.constEnd(); ++it ) {
00482         if ( (*it).name == defaultValue ) {
00483           if ( globalEnums && choices.name().isEmpty() )
00484             defaultValue.prepend( choices.prefix );
00485           else
00486             defaultValue.prepend( enumTypeQualifier(name, choices) + choices.prefix );
00487           break;
00488         }
00489       }
00490 
00491     } else if ( type == "IntList" ) {
00492       QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
00493       if (!code.isEmpty())
00494          cpp << endl;
00495 
00496       cpp << "  QList<int> default" << name << ";" << endl;
00497       if (!defaultValue.isEmpty())
00498       {
00499         QStringList defaults = defaultValue.split( ',' );
00500         QStringList::ConstIterator it;
00501         for( it = defaults.constBegin(); it != defaults.constEnd(); ++it ) {
00502           cpp << "  default" << name << ".append( " << *it << " );"
00503               << endl;
00504         }
00505       }
00506       defaultValue = "default" + name;
00507     }
00508 }
00509 
00510 
00511 CfgEntry *parseEntry( const QString &group, const QDomElement &element )
00512 {
00513   bool defaultCode = false;
00514   QString type = element.attribute( "type" );
00515   QString name = element.attribute( "name" );
00516   QString key = element.attribute( "key" );
00517   QString hidden = element.attribute( "hidden" );
00518   QString context = element.attribute( "context" );
00519   QString label;
00520   QString toolTip;
00521   QString whatsThis;
00522   QString defaultValue;
00523   QString code;
00524   QString param;
00525   QString paramName;
00526   QString paramType;
00527   CfgEntry::Choices choices;
00528   QList<Signal> signalList;
00529   QStringList paramValues;
00530   QStringList paramDefaultValues;
00531   QString minValue;
00532   QString maxValue;
00533   int paramMax = 0;
00534 
00535   for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
00536     QString tag = e.tagName();
00537     if ( tag == "label" ) {
00538       label = e.text();
00539       context = e.attribute( "context" );
00540     }
00541     else if ( tag == "tooltip" ) {
00542       toolTip = e.text();
00543       context = e.attribute( "context" );
00544     }
00545     else if ( tag == "whatsthis" ) {
00546       whatsThis = e.text();
00547       context = e.attribute( "context" );
00548     }
00549     else if ( tag == "min" ) minValue = e.text();
00550     else if ( tag == "max" ) maxValue = e.text();
00551     else if ( tag == "code" ) code = e.text();
00552     else if ( tag == "parameter" )
00553     {
00554       param = e.attribute( "name" );
00555       paramType = e.attribute( "type" );
00556       if ( param.isEmpty() ) {
00557         std::cerr << "Parameter must have a name: " << qPrintable(dumpNode(e)) << std::endl;
00558         return 0;
00559       }
00560       if ( paramType.isEmpty() ) {
00561         std::cerr << "Parameter must have a type: " << qPrintable(dumpNode(e)) << std::endl;
00562         return 0;
00563       }
00564       if ((paramType == "Int") || (paramType == "UInt"))
00565       {
00566          bool ok;
00567          paramMax = e.attribute("max").toInt(&ok);
00568          if (!ok)
00569          {
00570            std::cerr << "Integer parameter must have a maximum (e.g. max=\"0\"): "
00571                        << qPrintable(dumpNode(e)) << std::endl;
00572            return 0;
00573          }
00574       }
00575       else if (paramType == "Enum")
00576       {
00577          for ( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
00578            if (e2.tagName() == "values")
00579            {
00580              for ( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) {
00581                if (e3.tagName() == "value")
00582                {
00583                   paramValues.append( e3.text() );
00584                }
00585              }
00586              break;
00587            }
00588          }
00589          if (paramValues.isEmpty())
00590          {
00591            std::cerr << "No values specified for parameter '" << qPrintable(param)
00592                        << "'." << std::endl;
00593            return 0;
00594          }
00595          paramMax = paramValues.count()-1;
00596       }
00597       else
00598       {
00599         std::cerr << "Parameter '" << qPrintable(param) << "' has type " << qPrintable(paramType)
00600                     << " but must be of type int, uint or Enum." << std::endl;
00601         return 0;
00602       }
00603     }
00604     else if ( tag == "default" )
00605     {
00606       if (e.attribute("param").isEmpty())
00607       {
00608         defaultValue = e.text();
00609         if (e.attribute( "code" ) == "true")
00610           defaultCode = true;
00611       }
00612     }
00613     else if ( tag == "choices" ) {
00614       QString name = e.attribute( "name" );
00615       QString prefix = e.attribute( "prefix" );
00616       QList<CfgEntry::Choice> chlist;
00617       for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
00618         if ( e2.tagName() == "choice" ) {
00619           CfgEntry::Choice choice;
00620           choice.name = e2.attribute( "name" );
00621           if ( choice.name.isEmpty() ) {
00622             std::cerr << "Tag <choice> requires attribute 'name'." << std::endl;
00623           }
00624           for( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) {
00625             if ( e3.tagName() == "label" ) {
00626               choice.label = e3.text();
00627               choice.context = e3.attribute( "context" );
00628             }
00629             if ( e3.tagName() == "tooltip" ) {
00630               choice.toolTip = e3.text();
00631               choice.context = e3.attribute( "context" );
00632             }
00633             if ( e3.tagName() == "whatsthis" ) {
00634               choice.whatsThis = e3.text();
00635               choice.context = e3.attribute( "context" );
00636             }
00637           }
00638           chlist.append( choice );
00639         }
00640       }
00641       choices = CfgEntry::Choices( chlist, name, prefix );
00642     }
00643    else if ( tag == "emit" ) {
00644     QDomNode signalNode;
00645     Signal signal;
00646     signal.name = e.attribute( "signal" );
00647     signalList.append( signal);
00648    }
00649   }
00650 
00651 
00652   bool nameIsEmpty = name.isEmpty();
00653   if ( nameIsEmpty && key.isEmpty() ) {
00654     std::cerr << "Entry must have a name or a key: " << qPrintable(dumpNode(element)) << std::endl;
00655     return 0;
00656   }
00657 
00658   if ( key.isEmpty() ) {
00659     key = name;
00660   }
00661 
00662   if ( nameIsEmpty ) {
00663     name = key;
00664     name.remove( ' ' );
00665   } else if ( name.contains( ' ' ) ) {
00666     std::cout<<"Entry '"<<qPrintable(name)<<"' contains spaces! <name> elements can not contain spaces!"<<std::endl;
00667     name.remove( ' ' );
00668   }
00669 
00670   if (name.contains("$("))
00671   {
00672     if (param.isEmpty())
00673     {
00674       std::cerr << "Name may not be parameterized: " << qPrintable(name) << std::endl;
00675       return 0;
00676     }
00677   }
00678   else
00679   {
00680     if (!param.isEmpty())
00681     {
00682       std::cerr << "Name must contain '$(" << qPrintable(param) << ")': " << qPrintable(name) << std::endl;
00683       return 0;
00684     }
00685   }
00686 
00687   if ( label.isEmpty() ) {
00688     label = key;
00689   }
00690 
00691   if ( type.isEmpty() ) type = "String"; // XXX : implicit type might be bad
00692 
00693   if (!param.isEmpty())
00694   {
00695     // Adjust name
00696     paramName = name;
00697     name.remove("$("+param+')');
00698     // Lookup defaults for indexed entries
00699     for(int i = 0; i <= paramMax; i++)
00700     {
00701       paramDefaultValues.append(QString());
00702     }
00703 
00704     for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
00705       QString tag = e.tagName();
00706       if ( tag == "default" )
00707       {
00708         QString index = e.attribute("param");
00709         if (index.isEmpty())
00710            continue;
00711 
00712         bool ok;
00713         int i = index.toInt(&ok);
00714         if (!ok)
00715         {
00716           i = paramValues.indexOf(index);
00717           if (i == -1)
00718           {
00719             std::cerr << "Index '" << qPrintable(index) << "' for default value is unknown." << std::endl;
00720             return 0;
00721           }
00722         }
00723 
00724         if ((i < 0) || (i > paramMax))
00725         {
00726           std::cerr << "Index '" << i << "' for default value is out of range [0, "<< paramMax<<"]." << std::endl;
00727           return 0;
00728         }
00729 
00730         QString tmpDefaultValue = e.text();
00731 
00732         if (e.attribute( "code" ) != "true")
00733            preProcessDefault(tmpDefaultValue, name, type, choices, code);
00734 
00735         paramDefaultValues[i] = tmpDefaultValue;
00736       }
00737     }
00738   }
00739 
00740   if (!validNameRegexp->exactMatch(name))
00741   {
00742     if (nameIsEmpty)
00743       std::cerr << "The key '" << qPrintable(key) << "' can not be used as name for the entry because "
00744                    "it is not a valid name. You need to specify a valid name for this entry." << std::endl;
00745     else
00746       std::cerr << "The name '" << qPrintable(name) << "' is not a valid name for an entry." << std::endl;
00747     return 0;
00748   }
00749 
00750   if (allNames.contains(name))
00751   {
00752     if (nameIsEmpty)
00753       std::cerr << "The key '" << qPrintable(key) << "' can not be used as name for the entry because "
00754                    "it does not result in a unique name. You need to specify a unique name for this entry." << std::endl;
00755     else
00756       std::cerr << "The name '" << qPrintable(name) << "' is not unique." << std::endl;
00757     return 0;
00758   }
00759   allNames.append(name);
00760 
00761   if (!defaultCode)
00762   {
00763     preProcessDefault(defaultValue, name, type, choices, code);
00764   }
00765 
00766   CfgEntry *result = new CfgEntry( group, type, key, name, context, label, toolTip, whatsThis,
00767                                    code, defaultValue, choices, signalList,
00768                                    hidden == "true" );
00769   if (!param.isEmpty())
00770   {
00771     result->setParam(param);
00772     result->setParamName(paramName);
00773     result->setParamType(paramType);
00774     result->setParamValues(paramValues);
00775     result->setParamDefaultValues(paramDefaultValues);
00776     result->setParamMax(paramMax);
00777   }
00778   result->setMinValue(minValue);
00779   result->setMaxValue(maxValue);
00780 
00781   return result;
00782 }
00783 
00784 static bool isUnsigned(const QString& type)
00785 {
00786     if ( type == "UInt" )        return true;
00787     if ( type == "ULongLong" )   return true;
00788     return false;
00789 }
00790 
00794 QString param( const QString &type )
00795 {
00796     if ( type == "String" )           return "const QString &";
00797     else if ( type == "StringList" )  return "const QStringList &";
00798     else if ( type == "Font" )        return "const QFont &";
00799     else if ( type == "Rect" )        return "const QRect &";
00800     else if ( type == "Size" )        return "const QSize &";
00801     else if ( type == "Color" )       return "const QColor &";
00802     else if ( type == "Point" )       return "const QPoint &";
00803     else if ( type == "Int" )         return "int";
00804     else if ( type == "UInt" )        return "uint";
00805     else if ( type == "Bool" )        return "bool";
00806     else if ( type == "Double" )      return "double";
00807     else if ( type == "DateTime" )    return "const QDateTime &";
00808     else if ( type == "LongLong" )    return "qint64";
00809     else if ( type == "ULongLong" )   return "quint64";
00810     else if ( type == "IntList" )     return "const QList<int> &";
00811     else if ( type == "Enum" )        return "int";
00812     else if ( type == "Path" )        return "const QString &";
00813     else if ( type == "PathList" )    return "const QStringList &";
00814     else if ( type == "Password" )    return "const QString &";
00815     else if ( type == "Url" )         return "const KUrl &";
00816     else if ( type == "UrlList" )     return "const KUrl::List &";
00817     else {
00818         std::cerr <<"kconfig_compiler does not support type \""<< type <<"\""<<std::endl;
00819         return "QString"; //For now, but an assert would be better
00820     }
00821 }
00822 
00826 QString cppType( const QString &type )
00827 {
00828     if ( type == "String" )           return "QString";
00829     else if ( type == "StringList" )  return "QStringList";
00830     else if ( type == "Font" )        return "QFont";
00831     else if ( type == "Rect" )        return "QRect";
00832     else if ( type == "Size" )        return "QSize";
00833     else if ( type == "Color" )       return "QColor";
00834     else if ( type == "Point" )       return "QPoint";
00835     else if ( type == "Int" )         return "int";
00836     else if ( type == "UInt" )        return "uint";
00837     else if ( type == "Bool" )        return "bool";
00838     else if ( type == "Double" )      return "double";
00839     else if ( type == "DateTime" )    return "QDateTime";
00840     else if ( type == "LongLong" )    return "qint64";
00841     else if ( type == "ULongLong" )   return "quint64";
00842     else if ( type == "IntList" )     return "QList<int>";
00843     else if ( type == "Enum" )        return "int";
00844     else if ( type == "Path" )        return "QString";
00845     else if ( type == "PathList" )    return "QStringList";
00846     else if ( type == "Password" )    return "QString";
00847     else if ( type == "Url" )         return "KUrl";
00848     else if ( type == "UrlList" )     return "KUrl::List";
00849     else {
00850         std::cerr<<"kconfig_compiler does not support type \""<< type <<"\""<<std::endl;
00851         return "QString"; //For now, but an assert would be better
00852     }
00853 }
00854 
00855 QString defaultValue( const QString &type )
00856 {
00857     if ( type == "String" )           return "\"\""; // Use empty string, not null string!
00858     else if ( type == "StringList" )  return "QStringList()";
00859     else if ( type == "Font" )        return "QFont()";
00860     else if ( type == "Rect" )        return "QRect()";
00861     else if ( type == "Size" )        return "QSize()";
00862     else if ( type == "Color" )       return "QColor(128, 128, 128)";
00863     else if ( type == "Point" )       return "QPoint()";
00864     else if ( type == "Int" )         return "0";
00865     else if ( type == "UInt" )        return "0";
00866     else if ( type == "Bool" )        return "false";
00867     else if ( type == "Double" )      return "0.0";
00868     else if ( type == "DateTime" )    return "QDateTime()";
00869     else if ( type == "LongLong" )    return "0";
00870     else if ( type == "ULongLong" )   return "0";
00871     else if ( type == "IntList" )     return "QList<int>()";
00872     else if ( type == "Enum" )        return "0";
00873     else if ( type == "Path" )        return "\"\""; // Use empty string, not null string!
00874     else if ( type == "PathList" )    return "QStringList()";
00875     else if ( type == "Password" )    return "\"\""; // Use empty string, not null string!
00876     else if ( type == "Url" )         return "KUrl()";
00877     else if ( type == "UrlList" )     return "KUrl::List()";
00878     else {
00879         std::cerr<<"Error, kconfig_compiler does not support the \""<< type <<"\" type!"<<std::endl;
00880         return "QString"; //For now, but an assert would be better
00881     }
00882 }
00883 
00884 QString itemType( const QString &type )
00885 {
00886   QString t;
00887 
00888   t = type;
00889   t.replace( 0, 1, t.left( 1 ).toUpper() );
00890 
00891   return t;
00892 }
00893 
00894 static QString itemDeclaration(const CfgEntry *e)
00895 {
00896   if (itemAccessors)
00897      return QString();
00898 
00899   QString fCap = e->name();
00900   fCap[0] = fCap[0].toUpper();
00901   return "  KConfigSkeleton::Item"+itemType( e->type() ) +
00902          "  *item" + fCap +
00903          ( (!e->param().isEmpty())?(QString("[%1]").arg(e->paramMax()+1)) : QString()) +
00904          ";\n";
00905 }
00906 
00907 // returns the name of an item variable
00908 // use itemPath to know the full path
00909 // like using d-> in case of dpointer
00910 static QString itemVar(const CfgEntry *e)
00911 {
00912   QString result;
00913   if (itemAccessors)
00914   {
00915     if ( !dpointer )
00916     {
00917       result = 'm' + e->name() + "Item";
00918       result[1] = result[1].toUpper();
00919     }
00920     else
00921     {
00922       result = e->name() + "Item";
00923       result[0] = result[0].toLower();
00924     }
00925   }
00926   else
00927   {
00928     result = "item" + e->name();
00929     result[4] = result[4].toUpper();
00930   }
00931   return result;
00932 }
00933 
00934 static QString itemPath(const CfgEntry *e)
00935 {
00936   QString result;
00937   if ( dpointer ) {
00938     result = "d->"+itemVar(e);
00939   }
00940   else {
00941     result = itemVar(e);
00942   }
00943   return result;
00944 }
00945 
00946 QString newItem( const QString &type, const QString &name, const QString &key,
00947                  const QString &defaultValue, const QString &param = QString())
00948 {
00949   QString t = "new KConfigSkeleton::Item" + itemType( type ) +
00950               "( currentGroup(), " + key + ", " + varPath( name ) + param;
00951   if ( type == "Enum" ) t += ", values" + name;
00952   if ( !defaultValue.isEmpty() ) {
00953     t += ", ";
00954     if ( type == "String" ) t += defaultValue;
00955     else t+= defaultValue;
00956   }
00957   t += " );";
00958 
00959   return t;
00960 }
00961 
00962 QString paramString(const QString &s, const CfgEntry *e, int i)
00963 {
00964   QString result = s;
00965   QString needle = "$("+e->param()+')';
00966   if (result.contains(needle))
00967   {
00968     QString tmp;
00969     if (e->paramType() == "Enum")
00970     {
00971       tmp = e->paramValues()[i];
00972     }
00973     else
00974     {
00975       tmp = QString::number(i);
00976     }
00977 
00978     result.replace(needle, tmp);
00979   }
00980   return result;
00981 }
00982 
00983 QString paramString(const QString &group, const QList<Param> &parameters)
00984 {
00985   QString paramString = group;
00986   QString arguments;
00987   int i = 1;
00988   for (QList<Param>::ConstIterator it = parameters.constBegin();
00989        it != parameters.constEnd(); ++it)
00990   {
00991      if (paramString.contains("$("+(*it).name+')'))
00992      {
00993        QString tmp;
00994        tmp.sprintf("%%%d", i++);
00995        paramString.replace("$("+(*it).name+')', tmp);
00996        arguments += ".arg( mParam"+(*it).name+" )";
00997      }
00998   }
00999   if (arguments.isEmpty())
01000     return "QLatin1String( \""+group+"\" )";
01001 
01002   return "QString( QLatin1String( \""+paramString+"\" ) )"+arguments;
01003 }
01004 
01005 /* int i is the value of the parameter */
01006 QString userTextsFunctions( CfgEntry *e, QString itemVarStr=QString(), QString i=QString() )
01007 {
01008   QString txt;
01009   if (itemVarStr.isNull()) itemVarStr=itemPath(e);
01010   if ( !e->label().isEmpty() ) {
01011     txt += "  " + itemVarStr + "->setLabel( ";
01012     if ( !e->context().isEmpty() )
01013       txt += "i18nc(" + quoteString(e->context()) + ", ";
01014     else
01015       txt += "i18n(";
01016     if ( !e->param().isEmpty() )
01017       txt += quoteString(e->label().replace("$("+e->param()+')', i));
01018     else
01019       txt+= quoteString(e->label());
01020     txt+= ") );\n";
01021   }
01022   if ( !e->toolTip().isEmpty() ) {
01023     txt += "  " + itemVarStr + "->setToolTip( ";
01024     if ( !e->context().isEmpty() )
01025       txt += "i18nc(" + quoteString(e->context()) + ", ";
01026     else
01027       txt += "i18n(";
01028     if ( !e->param().isEmpty() )
01029       txt += quoteString(e->toolTip().replace("$("+e->param()+')', i));
01030     else
01031       txt+= quoteString(e->toolTip());
01032     txt+=") );\n";
01033   }
01034   if ( !e->whatsThis().isEmpty() ) {
01035     txt += "  " + itemVarStr + "->setWhatsThis( ";
01036     if ( !e->context().isEmpty() )
01037       txt += "i18nc(" + quoteString(e->context()) + ", ";
01038     else
01039       txt += "i18n(";
01040     if ( !e->param().isEmpty() )
01041       txt += quoteString(e->whatsThis().replace("$("+e->param()+')', i));
01042     else
01043       txt+= quoteString(e->whatsThis());
01044     txt+=") );\n";
01045   }
01046   return txt;
01047 }
01048 
01049 // returns the member accesor implementation
01050 // which should go in the h file if inline
01051 // or the cpp file if not inline
01052 QString memberAccessorBody( CfgEntry *e )
01053 {
01054     QString result;
01055     QTextStream out(&result, QIODevice::WriteOnly);
01056     QString n = e->name();
01057     QString t = e->type();
01058     bool useEnumType = useEnumTypes && t == "Enum";
01059 
01060     out << "return ";
01061     if (useEnumType)
01062       out << "static_cast<" << enumType(e) << ">(";
01063     out << This << varPath(n);
01064     if (!e->param().isEmpty())
01065       out << "[i]";
01066     if (useEnumType)
01067       out << ")";
01068     out << ";" << endl;
01069 
01070     return result;
01071 }
01072 
01073 // returns the member mutator implementation
01074 // which should go in the h file if inline
01075 // or the cpp file if not inline
01076 QString memberMutatorBody( CfgEntry *e )
01077 {
01078   QString result;
01079   QTextStream out(&result, QIODevice::WriteOnly);
01080   QString n = e->name();
01081   QString t = e->type();
01082 
01083   if (!e->minValue().isEmpty())
01084   {
01085     if (e->minValue() != "0" || !isUnsigned(t)) { // skip writing "if uint<0" (#187579)
01086       out << "if (v < " << e->minValue() << ")" << endl;
01087       out << "{" << endl;
01088       out << "  kDebug() << \"" << setFunction(n);
01089       out << ": value \" << v << \" is less than the minimum value of ";
01090       out << e->minValue()<< "\" << endl;" << endl;
01091       out << "  v = " << e->minValue() << ";" << endl;
01092       out << "}" << endl;
01093     }
01094   }
01095 
01096   if (!e->maxValue().isEmpty())
01097   {
01098     out << endl << "if (v > " << e->maxValue() << ")" << endl;
01099     out << "{" << endl;
01100     out << "  kDebug() << \"" << setFunction(n);
01101     out << ": value \" << v << \" is greater than the maximum value of ";
01102     out << e->maxValue()<< "\" << endl;" << endl;
01103     out << "  v = " << e->maxValue() << ";" << endl;
01104     out << "}" << endl << endl;
01105   }
01106 
01107   out << "if (!" << This << "isImmutable( QString::fromLatin1 ( \"";
01108   if (!e->param().isEmpty())
01109   {
01110     out << e->paramName().replace("$("+e->param()+")", "%1") << "\" ).arg( ";
01111     if ( e->paramType() == "Enum" ) {
01112       out << "QLatin1String( ";
01113 
01114       if (globalEnums)
01115         out << enumName(e->param()) << "ToString[i]";
01116       else
01117         out << enumName(e->param()) << "::enumToString[i]";
01118 
01119         out << " )";
01120     }
01121     else
01122     {
01123       out << "i";
01124     }
01125     out << " )";
01126   }
01127   else
01128   {
01129     out << n << "\" )";
01130   }
01131   out << " ))" << (!e->signalList().empty() ? " {" : "") << endl;
01132   out << "  " << This << varPath(n);
01133   if (!e->param().isEmpty())
01134     out << "[i]";
01135   out << " = v;" << endl;
01136 
01137   if ( !e->signalList().empty() ) {
01138     foreach(const Signal &signal, e->signalList()) {
01139       out << "  " << This << varPath("settingsChanged") << " |= " << signalEnumName(signal.name) << ";" << endl;
01140     }
01141     out << "}" << endl;
01142   }
01143 
01144   return result;
01145 }
01146 
01147 // returns the item accesor implementation
01148 // which should go in the h file if inline
01149 // or the cpp file if not inline
01150 QString itemAccessorBody( CfgEntry *e )
01151 {
01152     QString result;
01153     QTextStream out(&result, QIODevice::WriteOnly);
01154 
01155     out << "return " << itemPath(e);
01156     if (!e->param().isEmpty()) out << "[i]";
01157     out << ";" << endl;
01158 
01159     return result;
01160 }
01161 
01162 //indents text adding X spaces per line
01163 QString indent(QString text, int spaces)
01164 {
01165     QString result;
01166     QTextStream out(&result, QIODevice::WriteOnly);
01167     QTextStream in(&text, QIODevice::ReadOnly);
01168     QString currLine;
01169     while ( !in.atEnd() )
01170     {
01171       currLine = in.readLine();
01172       if (!currLine.isEmpty())
01173         for (int i=0; i < spaces; i++)
01174           out << " ";
01175       out << currLine << endl;
01176     }
01177     return result;
01178 }
01179 
01180 
01181 int main( int argc, char **argv )
01182 {
01183   QCoreApplication app(argc, argv);
01184 
01185   validNameRegexp = new QRegExp("[a-zA-Z_][a-zA-Z0-9_]*");
01186 
01187   QString directoryName, inputFilename, codegenFilename;
01188   parseArgs(app.arguments(), directoryName, inputFilename, codegenFilename);
01189 
01190   QString baseDir = directoryName;
01191 #ifdef Q_OS_WIN
01192   if (!baseDir.endsWith('/') && !baseDir.endsWith('\\'))
01193 #else
01194   if (!baseDir.endsWith('/'))
01195 #endif
01196     baseDir.append("/");
01197 
01198   if (!codegenFilename.endsWith(".kcfgc"))
01199   {
01200     std::cerr << "Codegen options file must have extension .kcfgc" << std::endl;
01201     return 1;
01202   }
01203   QString baseName = QFileInfo(codegenFilename).fileName();
01204   baseName = baseName.left(baseName.length() - 6);
01205 
01206   QSettings codegenConfig(codegenFilename, QSettings::IniFormat);
01207 
01208   QString nameSpace = codegenConfig.value("NameSpace").toString();
01209   QString className = codegenConfig.value("ClassName").toString();
01210   QString inherits = codegenConfig.value("Inherits").toString();
01211   QString visibility = codegenConfig.value("Visibility").toString();
01212   if (!visibility.isEmpty()) visibility+=' ';
01213   bool forceStringFilename = codegenConfig.value("ForceStringFilename", false).toBool();
01214   bool singleton = codegenConfig.value("Singleton", false).toBool();
01215   bool staticAccessors = singleton;
01216   //bool useDPointer = codegenConfig.readEntry("DPointer", false);
01217   bool customAddons = codegenConfig.value("CustomAdditions", false).toBool();
01218   QString memberVariables = codegenConfig.value("MemberVariables").toString();
01219   QStringList headerIncludes = codegenConfig.value("IncludeFiles", QStringList()).toStringList();
01220   QStringList sourceIncludes = codegenConfig.value("SourceIncludeFiles", QStringList()).toStringList();
01221   QStringList mutators = codegenConfig.value("Mutators", QStringList()).toStringList();
01222   bool allMutators = false;
01223   if ((mutators.count() == 1) && (mutators.at(0).toLower() == "true"))
01224      allMutators = true;
01225   itemAccessors = codegenConfig.value("ItemAccessors", false).toBool();
01226   bool setUserTexts = codegenConfig.value("SetUserTexts", false).toBool();
01227 
01228   globalEnums = codegenConfig.value("GlobalEnums", false).toBool();
01229   useEnumTypes = codegenConfig.value("UseEnumTypes", false).toBool();
01230 
01231   dpointer = (memberVariables == "dpointer");
01232 
01233   QFile input( inputFilename );
01234 
01235   QDomDocument doc;
01236   QString errorMsg;
01237   int errorRow;
01238   int errorCol;
01239   if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
01240     std::cerr << "Unable to load document." << std::endl;
01241     std::cerr << "Parse error in " << inputFilename << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << std::endl;
01242     return 1;
01243   }
01244 
01245   QDomElement cfgElement = doc.documentElement();
01246 
01247   if ( cfgElement.isNull() ) {
01248     std::cerr << "No document in kcfg file" << std::endl;
01249     return 1;
01250   }
01251 
01252   QString cfgFileName;
01253   bool cfgFileNameArg = false;
01254   QList<Param> parameters;
01255   QList<Signal> signalList;
01256   QStringList includes;
01257   bool hasSignals = false;
01258 
01259   QList<CfgEntry*> entries;
01260 
01261   for ( QDomElement e = cfgElement.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
01262     QString tag = e.tagName();
01263 
01264     if ( tag == "include" ) {
01265       QString includeFile = e.text();
01266       if (!includeFile.isEmpty())
01267         includes.append(includeFile);
01268 
01269     } else if ( tag == "kcfgfile" ) {
01270       cfgFileName = e.attribute( "name" );
01271       cfgFileNameArg = e.attribute( "arg" ).toLower() == "true";
01272       for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
01273         if ( e2.tagName() == "parameter" ) {
01274           Param p;
01275           p.name = e2.attribute( "name" );
01276           p.type = e2.attribute( "type" );
01277           if (p.type.isEmpty())
01278              p.type = "String";
01279           parameters.append( p );
01280         }
01281       }
01282 
01283     } else if ( tag == "group" ) {
01284       QString group = e.attribute( "name" );
01285       if ( group.isEmpty() ) {
01286         std::cerr << "Group without name" << std::endl;
01287         return 1;
01288       }
01289       for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
01290         if ( e2.tagName() != "entry" ) continue;
01291         CfgEntry *entry = parseEntry( group, e2 );
01292         if ( entry ) entries.append( entry );
01293         else {
01294           std::cerr << "Can not parse entry." << std::endl;
01295           return 1;
01296         }
01297       }
01298     }
01299     else if ( tag == "signal" ) {
01300       QString signalName = e.attribute( "name" );
01301       if ( signalName.isEmpty() ) {
01302         std::cerr << "Signal without name." << std::endl;
01303         return 1;
01304       }
01305       Signal theSignal;
01306       theSignal.name = signalName;
01307 
01308       for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
01309         if ( e2.tagName() == "argument") {
01310           SignalArguments argument;
01311           argument.type = e2.attribute("type");
01312           if ( argument.type.isEmpty() ) {
01313             std::cerr << "Signal argument without type." << std::endl;
01314             return 1;
01315           }
01316           argument.variableName = e2.text();
01317           theSignal.arguments.append(argument);
01318         }
01319         else if( e2.tagName() == "label") {
01320           theSignal.label = e2.text();
01321         }
01322       }
01323       signalList.append(theSignal);
01324     }
01325   }
01326 
01327   if ( inherits.isEmpty() ) inherits = "KConfigSkeleton";
01328 
01329   if ( className.isEmpty() ) {
01330     std::cerr << "Class name missing" << std::endl;
01331     return 1;
01332   }
01333 
01334   if ( singleton && !parameters.isEmpty() ) {
01335     std::cerr << "Singleton class can not have parameters" << std::endl;
01336     return 1;
01337   }
01338 
01339   if ( !cfgFileName.isEmpty() && cfgFileNameArg)
01340   {
01341     std::cerr << "Having both a fixed filename and a filename as argument is not possible." << std::endl;
01342     return 1;
01343   }
01344 
01345   if ( entries.isEmpty() ) {
01346     std::cerr << "No entries." << std::endl;
01347   }
01348 
01349 #if 0
01350   CfgEntry *cfg;
01351   for( cfg = entries.first(); cfg; cfg = entries.next() ) {
01352     cfg->dump();
01353   }
01354 #endif
01355 
01356   hasSignals = !signalList.empty();
01357   QString headerFileName = baseName + ".h";
01358   QString implementationFileName = baseName + ".cpp";
01359   QString mocFileName = baseName + ".moc";
01360   QString cppPreamble; // code to be inserted at the beginnin of the cpp file, e.g. initialization of static values
01361 
01362   QFile header( baseDir + headerFileName );
01363   if ( !header.open( QIODevice::WriteOnly ) ) {
01364     std::cerr << "Can not open '" << baseDir  << headerFileName << "for writing." << std::endl;
01365     return 1;
01366   }
01367 
01368   QTextStream h( &header );
01369 
01370   h << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
01371   h << "// All changes you do to this file will be lost." << endl;
01372 
01373   h << "#ifndef " << ( !nameSpace.isEmpty() ? nameSpace.toUpper() + '_' : "" )
01374     << className.toUpper() << "_H" << endl;
01375   h << "#define " << ( !nameSpace.isEmpty() ? nameSpace.toUpper() + '_' : "" )
01376     << className.toUpper() << "_H" << endl << endl;
01377 
01378   // Includes
01379   QStringList::ConstIterator it;
01380   for( it = headerIncludes.constBegin(); it != headerIncludes.constEnd(); ++it ) {
01381     if ( (*it).startsWith('"') )
01382       h << "#include " << *it << endl;
01383     else
01384       h << "#include <" << *it << ">" << endl;
01385   }
01386 
01387   if ( headerIncludes.count() > 0 ) h << endl;
01388 
01389   if ( !singleton && parameters.isEmpty() )
01390     h << "#include <kglobal.h>" << endl;
01391 
01392   h << "#include <kconfigskeleton.h>" << endl;
01393   h << "#include <kdebug.h>" << endl << endl;
01394 
01395   // Includes
01396   for( it = includes.constBegin(); it != includes.constEnd(); ++it ) {
01397     if ( (*it).startsWith('"') )
01398       h << "#include " << *it << endl;
01399     else
01400       h << "#include <" << *it << ">" << endl;
01401   }
01402 
01403   if ( !nameSpace.isEmpty() )
01404     h << "namespace " << nameSpace << " {" << endl << endl;
01405 
01406   // Private class declaration
01407   if ( dpointer )
01408     h << "class " << className << "Private;" << endl << endl;
01409 
01410   // Class declaration header
01411   h << "class " << visibility << className << " : public " << inherits << endl;
01412 
01413   h << "{" << endl;
01414   // Add Q_OBJECT macro if the config need signals.
01415   if( hasSignals )
01416    h << "  Q_OBJECT" << endl;
01417   h << "  public:" << endl;
01418 
01419   // enums
01420   QList<CfgEntry*>::ConstIterator itEntry;
01421   for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01422     const CfgEntry::Choices &choices = (*itEntry)->choices();
01423     QList<CfgEntry::Choice> chlist = choices.choices;
01424     if ( !chlist.isEmpty() ) {
01425       QStringList values;
01426       QList<CfgEntry::Choice>::ConstIterator itChoice;
01427       for( itChoice = chlist.constBegin(); itChoice != chlist.constEnd(); ++itChoice ) {
01428         values.append( choices.prefix + (*itChoice).name );
01429       }
01430       if ( choices.name().isEmpty() ) {
01431         if ( globalEnums ) {
01432           h << "    enum { " << values.join( ", " ) << " };" << endl;
01433         } else {
01434           // Create an automatically named enum
01435           h << "    class " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << endl;
01436           h << "    {" << endl;
01437           h << "      public:" << endl;
01438           h << "      enum type { " << values.join( ", " ) << ", COUNT };" << endl;
01439           h << "    };" << endl;
01440         }
01441       } else if ( !choices.external() ) {
01442         // Create a named enum
01443         h << "    enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << " { " << values.join( ", " ) << " };" << endl;
01444       }
01445     }
01446     QStringList values = (*itEntry)->paramValues();
01447     if ( !values.isEmpty() ) {
01448       if ( globalEnums ) {
01449         // ### FIXME!!
01450         // make the following string table an index-based string search!
01451         // ###
01452         h << "    enum { " << values.join( ", " ) << " };" << endl;
01453         h << "    static const char* const " << enumName( (*itEntry)->param() ) << "ToString[];" << endl;
01454         cppPreamble += "const char* const " + className + "::" + enumName( (*itEntry)->param() ) +
01455            "ToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
01456       } else {
01457         h << "    class " << enumName( (*itEntry)->param() ) << endl;
01458         h << "    {" << endl;
01459         h << "      public:" << endl;
01460         h << "      enum type { " << values.join( ", " ) << ", COUNT };" << endl;
01461         h << "      static const char* const enumToString[];" << endl;
01462         h << "    };" << endl;
01463         cppPreamble += "const char* const " + className + "::" + enumName( (*itEntry)->param() ) +
01464            "::enumToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
01465       }
01466     }
01467   }
01468   if ( hasSignals ) {
01469    h << "\n    enum {" << endl;
01470    unsigned val = 1;
01471    QList<Signal>::ConstIterator it, itEnd = signalList.constEnd();
01472    for ( it = signalList.constBegin(); it != itEnd; val <<= 1) {
01473      if ( !val ) {
01474        std::cerr << "Too many signals to create unique bit masks" << std::endl;
01475        exit(1);
01476      }
01477      Signal signal = *it;
01478      h << "      " << signalEnumName(signal.name) << " = 0x" << hex << val;
01479      if ( ++it != itEnd )
01480       h << ",";
01481      h << endl;
01482    }
01483    h << " };" << dec << endl;
01484   }
01485   h << endl;
01486   // Constructor or singleton accessor
01487   if ( !singleton ) {
01488     h << "    " << className << "(";
01489     if (cfgFileNameArg)
01490     {
01491         if(forceStringFilename)
01492             h << " const QString &cfgfilename"
01493                 << (parameters.isEmpty() ? " = QString()" : ", ");
01494         else
01495             h << " KSharedConfig::Ptr config"
01496                 << (parameters.isEmpty() ? " = KGlobal::config()" : ", ");
01497     }
01498     for (QList<Param>::ConstIterator it = parameters.constBegin();
01499          it != parameters.constEnd(); ++it)
01500     {
01501        if (it != parameters.constBegin())
01502          h << ",";
01503        h << " " << param((*it).type) << " " << (*it).name;
01504     }
01505     h << " );" << endl;
01506   } else {
01507     h << "    static " << className << " *self();" << endl;
01508     if (cfgFileNameArg)
01509     {
01510       h << "    static void instance(const QString& cfgfilename);" << endl;
01511     }
01512   }
01513 
01514   // Destructor
01515   h << "    ~" << className << "();" << endl << endl;
01516 
01517   // global variables
01518   if (staticAccessors)
01519     This = "self()->";
01520   else
01521     Const = " const";
01522 
01523   for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01524     QString n = (*itEntry)->name();
01525     QString t = (*itEntry)->type();
01526 
01527     // Manipulator
01528     if (allMutators || mutators.contains(n))
01529     {
01530       h << "    /**" << endl;
01531       h << "      Set " << (*itEntry)->label() << endl;
01532       h << "    */" << endl;
01533       if (staticAccessors)
01534         h << "    static" << endl;
01535       h << "    void " << setFunction(n) << "( ";
01536       if (!(*itEntry)->param().isEmpty())
01537         h << cppType((*itEntry)->paramType()) << " i, ";
01538       if (useEnumTypes && t == "Enum")
01539         h << enumType(*itEntry);
01540       else
01541         h << param( t );
01542       h << " v )";
01543       // function body inline only if not using dpointer
01544       // for BC mode
01545       if ( !dpointer )
01546       {
01547         h << endl << "    {" << endl;
01548         h << indent(memberMutatorBody(*itEntry), 6 );
01549         h << "    }" << endl;
01550       }
01551       else
01552       {
01553         h << ";" << endl;
01554       }
01555     }
01556     h << endl;
01557     // Accessor
01558     h << "    /**" << endl;
01559     h << "      Get " << (*itEntry)->label() << endl;
01560     h << "    */" << endl;
01561     if (staticAccessors)
01562       h << "    static" << endl;
01563     h << "    ";
01564     if (useEnumTypes && t == "Enum")
01565       h << enumType(*itEntry);
01566     else
01567       h << cppType(t);
01568     h << " " << getFunction(n) << "(";
01569     if (!(*itEntry)->param().isEmpty())
01570       h << " " << cppType((*itEntry)->paramType()) <<" i ";
01571     h << ")" << Const;
01572     // function body inline only if not using dpointer
01573     // for BC mode
01574     if ( !dpointer )
01575     {
01576        h << endl << "    {" << endl;
01577       h << indent(memberAccessorBody((*itEntry)), 6 );
01578        h << "    }" << endl;
01579     }
01580     else
01581     {
01582       h << ";" << endl;
01583     }
01584 
01585     // Item accessor
01586     if ( itemAccessors ) {
01587       h << endl;
01588       h << "    /**" << endl;
01589       h << "      Get Item object corresponding to " << n << "()"
01590         << endl;
01591       h << "    */" << endl;
01592       h << "    Item" << itemType( (*itEntry)->type() ) << " *"
01593         << getFunction( n ) << "Item(";
01594       if (!(*itEntry)->param().isEmpty()) {
01595         h << " " << cppType((*itEntry)->paramType()) << " i ";
01596       }
01597       h << ")";
01598       if (! dpointer )
01599       {
01600         h << endl << "    {" << endl;
01601         h << indent( itemAccessorBody((*itEntry)), 6);
01602         h << "    }" << endl;
01603       }
01604       else
01605       {
01606         h << ";" << endl;
01607       }
01608     }
01609 
01610     h << endl;
01611   }
01612 
01613 
01614   // Signal definition.
01615   if( hasSignals ) {
01616     h << endl;
01617     h << "  Q_SIGNALS:";
01618     foreach(const Signal &signal, signalList) {
01619       h << endl;
01620       if ( !signal.label.isEmpty() ) {
01621         h << "    /**" << endl;
01622         h << "      " << signal.label << endl;
01623         h << "    */" << endl;
01624       }
01625       h << "    void " << signal.name << "(";
01626       QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
01627       for ( it = signal.arguments.constBegin(); it != itEnd; ) {
01628         SignalArguments argument = *it;
01629         QString type = param(argument.type);
01630         if ( useEnumTypes && argument.type == "Enum" ) {
01631           for ( int i = 0, end = entries.count(); i < end; ++i ) {
01632             if ( entries[i]->name() == argument.variableName ) {
01633               type = enumType(entries[i]);
01634               break;
01635             }
01636           }
01637         }
01638         h << type << " " << argument.variableName;
01639         if ( ++it != itEnd ) {
01640          h << ", ";
01641         }
01642       }
01643       h << ");" << endl;
01644     }
01645     h << endl;
01646   }
01647 
01648   h << "  protected:" << endl;
01649 
01650   // Private constructor for singleton
01651   if ( singleton ) {
01652     h << "    " << className << "(";
01653     if ( cfgFileNameArg )
01654       h << "const QString& arg";
01655     h << ");" << endl;
01656     h << "    friend class " << className << "Helper;" << endl << endl;
01657   }
01658 
01659   if ( hasSignals ) {
01660     h << "    virtual void usrWriteConfig();" << endl;
01661   }
01662 
01663   // Member variables
01664   if ( !memberVariables.isEmpty() && memberVariables != "private" && memberVariables != "dpointer") {
01665     h << "  " << memberVariables << ":" << endl;
01666   }
01667 
01668   // Class Parameters
01669   for (QList<Param>::ConstIterator it = parameters.constBegin();
01670        it != parameters.constEnd(); ++it)
01671   {
01672      h << "    " << cppType((*it).type) << " mParam" << (*it).name << ";" << endl;
01673   }
01674 
01675   if ( memberVariables != "dpointer" )
01676   {
01677     QString group;
01678     for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01679       if ( (*itEntry)->group() != group ) {
01680         group = (*itEntry)->group();
01681         h << endl;
01682         h << "    // " << group << endl;
01683       }
01684       h << "    " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name() );
01685       if ( !(*itEntry)->param().isEmpty() )
01686       {
01687         h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01688       }
01689       h << ";" << endl;
01690     }
01691 
01692     h << endl << "  private:" << endl;
01693     if ( itemAccessors ) {
01694        for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01695         h << "    Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry );
01696         if ( !(*itEntry)->param().isEmpty() ) h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01697         h << ";" << endl;
01698       }
01699     }
01700     if ( hasSignals )
01701      h << "    uint " << varName("settingsChanged") << ";" << endl;
01702 
01703   }
01704   else
01705   {
01706     // use a private class for both member variables and items
01707     h << "  private:" << endl;
01708     h << "    " + className + "Private *d;" << endl;
01709   }
01710 
01711   if (customAddons)
01712   {
01713      h << "    // Include custom additions" << endl;
01714      h << "    #include \"" << filenameOnly(baseName) << "_addons.h\"" <<endl;
01715   }
01716 
01717   h << "};" << endl << endl;
01718 
01719   if ( !nameSpace.isEmpty() ) h << "}" << endl << endl;
01720 
01721   h << "#endif" << endl << endl;
01722 
01723 
01724   header.close();
01725 
01726   QFile implementation( baseDir + implementationFileName );
01727   if ( !implementation.open( QIODevice::WriteOnly ) ) {
01728     std::cerr << "Can not open '" << qPrintable(implementationFileName) << "for writing."
01729               << std::endl;
01730     return 1;
01731   }
01732 
01733   QTextStream cpp( &implementation );
01734 
01735 
01736   cpp << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
01737   cpp << "// All changes you do to this file will be lost." << endl << endl;
01738 
01739   cpp << "#include \"" << headerFileName << "\"" << endl << endl;
01740 
01741   for( it = sourceIncludes.constBegin(); it != sourceIncludes.constEnd(); ++it ) {
01742     if ( (*it).startsWith('"') )
01743       cpp << "#include " << *it << endl;
01744     else
01745       cpp << "#include <" << *it << ">" << endl;
01746   }
01747 
01748   if ( sourceIncludes.count() > 0 ) cpp << endl;
01749 
01750   if ( setUserTexts ) cpp << "#include <klocale.h>" << endl << endl;
01751 
01752   // Header required by singleton implementation
01753   if ( singleton )
01754     cpp << "#include <kglobal.h>" << endl << "#include <QtCore/QFile>" << endl << endl;
01755   if ( singleton && cfgFileNameArg )
01756     cpp << "#include <kdebug.h>" << endl << endl;
01757 
01758   if ( !nameSpace.isEmpty() )
01759     cpp << "using namespace " << nameSpace << ";" << endl << endl;
01760 
01761   QString group;
01762 
01763   // private class implementation
01764   if ( dpointer )
01765   {
01766     if ( !nameSpace.isEmpty() )
01767       cpp << "namespace " << nameSpace << " {" << endl;
01768     cpp << "class " << className << "Private" << endl;
01769     cpp << "{" << endl;
01770     cpp << "  public:" << endl;
01771     for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01772       if ( (*itEntry)->group() != group ) {
01773         group = (*itEntry)->group();
01774         cpp << endl;
01775         cpp << "    // " << group << endl;
01776       }
01777       cpp << "    " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name() );
01778       if ( !(*itEntry)->param().isEmpty() )
01779       {
01780         cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01781       }
01782       cpp << ";" << endl;
01783     }
01784     cpp << endl << "    // items" << endl;
01785     for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01786       cpp << "    KConfigSkeleton::Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry );
01787       if ( !(*itEntry)->param().isEmpty() ) cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01788         cpp << ";" << endl;
01789     }
01790     if ( hasSignals ) {
01791       cpp << "    uint " << varName("settingsChanged") << ";" << endl;
01792     }
01793 
01794     cpp << "};" << endl << endl;
01795     if ( !nameSpace.isEmpty() )
01796       cpp << "}" << endl << endl;
01797   }
01798 
01799   // Singleton implementation
01800   if ( singleton ) {
01801     if( !nameSpace.isEmpty() )
01802       cpp << "namespace " << nameSpace << " {" << endl;
01803     cpp << "class " << className << "Helper" << endl;
01804     cpp << '{' << endl;
01805     cpp << "  public:" << endl;
01806     cpp << "    " << className << "Helper() : q(0) {}" << endl;
01807     cpp << "    ~" << className << "Helper() { delete q; }" << endl;
01808     cpp << "    " << className << " *q;" << endl;
01809     cpp << "};" << endl;
01810     if( !nameSpace.isEmpty() )
01811       cpp << "}" << endl;
01812     cpp << "K_GLOBAL_STATIC(" << className << "Helper, s_global" << className << ")" << endl;
01813 
01814     cpp << className << " *" << className << "::self()" << endl;
01815     cpp << "{" << endl;
01816     if ( cfgFileNameArg ) {
01817       cpp << "  if (!s_global" << className << "->q)" << endl;
01818       cpp << "     kFatal() << \"you need to call " << className << "::instance before using\";" << endl;
01819     } else {
01820       cpp << "  if (!s_global" << className << "->q) {" << endl;
01821       cpp << "    new " << className << ';' << endl;
01822       cpp << "    s_global" << className << "->q->readConfig();" << endl;
01823       cpp << "  }" << endl << endl;
01824     }
01825     cpp << "  return s_global" << className << "->q;" << endl;
01826     cpp << "}" << endl << endl;
01827 
01828     if ( cfgFileNameArg ) {
01829       cpp << "void " << className << "::instance(const QString& cfgfilename)" << endl;
01830       cpp << "{" << endl;
01831       cpp << "  if (s_global" << className << "->q) {" << endl;
01832       cpp << "     kDebug() << \"" << className << "::instance called after the first use - ignoring\";" << endl;
01833       cpp << "     return;" << endl;
01834       cpp << "  }" << endl;
01835       cpp << "  new " << className << "(cfgfilename);" << endl;
01836       cpp << "  s_global" << className << "->q->readConfig();" << endl;
01837       cpp << "}" << endl << endl;
01838     }
01839   }
01840 
01841   if ( !cppPreamble.isEmpty() )
01842     cpp << cppPreamble << endl;
01843 
01844   // Constructor
01845   cpp << className << "::" << className << "( ";
01846   if ( cfgFileNameArg ) {
01847     if ( !singleton && ! forceStringFilename)
01848       cpp << " KSharedConfig::Ptr config";
01849     else
01850       cpp << " const QString& config";
01851     cpp << (parameters.isEmpty() ? " " : ", ");
01852   }
01853 
01854   for (QList<Param>::ConstIterator it = parameters.constBegin();
01855        it != parameters.constEnd(); ++it)
01856   {
01857      if (it != parameters.constBegin())
01858        cpp << ",";
01859      cpp << " " << param((*it).type) << " " << (*it).name;
01860   }
01861   cpp << " )" << endl;
01862 
01863   cpp << "  : " << inherits << "(";
01864   if ( !cfgFileName.isEmpty() ) cpp << " QLatin1String( \"" << cfgFileName << "\" ";
01865   if ( cfgFileNameArg ) cpp << " config ";
01866   if ( !cfgFileName.isEmpty() ) cpp << ") ";
01867   cpp << ")" << endl;
01868 
01869   // Store parameters
01870   for (QList<Param>::ConstIterator it = parameters.constBegin();
01871        it != parameters.constEnd(); ++it)
01872   {
01873      cpp << "  , mParam" << (*it).name << "(" << (*it).name << ")" << endl;
01874   }
01875 
01876   if ( hasSignals && !dpointer )
01877     cpp << "  , " << varName("settingsChanged") << "(0)" << endl;
01878 
01879   cpp << "{" << endl;
01880 
01881   if (dpointer)
01882   {
01883     cpp << "  d = new " + className + "Private;" << endl;
01884     if (hasSignals)
01885       cpp << "  " << varPath("settingsChanged") << " = 0;" << endl;
01886   }
01887   // Needed in case the singleton class is used as baseclass for
01888   // another singleton.
01889   if (singleton) {
01890     cpp << "  Q_ASSERT(!s_global" << className << "->q);" << endl;
01891     cpp << "  s_global" << className << "->q = this;" << endl;
01892   }
01893 
01894   group.clear();
01895 
01896   for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01897     if ( (*itEntry)->group() != group ) {
01898       if ( !group.isEmpty() ) cpp << endl;
01899       group = (*itEntry)->group();
01900       cpp << "  setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl;
01901     }
01902 
01903     QString key = paramString( (*itEntry)->key(), parameters );
01904     if ( !(*itEntry)->code().isEmpty() ) {
01905       cpp << (*itEntry)->code() << endl;
01906     }
01907     if ( (*itEntry)->type() == "Enum" ) {
01908       cpp << "  QList<KConfigSkeleton::ItemEnum::Choice2> values"
01909           << (*itEntry)->name() << ";" << endl;
01910       QList<CfgEntry::Choice> choices = (*itEntry)->choices().choices;
01911       QList<CfgEntry::Choice>::ConstIterator it;
01912       for( it = choices.constBegin(); it != choices.constEnd(); ++it ) {
01913         cpp << "  {" << endl;
01914         cpp << "    KConfigSkeleton::ItemEnum::Choice2 choice;" << endl;
01915         cpp << "    choice.name = QLatin1String(\"" << (*it).name << "\");" << endl;
01916         if ( setUserTexts ) {
01917           if ( !(*it).label.isEmpty() ) {
01918             cpp << "    choice.label = ";
01919             if ( !(*it).context.isEmpty() )
01920               cpp << "i18nc(" + quoteString((*it).context) + ", ";
01921             else
01922               cpp << "i18n(";
01923             cpp << quoteString((*it).label) << ");" << endl;
01924           }
01925           if ( !(*it).toolTip.isEmpty() ) {
01926             cpp << "    choice.toolTip = ";
01927             if ( !(*it).context.isEmpty() )
01928               cpp << "i18nc(" + quoteString((*it).context) + ", ";
01929             else
01930               cpp << "i18n(";
01931             cpp << quoteString((*it).toolTip) << ");" << endl;
01932           }
01933           if ( !(*it).whatsThis.isEmpty() ) {
01934             cpp << "    choice.whatsThis = ";
01935             if ( !(*it).context.isEmpty() )
01936               cpp << "i18nc(" + quoteString((*it).context) + ", ";
01937             else
01938               cpp << "i18n(";
01939             cpp << quoteString((*it).whatsThis) << ");" << endl;
01940           }
01941         }
01942         cpp << "    values" << (*itEntry)->name() << ".append( choice );" << endl;
01943         cpp << "  }" << endl;
01944       }
01945     }
01946 
01947     if (!dpointer)
01948       cpp << itemDeclaration( *itEntry );
01949 
01950     if ( (*itEntry)->param().isEmpty() )
01951     {
01952       // Normal case
01953       cpp << "  " << itemPath( *itEntry ) << " = "
01954           << newItem( (*itEntry)->type(), (*itEntry)->name(), key, (*itEntry)->defaultValue() ) << endl;
01955 
01956       if ( !(*itEntry)->minValue().isEmpty() )
01957         cpp << "  " << itemPath( *itEntry ) << "->setMinValue(" << (*itEntry)->minValue() << ");" << endl;
01958       if ( !(*itEntry)->maxValue().isEmpty() )
01959         cpp << "  " << itemPath( *itEntry ) << "->setMaxValue(" << (*itEntry)->maxValue() << ");" << endl;
01960 
01961       if ( setUserTexts )
01962         cpp << userTextsFunctions( (*itEntry) );
01963 
01964       cpp << "  addItem( " << itemPath( *itEntry );
01965       QString quotedName = (*itEntry)->name();
01966       addQuotes( quotedName );
01967       if ( quotedName != key ) cpp << ", QLatin1String( \"" << (*itEntry)->name() << "\" )";
01968       cpp << " );" << endl;
01969     }
01970     else
01971     {
01972       // Indexed
01973       for(int i = 0; i <= (*itEntry)->paramMax(); i++)
01974       {
01975         QString defaultStr;
01976         QString itemVarStr(itemPath( *itEntry )+QString("[%1]").arg(i));
01977 
01978         if ( !(*itEntry)->paramDefaultValue(i).isEmpty() )
01979           defaultStr = (*itEntry)->paramDefaultValue(i);
01980         else if ( !(*itEntry)->defaultValue().isEmpty() )
01981           defaultStr = paramString( (*itEntry)->defaultValue(), (*itEntry), i );
01982         else
01983           defaultStr = defaultValue( (*itEntry)->type() );
01984 
01985         cpp << "  " << itemVarStr << " = "
01986             << newItem( (*itEntry)->type(), (*itEntry)->name(), paramString(key, *itEntry, i), defaultStr, QString("[%1]").arg(i) )
01987             << endl;
01988 
01989         if ( setUserTexts )
01990           cpp << userTextsFunctions( *itEntry, itemVarStr, (*itEntry)->paramName() );
01991 
01992         // Make mutators for enum parameters work by adding them with $(..) replaced by the
01993         // param name. The check for isImmutable in the set* functions doesn't have the param
01994         // name available, just the corresponding enum value (int), so we need to store the
01995         // param names in a separate static list!.
01996         cpp << "  addItem( " << itemVarStr << ", QLatin1String( \"";
01997         if ( (*itEntry)->paramType()=="Enum" )
01998           cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg((*itEntry)->paramValues()[i] );
01999         else
02000           cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg(i);
02001         cpp << "\" ) );" << endl;
02002       }
02003     }
02004   }
02005 
02006   cpp << "}" << endl << endl;
02007 
02008   if (dpointer)
02009   {
02010     // setters and getters go in Cpp if in dpointer mode
02011     for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
02012       QString n = (*itEntry)->name();
02013       QString t = (*itEntry)->type();
02014 
02015       // Manipulator
02016       if (allMutators || mutators.contains(n))
02017       {
02018         cpp << "void " << setFunction(n, className) << "( ";
02019         if ( !(*itEntry)->param().isEmpty() )
02020           cpp << cppType( (*itEntry)->paramType() ) << " i, ";
02021         if (useEnumTypes && t == "Enum")
02022           cpp << enumType(*itEntry);
02023         else
02024           cpp << param( t );
02025         cpp << " v )";
02026         // function body inline only if not using dpointer
02027         // for BC mode
02028         cpp << "{" << endl;
02029         cpp << indent(memberMutatorBody( *itEntry ), 6);
02030         cpp << "}" << endl << endl;
02031       }
02032 
02033       // Accessor
02034       if (useEnumTypes && t == "Enum")
02035         cpp << enumType(*itEntry);
02036       else
02037         cpp << cppType(t);
02038       cpp << " " << getFunction(n, className) << "(";
02039       if ( !(*itEntry)->param().isEmpty() )
02040         cpp << " " << cppType( (*itEntry)->paramType() ) <<" i ";
02041       cpp << ")" << Const << endl;
02042       // function body inline only if not using dpointer
02043       // for BC mode
02044       cpp << "{" << endl;
02045       cpp << indent(memberAccessorBody( *itEntry ), 2);
02046       cpp << "}" << endl << endl;
02047 
02048       // Item accessor
02049       if ( itemAccessors )
02050       {
02051         cpp << endl;
02052         cpp << "KConfigSkeleton::Item" << itemType( (*itEntry)->type() ) << " *"
02053           << getFunction( n, className ) << "Item(";
02054         if ( !(*itEntry)->param().isEmpty() ) {
02055           cpp << " " << cppType( (*itEntry)->paramType() ) << " i ";
02056         }
02057         cpp << ")" << endl;
02058         cpp << "{" << endl;
02059         cpp << indent(itemAccessorBody( *itEntry ), 2);
02060         cpp << "}" << endl;
02061       }
02062 
02063       cpp << endl;
02064     }
02065   }
02066 
02067   // Destructor
02068   cpp << className << "::~" << className << "()" << endl;
02069   cpp << "{" << endl;
02070   if ( singleton ) {
02071     if ( dpointer )
02072       cpp << "  delete d;" << endl;
02073     cpp << "  if (!s_global" << className << ".isDestroyed()) {" << endl;
02074     cpp << "    s_global" << className << "->q = 0;" << endl;
02075     cpp << "  }" << endl;
02076   }
02077   cpp << "}" << endl << endl;
02078 
02079   if ( hasSignals ) {
02080     cpp << "void " << className << "::" << "usrWriteConfig()" << endl;
02081     cpp << "{" << endl;
02082     cpp << "  " << inherits << "::usrWriteConfig();" << endl << endl;
02083     foreach(const Signal &signal, signalList) {
02084       cpp << "  if ( " << varPath("settingsChanged") << " & " << signalEnumName(signal.name) << " ) " << endl;
02085       cpp << "    emit " << signal.name << "(";
02086       QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
02087       for ( it = signal.arguments.constBegin(); it != itEnd; ) {
02088         SignalArguments argument = *it;
02089         bool cast = false;
02090         if ( useEnumTypes && argument.type == "Enum" ) {
02091           for ( int i = 0, end = entries.count(); i < end; ++i ) {
02092             if ( entries[i]->name() == argument.variableName ) {
02093               cpp << "static_cast<" << enumType(entries[i]) << ">(";
02094               cast = true;
02095               break;
02096             }
02097           }
02098         }
02099         cpp << varPath(argument.variableName);
02100         if ( cast )
02101           cpp << ")";
02102         if ( ++it != itEnd )
02103           cpp << ", ";
02104       }
02105       cpp << ");" << endl << endl;
02106     }
02107     cpp << "  " << varPath("settingsChanged") << " = 0;" << endl;
02108     cpp << "}" << endl;
02109   }
02110 
02111   // Add includemoc if they are signals defined.
02112   if( hasSignals ) {
02113     cpp << endl;
02114     cpp << "#include \"" << mocFileName << "\"" << endl;
02115     cpp << endl;
02116   }
02117 
02118   // clear entries list
02119   qDeleteAll( entries );
02120 
02121   implementation.close();
02122 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal