• Skip to content
  • Skip to link menu
KDE 4.2 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 
00446     } else if ( (type == "StringList" || type == "PathList") && !defaultValue.isEmpty() ) {
00447       QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
00448       if (!code.isEmpty())
00449          cpp << endl;
00450 
00451       cpp << "  QStringList default" << name << ";" << endl;
00452       const QStringList defaults = defaultValue.split( ',' );
00453       QStringList::ConstIterator it;
00454       for( it = defaults.constBegin(); it != defaults.constEnd(); ++it ) {
00455         cpp << "  default" << name << ".append( QString::fromUtf8( \"" << *it << "\" ) );"
00456             << endl;
00457       }
00458       defaultValue = "default" + name;
00459 
00460     } else if ( type == "Color" && !defaultValue.isEmpty() ) {
00461       QRegExp colorRe("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?");
00462       if (colorRe.exactMatch(defaultValue))
00463       {
00464         defaultValue = "QColor( " + defaultValue + " )";
00465       }
00466       else
00467       {
00468         defaultValue = "QColor( \"" + defaultValue + "\" )";
00469       }
00470 
00471     } else if ( type == "Enum" ) {
00472       QList<CfgEntry::Choice>::ConstIterator it;
00473       for( it = choices.choices.constBegin(); it != choices.choices.constEnd(); ++it ) {
00474         if ( (*it).name == defaultValue ) {
00475           if ( globalEnums && choices.name().isEmpty() )
00476             defaultValue.prepend( choices.prefix );
00477           else
00478             defaultValue.prepend( enumTypeQualifier(name, choices) + choices.prefix );
00479           break;
00480         }
00481       }
00482 
00483     } else if ( type == "IntList" ) {
00484       QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
00485       if (!code.isEmpty())
00486          cpp << endl;
00487 
00488       cpp << "  QList<int> default" << name << ";" << endl;
00489       if (!defaultValue.isEmpty())
00490       {
00491         QStringList defaults = defaultValue.split( ',' );
00492         QStringList::ConstIterator it;
00493         for( it = defaults.constBegin(); it != defaults.constEnd(); ++it ) {
00494           cpp << "  default" << name << ".append( " << *it << " );"
00495               << endl;
00496         }
00497       }
00498       defaultValue = "default" + name;
00499     }
00500 }
00501 
00502 
00503 CfgEntry *parseEntry( const QString &group, const QDomElement &element )
00504 {
00505   bool defaultCode = false;
00506   QString type = element.attribute( "type" );
00507   QString name = element.attribute( "name" );
00508   QString key = element.attribute( "key" );
00509   QString hidden = element.attribute( "hidden" );
00510   QString context = element.attribute( "context" );
00511   QString label;
00512   QString toolTip;
00513   QString whatsThis;
00514   QString defaultValue;
00515   QString code;
00516   QString param;
00517   QString paramName;
00518   QString paramType;
00519   CfgEntry::Choices choices;
00520   QList<Signal> signalList;
00521   QStringList paramValues;
00522   QStringList paramDefaultValues;
00523   QString minValue;
00524   QString maxValue;
00525   int paramMax = 0;
00526 
00527   for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
00528     QString tag = e.tagName();
00529     if ( tag == "label" ) {
00530       label = e.text();
00531       context = e.attribute( "context" );
00532     }
00533     else if ( tag == "tooltip" ) {
00534       toolTip = e.text();
00535       context = e.attribute( "context" );
00536     }
00537     else if ( tag == "whatsthis" ) {
00538       whatsThis = e.text();
00539       context = e.attribute( "context" );
00540     }
00541     else if ( tag == "min" ) minValue = e.text();
00542     else if ( tag == "max" ) maxValue = e.text();
00543     else if ( tag == "code" ) code = e.text();
00544     else if ( tag == "parameter" )
00545     {
00546       param = e.attribute( "name" );
00547       paramType = e.attribute( "type" );
00548       if ( param.isEmpty() ) {
00549         std::cerr << "Parameter must have a name: " << qPrintable(dumpNode(e)) << std::endl;
00550         return 0;
00551       }
00552       if ( paramType.isEmpty() ) {
00553         std::cerr << "Parameter must have a type: " << qPrintable(dumpNode(e)) << std::endl;
00554         return 0;
00555       }
00556       if ((paramType == "Int") || (paramType == "UInt"))
00557       {
00558          bool ok;
00559          paramMax = e.attribute("max").toInt(&ok);
00560          if (!ok)
00561          {
00562            std::cerr << "Integer parameter must have a maximum (e.g. max=\"0\"): "
00563                        << qPrintable(dumpNode(e)) << std::endl;
00564            return 0;
00565          }
00566       }
00567       else if (paramType == "Enum")
00568       {
00569          for ( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
00570            if (e2.tagName() == "values")
00571            {
00572              for ( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) {
00573                if (e3.tagName() == "value")
00574                {
00575                   paramValues.append( e3.text() );
00576                }
00577              }
00578              break;
00579            }
00580          }
00581          if (paramValues.isEmpty())
00582          {
00583            std::cerr << "No values specified for parameter '" << qPrintable(param)
00584                        << "'." << std::endl;
00585            return 0;
00586          }
00587          paramMax = paramValues.count()-1;
00588       }
00589       else
00590       {
00591         std::cerr << "Parameter '" << qPrintable(param) << "' has type " << qPrintable(paramType)
00592                     << " but must be of type int, uint or Enum." << std::endl;
00593         return 0;
00594       }
00595     }
00596     else if ( tag == "default" )
00597     {
00598       if (e.attribute("param").isEmpty())
00599       {
00600         defaultValue = e.text();
00601         if (e.attribute( "code" ) == "true")
00602           defaultCode = true;
00603       }
00604     }
00605     else if ( tag == "choices" ) {
00606       QString name = e.attribute( "name" );
00607       QString prefix = e.attribute( "prefix" );
00608       QList<CfgEntry::Choice> chlist;
00609       for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
00610         if ( e2.tagName() == "choice" ) {
00611           CfgEntry::Choice choice;
00612           choice.name = e2.attribute( "name" );
00613           if ( choice.name.isEmpty() ) {
00614             std::cerr << "Tag <choice> requires attribute 'name'." << std::endl;
00615           }
00616           for( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) {
00617             if ( e3.tagName() == "label" ) {
00618               choice.label = e3.text();
00619               choice.context = e3.attribute( "context" );
00620             }
00621             if ( e3.tagName() == "tooltip" ) {
00622               choice.toolTip = e3.text();
00623               choice.context = e3.attribute( "context" );
00624             }
00625             if ( e3.tagName() == "whatsthis" ) {
00626               choice.whatsThis = e3.text();
00627               choice.context = e3.attribute( "context" );
00628             }
00629           }
00630           chlist.append( choice );
00631         }
00632       }
00633       choices = CfgEntry::Choices( chlist, name, prefix );
00634     }
00635    else if ( tag == "emit" ) {
00636     QDomNode signalNode;
00637     Signal signal;
00638     signal.name = e.attribute( "signal" );
00639     signalList.append( signal);
00640    }
00641   }
00642 
00643 
00644   bool nameIsEmpty = name.isEmpty();
00645   if ( nameIsEmpty && key.isEmpty() ) {
00646     std::cerr << "Entry must have a name or a key: " << qPrintable(dumpNode(element)) << std::endl;
00647     return 0;
00648   }
00649 
00650   if ( key.isEmpty() ) {
00651     key = name;
00652   }
00653 
00654   if ( nameIsEmpty ) {
00655     name = key;
00656     name.remove( ' ' );
00657   } else if ( name.contains( ' ' ) ) {
00658     std::cout<<"Entry '"<<qPrintable(name)<<"' contains spaces! <name> elements can not contain spaces!"<<std::endl;
00659     name.remove( ' ' );
00660   }
00661 
00662   if (name.contains("$("))
00663   {
00664     if (param.isEmpty())
00665     {
00666       std::cerr << "Name may not be parameterized: " << qPrintable(name) << std::endl;
00667       return 0;
00668     }
00669   }
00670   else
00671   {
00672     if (!param.isEmpty())
00673     {
00674       std::cerr << "Name must contain '$(" << qPrintable(param) << ")': " << qPrintable(name) << std::endl;
00675       return 0;
00676     }
00677   }
00678 
00679   if ( label.isEmpty() ) {
00680     label = key;
00681   }
00682 
00683   if ( type.isEmpty() ) type = "String"; // XXX : implicit type might be bad
00684 
00685   if (!param.isEmpty())
00686   {
00687     // Adjust name
00688     paramName = name;
00689     name.remove("$("+param+')');
00690     // Lookup defaults for indexed entries
00691     for(int i = 0; i <= paramMax; i++)
00692     {
00693       paramDefaultValues.append(QString());
00694     }
00695 
00696     for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
00697       QString tag = e.tagName();
00698       if ( tag == "default" )
00699       {
00700         QString index = e.attribute("param");
00701         if (index.isEmpty())
00702            continue;
00703 
00704         bool ok;
00705         int i = index.toInt(&ok);
00706         if (!ok)
00707         {
00708           i = paramValues.indexOf(index);
00709           if (i == -1)
00710           {
00711             std::cerr << "Index '" << qPrintable(index) << "' for default value is unknown." << std::endl;
00712             return 0;
00713           }
00714         }
00715 
00716         if ((i < 0) || (i > paramMax))
00717         {
00718           std::cerr << "Index '" << i << "' for default value is out of range [0, "<< paramMax<<"]." << std::endl;
00719           return 0;
00720         }
00721 
00722         QString tmpDefaultValue = e.text();
00723 
00724         if (e.attribute( "code" ) != "true")
00725            preProcessDefault(tmpDefaultValue, name, type, choices, code);
00726 
00727         paramDefaultValues[i] = tmpDefaultValue;
00728       }
00729     }
00730   }
00731 
00732   if (!validNameRegexp->exactMatch(name))
00733   {
00734     if (nameIsEmpty)
00735       std::cerr << "The key '" << qPrintable(key) << "' can not be used as name for the entry because "
00736                    "it is not a valid name. You need to specify a valid name for this entry." << std::endl;
00737     else
00738       std::cerr << "The name '" << qPrintable(name) << "' is not a valid name for an entry." << std::endl;
00739     return 0;
00740   }
00741 
00742   if (allNames.contains(name))
00743   {
00744     if (nameIsEmpty)
00745       std::cerr << "The key '" << qPrintable(key) << "' can not be used as name for the entry because "
00746                    "it does not result in a unique name. You need to specify a unique name for this entry." << std::endl;
00747     else
00748       std::cerr << "The name '" << qPrintable(name) << "' is not unique." << std::endl;
00749     return 0;
00750   }
00751   allNames.append(name);
00752 
00753   if (!defaultCode)
00754   {
00755     preProcessDefault(defaultValue, name, type, choices, code);
00756   }
00757 
00758   CfgEntry *result = new CfgEntry( group, type, key, name, context, label, toolTip, whatsThis,
00759                                    code, defaultValue, choices, signalList,
00760                                    hidden == "true" );
00761   if (!param.isEmpty())
00762   {
00763     result->setParam(param);
00764     result->setParamName(paramName);
00765     result->setParamType(paramType);
00766     result->setParamValues(paramValues);
00767     result->setParamDefaultValues(paramDefaultValues);
00768     result->setParamMax(paramMax);
00769   }
00770   result->setMinValue(minValue);
00771   result->setMaxValue(maxValue);
00772 
00773   return result;
00774 }
00775 
00779 QString param( const QString &type )
00780 {
00781     if ( type == "String" )           return "const QString &";
00782     else if ( type == "StringList" )  return "const QStringList &";
00783     else if ( type == "Font" )        return "const QFont &";
00784     else if ( type == "Rect" )        return "const QRect &";
00785     else if ( type == "Size" )        return "const QSize &";
00786     else if ( type == "Color" )       return "const QColor &";
00787     else if ( type == "Point" )       return "const QPoint &";
00788     else if ( type == "Int" )         return "int";
00789     else if ( type == "UInt" )        return "uint";
00790     else if ( type == "Bool" )        return "bool";
00791     else if ( type == "Double" )      return "double";
00792     else if ( type == "DateTime" )    return "const QDateTime &";
00793     else if ( type == "LongLong" )    return "qint64";
00794     else if ( type == "ULongLong" )   return "quint64";
00795     else if ( type == "IntList" )     return "const QList<int> &";
00796     else if ( type == "Enum" )        return "int";
00797     else if ( type == "Path" )        return "const QString &";
00798     else if ( type == "PathList" )    return "const QStringList &";
00799     else if ( type == "Password" )    return "const QString &";
00800     else if ( type == "Url" )         return "const KUrl &";
00801     else if ( type == "UrlList" )     return "const KUrl::List &";
00802     else {
00803         std::cerr <<"kconfig_compiler does not support type \""<< type <<"\""<<std::endl;
00804         return "QString"; //For now, but an assert would be better
00805     }
00806 }
00807 
00811 QString cppType( const QString &type )
00812 {
00813     if ( type == "String" )           return "QString";
00814     else if ( type == "StringList" )  return "QStringList";
00815     else if ( type == "Font" )        return "QFont";
00816     else if ( type == "Rect" )        return "QRect";
00817     else if ( type == "Size" )        return "QSize";
00818     else if ( type == "Color" )       return "QColor";
00819     else if ( type == "Point" )       return "QPoint";
00820     else if ( type == "Int" )         return "int";
00821     else if ( type == "UInt" )        return "uint";
00822     else if ( type == "Bool" )        return "bool";
00823     else if ( type == "Double" )      return "double";
00824     else if ( type == "DateTime" )    return "QDateTime";
00825     else if ( type == "LongLong" )    return "qint64";
00826     else if ( type == "ULongLong" )   return "quint64";
00827     else if ( type == "IntList" )     return "QList<int>";
00828     else if ( type == "Enum" )        return "int";
00829     else if ( type == "Path" )        return "QString";
00830     else if ( type == "PathList" )    return "QStringList";
00831     else if ( type == "Password" )    return "QString";
00832     else if ( type == "Url" )         return "KUrl";
00833     else if ( type == "UrlList" )     return "KUrl::List";
00834     else {
00835         std::cerr<<"kconfig_compiler does not support type \""<< type <<"\""<<std::endl;
00836         return "QString"; //For now, but an assert would be better
00837     }
00838 }
00839 
00840 QString defaultValue( const QString &type )
00841 {
00842     if ( type == "String" )           return "\"\""; // Use empty string, not null string!
00843     else if ( type == "StringList" )  return "QStringList()";
00844     else if ( type == "Font" )        return "QFont()";
00845     else if ( type == "Rect" )        return "QRect()";
00846     else if ( type == "Size" )        return "QSize()";
00847     else if ( type == "Color" )       return "QColor(128, 128, 128)";
00848     else if ( type == "Point" )       return "QPoint()";
00849     else if ( type == "Int" )         return "0";
00850     else if ( type == "UInt" )        return "0";
00851     else if ( type == "Bool" )        return "false";
00852     else if ( type == "Double" )      return "0.0";
00853     else if ( type == "DateTime" )    return "QDateTime()";
00854     else if ( type == "LongLong" )    return "0";
00855     else if ( type == "ULongLong" )   return "0";
00856     else if ( type == "IntList" )     return "QList<int>()";
00857     else if ( type == "Enum" )        return "0";
00858     else if ( type == "Path" )        return "\"\""; // Use empty string, not null string!
00859     else if ( type == "PathList" )    return "QStringList()";
00860     else if ( type == "Password" )    return "\"\""; // Use empty string, not null string!
00861     else if ( type == "Url" )         return "KUrl()";
00862     else if ( type == "UrlList" )     return "KUrl::List()";
00863     else {
00864         std::cerr<<"Error, kconfig_compiler does not support the \""<< type <<"\" type!"<<std::endl;
00865         return "QString"; //For now, but an assert would be better
00866     }
00867 }
00868 
00869 QString itemType( const QString &type )
00870 {
00871   QString t;
00872 
00873   t = type;
00874   t.replace( 0, 1, t.left( 1 ).toUpper() );
00875 
00876   return t;
00877 }
00878 
00879 static QString itemDeclaration(const CfgEntry *e)
00880 {
00881   if (itemAccessors)
00882      return QString();
00883 
00884   QString fCap = e->name();
00885   fCap[0] = fCap[0].toUpper();
00886   return "  KConfigSkeleton::Item"+itemType( e->type() ) +
00887          "  *item" + fCap +
00888          ( (!e->param().isEmpty())?(QString("[%1]").arg(e->paramMax()+1)) : QString()) +
00889          ";\n";
00890 }
00891 
00892 // returns the name of an item variable
00893 // use itemPath to know the full path
00894 // like using d-> in case of dpointer
00895 static QString itemVar(const CfgEntry *e)
00896 {
00897   QString result;
00898   if (itemAccessors)
00899   {
00900     if ( !dpointer )
00901     {
00902       result = 'm' + e->name() + "Item";
00903       result[1] = result[1].toUpper();
00904     }
00905     else
00906     {
00907       result = e->name() + "Item";
00908       result[0] = result[0].toLower();
00909     }
00910   }
00911   else
00912   {
00913     result = "item" + e->name();
00914     result[4] = result[4].toUpper();
00915   }
00916   return result;
00917 }
00918 
00919 static QString itemPath(const CfgEntry *e)
00920 {
00921   QString result;
00922   if ( dpointer ) {
00923     result = "d->"+itemVar(e);
00924   }
00925   else {
00926     result = itemVar(e);
00927   }
00928   return result;
00929 }
00930 
00931 QString newItem( const QString &type, const QString &name, const QString &key,
00932                  const QString &defaultValue, const QString &param = QString())
00933 {
00934   QString t = "new KConfigSkeleton::Item" + itemType( type ) +
00935               "( currentGroup(), " + key + ", " + varPath( name ) + param;
00936   if ( type == "Enum" ) t += ", values" + name;
00937   if ( !defaultValue.isEmpty() ) {
00938     t += ", ";
00939     if ( type == "String" ) t += defaultValue;
00940     else t+= defaultValue;
00941   }
00942   t += " );";
00943 
00944   return t;
00945 }
00946 
00947 QString paramString(const QString &s, const CfgEntry *e, int i)
00948 {
00949   QString result = s;
00950   QString needle = "$("+e->param()+')';
00951   if (result.contains(needle))
00952   {
00953     QString tmp;
00954     if (e->paramType() == "Enum")
00955     {
00956       tmp = e->paramValues()[i];
00957     }
00958     else
00959     {
00960       tmp = QString::number(i);
00961     }
00962 
00963     result.replace(needle, tmp);
00964   }
00965   return result;
00966 }
00967 
00968 QString paramString(const QString &group, const QList<Param> &parameters)
00969 {
00970   QString paramString = group;
00971   QString arguments;
00972   int i = 1;
00973   for (QList<Param>::ConstIterator it = parameters.constBegin();
00974        it != parameters.constEnd(); ++it)
00975   {
00976      if (paramString.contains("$("+(*it).name+')'))
00977      {
00978        QString tmp;
00979        tmp.sprintf("%%%d", i++);
00980        paramString.replace("$("+(*it).name+')', tmp);
00981        arguments += ".arg( mParam"+(*it).name+" )";
00982      }
00983   }
00984   if (arguments.isEmpty())
00985     return "QLatin1String( \""+group+"\" )";
00986 
00987   return "QString( QLatin1String( \""+paramString+"\" ) )"+arguments;
00988 }
00989 
00990 /* int i is the value of the parameter */
00991 QString userTextsFunctions( CfgEntry *e, QString itemVarStr=QString(), QString i=QString() )
00992 {
00993   QString txt;
00994   if (itemVarStr.isNull()) itemVarStr=itemPath(e);
00995   if ( !e->label().isEmpty() ) {
00996     txt += "  " + itemVarStr + "->setLabel( ";
00997     if ( !e->context().isEmpty() )
00998       txt += "i18nc(" + quoteString(e->context()) + ", ";
00999     else
01000       txt += "i18n(";
01001     if ( !e->param().isEmpty() )
01002       txt += quoteString(e->label().replace("$("+e->param()+')', i));
01003     else
01004       txt+= quoteString(e->label());
01005     txt+= ") );\n";
01006   }
01007   if ( !e->toolTip().isEmpty() ) {
01008     txt += "  " + itemVarStr + "->setToolTip( ";
01009     if ( !e->context().isEmpty() )
01010       txt += "i18nc(" + quoteString(e->context()) + ", ";
01011     else
01012       txt += "i18n(";
01013     if ( !e->param().isEmpty() )
01014       txt += quoteString(e->toolTip().replace("$("+e->param()+')', i));
01015     else
01016       txt+= quoteString(e->toolTip());
01017     txt+=") );\n";
01018   }
01019   if ( !e->whatsThis().isEmpty() ) {
01020     txt += "  " + itemVarStr + "->setWhatsThis( ";
01021     if ( !e->context().isEmpty() )
01022       txt += "i18nc(" + quoteString(e->context()) + ", ";
01023     else
01024       txt += "i18n(";
01025     if ( !e->param().isEmpty() )
01026       txt += quoteString(e->whatsThis().replace("$("+e->param()+')', i));
01027     else
01028       txt+= quoteString(e->whatsThis());
01029     txt+=") );\n";
01030   }
01031   return txt;
01032 }
01033 
01034 // returns the member accesor implementation
01035 // which should go in the h file if inline
01036 // or the cpp file if not inline
01037 QString memberAccessorBody( CfgEntry *e )
01038 {
01039     QString result;
01040     QTextStream out(&result, QIODevice::WriteOnly);
01041     QString n = e->name();
01042     QString t = e->type();
01043     bool useEnumType = useEnumTypes && t == "Enum";
01044 
01045     out << "return ";
01046     if (useEnumType)
01047       out << "static_cast<" << enumType(e) << ">(";
01048     out << This << varPath(n);
01049     if (!e->param().isEmpty())
01050       out << "[i]";
01051     if (useEnumType)
01052       out << ")";
01053     out << ";" << endl;
01054 
01055     return result;
01056 }
01057 
01058 // returns the member mutator implementation
01059 // which should go in the h file if inline
01060 // or the cpp file if not inline
01061 QString memberMutatorBody( CfgEntry *e )
01062 {
01063   QString result;
01064   QTextStream out(&result, QIODevice::WriteOnly);
01065   QString n = e->name();
01066   QString t = e->type();
01067 
01068   if (!e->minValue().isEmpty())
01069   {
01070     out << "if (v < " << e->minValue() << ")" << endl;
01071     out << "{" << endl;
01072     out << "  kDebug() << \"" << setFunction(n);
01073     out << ": value \" << v << \" is less than the minimum value of ";
01074     out << e->minValue()<< "\" << endl;" << endl;
01075     out << "  v = " << e->minValue() << ";" << endl;
01076     out << "}" << endl;
01077   }
01078 
01079   if (!e->maxValue().isEmpty())
01080   {
01081     out << endl << "if (v > " << e->maxValue() << ")" << endl;
01082     out << "{" << endl;
01083     out << "  kDebug() << \"" << setFunction(n);
01084     out << ": value \" << v << \" is greater than the maximum value of ";
01085     out << e->maxValue()<< "\" << endl;" << endl;
01086     out << "  v = " << e->maxValue() << ";" << endl;
01087     out << "}" << endl << endl;
01088   }
01089 
01090   out << "if (!" << This << "isImmutable( QString::fromLatin1 ( \"";
01091   if (!e->param().isEmpty())
01092   {
01093     out << e->paramName().replace("$("+e->param()+")", "%1") << "\" ).arg( ";
01094     if ( e->paramType() == "Enum" ) {
01095       out << "QLatin1String( ";
01096 
01097       if (globalEnums)
01098         out << enumName(e->param()) << "ToString[i]";
01099       else
01100         out << enumName(e->param()) << "::enumToString[i]";
01101 
01102         out << " )";
01103     }
01104     else
01105     {
01106       out << "i";
01107     }
01108     out << " )";
01109   }
01110   else
01111   {
01112     out << n << "\" )";
01113   }
01114   out << " ))" << (!e->signalList().empty() ? " {" : "") << endl;
01115   out << "  " << This << varPath(n);
01116   if (!e->param().isEmpty())
01117     out << "[i]";
01118   out << " = v;" << endl;
01119 
01120   if ( !e->signalList().empty() ) {
01121     foreach(const Signal &signal, e->signalList()) {
01122       out << "  " << This << varPath("settingsChanged") << " |= " << signalEnumName(signal.name) << ";" << endl;
01123     }
01124     out << "}" << endl;
01125   }
01126 
01127   return result;
01128 }
01129 
01130 // returns the item accesor implementation
01131 // which should go in the h file if inline
01132 // or the cpp file if not inline
01133 QString itemAccessorBody( CfgEntry *e )
01134 {
01135     QString result;
01136     QTextStream out(&result, QIODevice::WriteOnly);
01137 
01138     out << "return " << itemPath(e);
01139     if (!e->param().isEmpty()) out << "[i]";
01140     out << ";" << endl;
01141 
01142     return result;
01143 }
01144 
01145 //indents text adding X spaces per line
01146 QString indent(QString text, int spaces)
01147 {
01148     QString result;
01149     QTextStream out(&result, QIODevice::WriteOnly);
01150     QTextStream in(&text, QIODevice::ReadOnly);
01151     QString currLine;
01152     while ( !in.atEnd() )
01153     {
01154       currLine = in.readLine();
01155       if (!currLine.isEmpty())
01156         for (int i=0; i < spaces; i++)
01157           out << " ";
01158       out << currLine << endl;
01159     }
01160     return result;
01161 }
01162 
01163 
01164 int main( int argc, char **argv )
01165 {
01166   QCoreApplication app(argc, argv);
01167 
01168   validNameRegexp = new QRegExp("[a-zA-Z_][a-zA-Z0-9_]*");
01169 
01170   QString directoryName, inputFilename, codegenFilename;
01171   parseArgs(app.arguments(), directoryName, inputFilename, codegenFilename);
01172 
01173   QString baseDir = directoryName;
01174 #ifdef Q_OS_WIN
01175   if (!baseDir.endsWith('/') && !baseDir.endsWith('\\'))
01176 #else
01177   if (!baseDir.endsWith('/'))
01178 #endif
01179     baseDir.append("/");
01180 
01181   if (!codegenFilename.endsWith(".kcfgc"))
01182   {
01183     std::cerr << "Codegen options file must have extension .kcfgc" << std::endl;
01184     return 1;
01185   }
01186   QString baseName = QFileInfo(codegenFilename).fileName();
01187   baseName = baseName.left(baseName.length() - 6);
01188 
01189   QSettings codegenConfig(codegenFilename, QSettings::IniFormat);
01190 
01191   QString nameSpace = codegenConfig.value("NameSpace").toString();
01192   QString className = codegenConfig.value("ClassName").toString();
01193   QString inherits = codegenConfig.value("Inherits").toString();
01194   QString visibility = codegenConfig.value("Visibility").toString();
01195   if (!visibility.isEmpty()) visibility+=' ';
01196   bool forceStringFilename = codegenConfig.value("ForceStringFilename", false).toBool();
01197   bool singleton = codegenConfig.value("Singleton", false).toBool();
01198   bool staticAccessors = singleton;
01199   //bool useDPointer = codegenConfig.readEntry("DPointer", false);
01200   bool customAddons = codegenConfig.value("CustomAdditions", false).toBool();
01201   QString memberVariables = codegenConfig.value("MemberVariables").toString();
01202   QStringList headerIncludes = codegenConfig.value("IncludeFiles", QStringList()).toStringList();
01203   QStringList sourceIncludes = codegenConfig.value("SourceIncludeFiles", QStringList()).toStringList();
01204   QStringList mutators = codegenConfig.value("Mutators", QStringList()).toStringList();
01205   bool allMutators = false;
01206   if ((mutators.count() == 1) && (mutators.at(0).toLower() == "true"))
01207      allMutators = true;
01208   itemAccessors = codegenConfig.value("ItemAccessors", false).toBool();
01209   bool setUserTexts = codegenConfig.value("SetUserTexts", false).toBool();
01210 
01211   globalEnums = codegenConfig.value("GlobalEnums", false).toBool();
01212   useEnumTypes = codegenConfig.value("UseEnumTypes", false).toBool();
01213 
01214   dpointer = (memberVariables == "dpointer");
01215 
01216   QFile input( inputFilename );
01217 
01218   QDomDocument doc;
01219   QString errorMsg;
01220   int errorRow;
01221   int errorCol;
01222   if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
01223     std::cerr << "Unable to load document." << std::endl;
01224     std::cerr << "Parse error in " << inputFilename << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << std::endl;
01225     return 1;
01226   }
01227 
01228   QDomElement cfgElement = doc.documentElement();
01229 
01230   if ( cfgElement.isNull() ) {
01231     std::cerr << "No document in kcfg file" << std::endl;
01232     return 1;
01233   }
01234 
01235   QString cfgFileName;
01236   bool cfgFileNameArg = false;
01237   QList<Param> parameters;
01238   QList<Signal> signalList;
01239   QStringList includes;
01240   bool hasSignals = false;
01241 
01242   QList<CfgEntry*> entries;
01243 
01244   for ( QDomElement e = cfgElement.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
01245     QString tag = e.tagName();
01246 
01247     if ( tag == "include" ) {
01248       QString includeFile = e.text();
01249       if (!includeFile.isEmpty())
01250         includes.append(includeFile);
01251 
01252     } else if ( tag == "kcfgfile" ) {
01253       cfgFileName = e.attribute( "name" );
01254       cfgFileNameArg = e.attribute( "arg" ).toLower() == "true";
01255       for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
01256         if ( e2.tagName() == "parameter" ) {
01257           Param p;
01258           p.name = e2.attribute( "name" );
01259           p.type = e2.attribute( "type" );
01260           if (p.type.isEmpty())
01261              p.type = "String";
01262           parameters.append( p );
01263         }
01264       }
01265 
01266     } else if ( tag == "group" ) {
01267       QString group = e.attribute( "name" );
01268       if ( group.isEmpty() ) {
01269         std::cerr << "Group without name" << std::endl;
01270         return 1;
01271       }
01272       for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
01273         if ( e2.tagName() != "entry" ) continue;
01274         CfgEntry *entry = parseEntry( group, e2 );
01275         if ( entry ) entries.append( entry );
01276         else {
01277           std::cerr << "Can not parse entry." << std::endl;
01278           return 1;
01279         }
01280       }
01281     }
01282     else if ( tag == "signal" ) {
01283       QString signalName = e.attribute( "name" );
01284       if ( signalName.isEmpty() ) {
01285         std::cerr << "Signal without name." << std::endl;
01286         return 1;
01287       }
01288       Signal theSignal;
01289       theSignal.name = signalName;
01290 
01291       for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
01292         if ( e2.tagName() == "argument") {
01293           SignalArguments argument;
01294           argument.type = e2.attribute("type");
01295           if ( argument.type.isEmpty() ) {
01296             std::cerr << "Signal argument without type." << std::endl;
01297             return 1;
01298           }
01299           argument.variableName = e2.text();
01300           theSignal.arguments.append(argument);
01301         }
01302         else if( e2.tagName() == "label") {
01303           theSignal.label = e2.text();
01304         }
01305       }
01306       signalList.append(theSignal);
01307     }
01308   }
01309 
01310   if ( inherits.isEmpty() ) inherits = "KConfigSkeleton";
01311 
01312   if ( className.isEmpty() ) {
01313     std::cerr << "Class name missing" << std::endl;
01314     return 1;
01315   }
01316 
01317   if ( singleton && !parameters.isEmpty() ) {
01318     std::cerr << "Singleton class can not have parameters" << std::endl;
01319     return 1;
01320   }
01321 
01322   if ( !cfgFileName.isEmpty() && cfgFileNameArg)
01323   {
01324     std::cerr << "Having both a fixed filename and a filename as argument is not possible." << std::endl;
01325     return 1;
01326   }
01327 
01328   if ( entries.isEmpty() ) {
01329     std::cerr << "No entries." << std::endl;
01330   }
01331 
01332 #if 0
01333   CfgEntry *cfg;
01334   for( cfg = entries.first(); cfg; cfg = entries.next() ) {
01335     cfg->dump();
01336   }
01337 #endif
01338 
01339   hasSignals = !signalList.empty();
01340   QString headerFileName = baseName + ".h";
01341   QString implementationFileName = baseName + ".cpp";
01342   QString mocFileName = baseName + ".moc";
01343   QString cppPreamble; // code to be inserted at the beginnin of the cpp file, e.g. initialization of static values
01344 
01345   QFile header( baseDir + headerFileName );
01346   if ( !header.open( QIODevice::WriteOnly ) ) {
01347     std::cerr << "Can not open '" << baseDir  << headerFileName << "for writing." << std::endl;
01348     return 1;
01349   }
01350 
01351   QTextStream h( &header );
01352 
01353   h << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
01354   h << "// All changes you do to this file will be lost." << endl;
01355 
01356   h << "#ifndef " << ( !nameSpace.isEmpty() ? nameSpace.toUpper() + '_' : "" )
01357     << className.toUpper() << "_H" << endl;
01358   h << "#define " << ( !nameSpace.isEmpty() ? nameSpace.toUpper() + '_' : "" )
01359     << className.toUpper() << "_H" << endl << endl;
01360 
01361   // Includes
01362   QStringList::ConstIterator it;
01363   for( it = headerIncludes.constBegin(); it != headerIncludes.constEnd(); ++it ) {
01364     if ( (*it).startsWith('"') )
01365       h << "#include " << *it << endl;
01366     else
01367       h << "#include <" << *it << ">" << endl;
01368   }
01369 
01370   if ( headerIncludes.count() > 0 ) h << endl;
01371 
01372   if ( !singleton && parameters.isEmpty() )
01373     h << "#include <kglobal.h>" << endl;
01374 
01375   h << "#include <kconfigskeleton.h>" << endl;
01376   h << "#include <kdebug.h>" << endl << endl;
01377 
01378   // Includes
01379   for( it = includes.constBegin(); it != includes.constEnd(); ++it ) {
01380     if ( (*it).startsWith('"') )
01381       h << "#include " << *it << endl;
01382     else
01383       h << "#include <" << *it << ">" << endl;
01384   }
01385 
01386   if ( !nameSpace.isEmpty() )
01387     h << "namespace " << nameSpace << " {" << endl << endl;
01388 
01389   // Private class declaration
01390   if ( dpointer )
01391     h << "class " << className << "Private;" << endl << endl;
01392 
01393   // Class declaration header
01394   h << "class " << visibility << className << " : public " << inherits << endl;
01395 
01396   h << "{" << endl;
01397   // Add Q_OBJECT macro if the config need signals.
01398   if( hasSignals )
01399    h << "  Q_OBJECT" << endl;
01400   h << "  public:" << endl;
01401 
01402   // enums
01403   QList<CfgEntry*>::ConstIterator itEntry;
01404   for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01405     const CfgEntry::Choices &choices = (*itEntry)->choices();
01406     QList<CfgEntry::Choice> chlist = choices.choices;
01407     if ( !chlist.isEmpty() ) {
01408       QStringList values;
01409       QList<CfgEntry::Choice>::ConstIterator itChoice;
01410       for( itChoice = chlist.constBegin(); itChoice != chlist.constEnd(); ++itChoice ) {
01411         values.append( choices.prefix + (*itChoice).name );
01412       }
01413       if ( choices.name().isEmpty() ) {
01414         if ( globalEnums ) {
01415           h << "    enum { " << values.join( ", " ) << " };" << endl;
01416         } else {
01417           // Create an automatically named enum
01418           h << "    class " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << endl;
01419           h << "    {" << endl;
01420           h << "      public:" << endl;
01421           h << "      enum type { " << values.join( ", " ) << ", COUNT };" << endl;
01422           h << "    };" << endl;
01423         }
01424       } else if ( !choices.external() ) {
01425         // Create a named enum
01426         h << "    enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << " { " << values.join( ", " ) << " };" << endl;
01427       }
01428     }
01429     QStringList values = (*itEntry)->paramValues();
01430     if ( !values.isEmpty() ) {
01431       if ( globalEnums ) {
01432         // ### FIXME!!
01433         // make the following string table an index-based string search!
01434         // ###
01435         h << "    enum { " << values.join( ", " ) << " };" << endl;
01436         h << "    static const char* const " << enumName( (*itEntry)->param() ) << "ToString[];" << endl;
01437         cppPreamble += "const char* const " + className + "::" + enumName( (*itEntry)->param() ) +
01438            "ToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
01439       } else {
01440         h << "    class " << enumName( (*itEntry)->param() ) << endl;
01441         h << "    {" << endl;
01442         h << "      public:" << endl;
01443         h << "      enum type { " << values.join( ", " ) << ", COUNT };" << endl;
01444         h << "      static const char* const enumToString[];" << endl;
01445         h << "    };" << endl;
01446         cppPreamble += "const char* const " + className + "::" + enumName( (*itEntry)->param() ) +
01447            "::enumToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
01448       }
01449     }
01450   }
01451   if ( hasSignals ) {
01452    h << "\n    enum {" << endl;
01453    unsigned val = 1;
01454    QList<Signal>::ConstIterator it, itEnd = signalList.constEnd();
01455    for ( it = signalList.constBegin(); it != itEnd; val <<= 1) {
01456      if ( !val ) {
01457        std::cerr << "Too many signals to create unique bit masks" << std::endl;
01458        exit(1);
01459      }
01460      Signal signal = *it;
01461      h << "      " << signalEnumName(signal.name) << " = 0x" << hex << val;
01462      if ( ++it != itEnd )
01463       h << ",";
01464      h << endl;
01465    }
01466    h << " };" << dec << endl;
01467   }
01468   h << endl;
01469   // Constructor or singleton accessor
01470   if ( !singleton ) {
01471     h << "    " << className << "(";
01472     if (cfgFileNameArg)
01473     {
01474         if(forceStringFilename)
01475             h << " const QString &cfgfilename"
01476                 << (parameters.isEmpty() ? " = QString()" : ", ");
01477         else
01478             h << " KSharedConfig::Ptr config"
01479                 << (parameters.isEmpty() ? " = KGlobal::config()" : ", ");
01480     }
01481     for (QList<Param>::ConstIterator it = parameters.constBegin();
01482          it != parameters.constEnd(); ++it)
01483     {
01484        if (it != parameters.constBegin())
01485          h << ",";
01486        h << " " << param((*it).type) << " " << (*it).name;
01487     }
01488     h << " );" << endl;
01489   } else {
01490     h << "    static " << className << " *self();" << endl;
01491     if (cfgFileNameArg)
01492     {
01493       h << "    static void instance(const QString& cfgfilename);" << endl;
01494     }
01495   }
01496 
01497   // Destructor
01498   h << "    ~" << className << "();" << endl << endl;
01499 
01500   // global variables
01501   if (staticAccessors)
01502     This = "self()->";
01503   else
01504     Const = " const";
01505 
01506   for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01507     QString n = (*itEntry)->name();
01508     QString t = (*itEntry)->type();
01509 
01510     // Manipulator
01511     if (allMutators || mutators.contains(n))
01512     {
01513       h << "    /**" << endl;
01514       h << "      Set " << (*itEntry)->label() << endl;
01515       h << "    */" << endl;
01516       if (staticAccessors)
01517         h << "    static" << endl;
01518       h << "    void " << setFunction(n) << "( ";
01519       if (!(*itEntry)->param().isEmpty())
01520         h << cppType((*itEntry)->paramType()) << " i, ";
01521       if (useEnumTypes && t == "Enum")
01522         h << enumType(*itEntry);
01523       else
01524         h << param( t );
01525       h << " v )";
01526       // function body inline only if not using dpointer
01527       // for BC mode
01528       if ( !dpointer )
01529       {
01530         h << endl << "    {" << endl;
01531         h << indent(memberMutatorBody(*itEntry), 6 );
01532         h << "    }" << endl;
01533       }
01534       else
01535       {
01536         h << ";" << endl;
01537       }
01538     }
01539     h << endl;
01540     // Accessor
01541     h << "    /**" << endl;
01542     h << "      Get " << (*itEntry)->label() << endl;
01543     h << "    */" << endl;
01544     if (staticAccessors)
01545       h << "    static" << endl;
01546     h << "    ";
01547     if (useEnumTypes && t == "Enum")
01548       h << enumType(*itEntry);
01549     else
01550       h << cppType(t);
01551     h << " " << getFunction(n) << "(";
01552     if (!(*itEntry)->param().isEmpty())
01553       h << " " << cppType((*itEntry)->paramType()) <<" i ";
01554     h << ")" << Const;
01555     // function body inline only if not using dpointer
01556     // for BC mode
01557     if ( !dpointer )
01558     {
01559        h << endl << "    {" << endl;
01560       h << indent(memberAccessorBody((*itEntry)), 6 );
01561        h << "    }" << endl;
01562     }
01563     else
01564     {
01565       h << ";" << endl;
01566     }
01567 
01568     // Item accessor
01569     if ( itemAccessors ) {
01570       h << endl;
01571       h << "    /**" << endl;
01572       h << "      Get Item object corresponding to " << n << "()"
01573         << endl;
01574       h << "    */" << endl;
01575       h << "    Item" << itemType( (*itEntry)->type() ) << " *"
01576         << getFunction( n ) << "Item(";
01577       if (!(*itEntry)->param().isEmpty()) {
01578         h << " " << cppType((*itEntry)->paramType()) << " i ";
01579       }
01580       h << ")";
01581       if (! dpointer )
01582       {
01583         h << endl << "    {" << endl;
01584         h << indent( itemAccessorBody((*itEntry)), 6);
01585         h << "    }" << endl;
01586       }
01587       else
01588       {
01589         h << ";" << endl;
01590       }
01591     }
01592 
01593     h << endl;
01594   }
01595 
01596 
01597   // Signal definition.
01598   if( hasSignals ) {
01599     h << endl;
01600     h << "  Q_SIGNALS:";
01601     foreach(const Signal &signal, signalList) {
01602       h << endl;
01603       if ( !signal.label.isEmpty() ) {
01604         h << "    /**" << endl;
01605         h << "      " << signal.label << endl;
01606         h << "    */" << endl;
01607       }
01608       h << "    void " << signal.name << "(";
01609       QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
01610       for ( it = signal.arguments.constBegin(); it != itEnd; ) {
01611         SignalArguments argument = *it;
01612         QString type = param(argument.type);
01613         if ( useEnumTypes && argument.type == "Enum" ) {
01614           for ( int i = 0, end = entries.count(); i < end; ++i ) {
01615             if ( entries[i]->name() == argument.variableName ) {
01616               type = enumType(entries[i]);
01617               break;
01618             }
01619           }
01620         }
01621         h << type << " " << argument.variableName;
01622         if ( ++it != itEnd ) {
01623          h << ", ";
01624         }
01625       }
01626       h << ");" << endl;
01627     }
01628     h << endl;
01629   }
01630 
01631   h << "  protected:" << endl;
01632 
01633   // Private constructor for singleton
01634   if ( singleton ) {
01635     h << "    " << className << "(";
01636     if ( cfgFileNameArg )
01637       h << "const QString& arg";
01638     h << ");" << endl;
01639     h << "    friend class " << className << "Helper;" << endl << endl;
01640   }
01641 
01642   if ( hasSignals ) {
01643     h << "    virtual void usrWriteConfig();" << endl;
01644   }
01645 
01646   // Member variables
01647   if ( !memberVariables.isEmpty() && memberVariables != "private" && memberVariables != "dpointer") {
01648     h << "  " << memberVariables << ":" << endl;
01649   }
01650 
01651   // Class Parameters
01652   for (QList<Param>::ConstIterator it = parameters.constBegin();
01653        it != parameters.constEnd(); ++it)
01654   {
01655      h << "    " << cppType((*it).type) << " mParam" << (*it).name << ";" << endl;
01656   }
01657 
01658   if ( memberVariables != "dpointer" )
01659   {
01660     QString group;
01661     for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01662       if ( (*itEntry)->group() != group ) {
01663         group = (*itEntry)->group();
01664         h << endl;
01665         h << "    // " << group << endl;
01666       }
01667       h << "    " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name() );
01668       if ( !(*itEntry)->param().isEmpty() )
01669       {
01670         h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01671       }
01672       h << ";" << endl;
01673     }
01674 
01675     h << endl << "  private:" << endl;
01676     if ( itemAccessors ) {
01677        for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01678         h << "    Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry );
01679         if ( !(*itEntry)->param().isEmpty() ) h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01680         h << ";" << endl;
01681       }
01682     }
01683     if ( hasSignals )
01684      h << "    uint " << varName("settingsChanged") << ";" << endl;
01685 
01686   }
01687   else
01688   {
01689     // use a private class for both member variables and items
01690     h << "  private:" << endl;
01691     h << "    " + className + "Private *d;" << endl;
01692   }
01693 
01694   if (customAddons)
01695   {
01696      h << "    // Include custom additions" << endl;
01697      h << "    #include \"" << filenameOnly(baseName) << "_addons.h\"" <<endl;
01698   }
01699 
01700   h << "};" << endl << endl;
01701 
01702   if ( !nameSpace.isEmpty() ) h << "}" << endl << endl;
01703 
01704   h << "#endif" << endl << endl;
01705 
01706 
01707   header.close();
01708 
01709   QFile implementation( baseDir + implementationFileName );
01710   if ( !implementation.open( QIODevice::WriteOnly ) ) {
01711     std::cerr << "Can not open '" << qPrintable(implementationFileName) << "for writing."
01712               << std::endl;
01713     return 1;
01714   }
01715 
01716   QTextStream cpp( &implementation );
01717 
01718 
01719   cpp << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
01720   cpp << "// All changes you do to this file will be lost." << endl << endl;
01721 
01722   cpp << "#include \"" << headerFileName << "\"" << endl << endl;
01723 
01724   for( it = sourceIncludes.constBegin(); it != sourceIncludes.constEnd(); ++it ) {
01725     if ( (*it).startsWith('"') )
01726       cpp << "#include " << *it << endl;
01727     else
01728       cpp << "#include <" << *it << ">" << endl;
01729   }
01730 
01731   if ( sourceIncludes.count() > 0 ) cpp << endl;
01732 
01733   if ( setUserTexts ) cpp << "#include <klocale.h>" << endl << endl;
01734 
01735   // Header required by singleton implementation
01736   if ( singleton )
01737     cpp << "#include <kglobal.h>" << endl << "#include <QtCore/QFile>" << endl << endl;
01738   if ( singleton && cfgFileNameArg )
01739     cpp << "#include <kdebug.h>" << endl << endl;
01740 
01741   if ( !nameSpace.isEmpty() )
01742     cpp << "using namespace " << nameSpace << ";" << endl << endl;
01743 
01744   QString group;
01745 
01746   // private class implementation
01747   if ( dpointer )
01748   {
01749     if ( !nameSpace.isEmpty() )
01750       cpp << "namespace " << nameSpace << " {" << endl;
01751     cpp << "class " << className << "Private" << endl;
01752     cpp << "{" << endl;
01753     cpp << "  public:" << endl;
01754     for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01755       if ( (*itEntry)->group() != group ) {
01756         group = (*itEntry)->group();
01757         cpp << endl;
01758         cpp << "    // " << group << endl;
01759       }
01760       cpp << "    " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name() );
01761       if ( !(*itEntry)->param().isEmpty() )
01762       {
01763         cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01764       }
01765       cpp << ";" << endl;
01766     }
01767     cpp << endl << "    // items" << endl;
01768     for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01769       cpp << "    KConfigSkeleton::Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry );
01770       if ( !(*itEntry)->param().isEmpty() ) cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01771         cpp << ";" << endl;
01772     }
01773     if ( hasSignals ) {
01774       cpp << "    uint " << varName("settingsChanged") << ";" << endl;
01775     }
01776 
01777     cpp << "};" << endl << endl;
01778     if ( !nameSpace.isEmpty() )
01779       cpp << "}" << endl << endl;
01780   }
01781 
01782   // Singleton implementation
01783   if ( singleton ) {
01784     if( !nameSpace.isEmpty() )
01785       cpp << "namespace " << nameSpace << " {" << endl;
01786     cpp << "class " << className << "Helper" << endl;
01787     cpp << '{' << endl;
01788     cpp << "  public:" << endl;
01789     cpp << "    " << className << "Helper() : q(0) {}" << endl;
01790     cpp << "    ~" << className << "Helper() { delete q; }" << endl;
01791     cpp << "    " << className << " *q;" << endl;
01792     cpp << "};" << endl;
01793     if( !nameSpace.isEmpty() )
01794       cpp << "}" << endl;
01795     cpp << "K_GLOBAL_STATIC(" << className << "Helper, s_global" << className << ")" << endl;
01796 
01797     cpp << className << " *" << className << "::self()" << endl;
01798     cpp << "{" << endl;
01799     if ( cfgFileNameArg ) {
01800       cpp << "  if (!s_global" << className << "->q)" << endl;
01801       cpp << "     kFatal() << \"you need to call " << className << "::instance before using\";" << endl;
01802     } else {
01803       cpp << "  if (!s_global" << className << "->q) {" << endl;
01804       cpp << "    new " << className << ';' << endl;
01805       cpp << "    s_global" << className << "->q->readConfig();" << endl;
01806       cpp << "  }" << endl << endl;
01807     }
01808     cpp << "  return s_global" << className << "->q;" << endl;
01809     cpp << "}" << endl << endl;
01810 
01811     if ( cfgFileNameArg ) {
01812       cpp << "void " << className << "::instance(const QString& cfgfilename)" << endl;
01813       cpp << "{" << endl;
01814       cpp << "  if (s_global" << className << "->q) {" << endl;
01815       cpp << "     kDebug() << \"" << className << "::instance called after the first use - ignoring\";" << endl;
01816       cpp << "     return;" << endl;
01817       cpp << "  }" << endl;
01818       cpp << "  new " << className << "(cfgfilename);" << endl;
01819       cpp << "  s_global" << className << "->q->readConfig();" << endl;
01820       cpp << "}" << endl << endl;
01821     }
01822   }
01823 
01824   if ( !cppPreamble.isEmpty() )
01825     cpp << cppPreamble << endl;
01826 
01827   // Constructor
01828   cpp << className << "::" << className << "( ";
01829   if ( cfgFileNameArg ) {
01830     if ( !singleton && ! forceStringFilename)
01831       cpp << " KSharedConfig::Ptr config";
01832     else
01833       cpp << " const QString& config";
01834     cpp << (parameters.isEmpty() ? " " : ", ");
01835   }
01836 
01837   for (QList<Param>::ConstIterator it = parameters.constBegin();
01838        it != parameters.constEnd(); ++it)
01839   {
01840      if (it != parameters.constBegin())
01841        cpp << ",";
01842      cpp << " " << param((*it).type) << " " << (*it).name;
01843   }
01844   cpp << " )" << endl;
01845 
01846   cpp << "  : " << inherits << "(";
01847   if ( !cfgFileName.isEmpty() ) cpp << " QLatin1String( \"" << cfgFileName << "\" ";
01848   if ( cfgFileNameArg ) cpp << " config ";
01849   if ( !cfgFileName.isEmpty() ) cpp << ") ";
01850   cpp << ")" << endl;
01851 
01852   // Store parameters
01853   for (QList<Param>::ConstIterator it = parameters.constBegin();
01854        it != parameters.constEnd(); ++it)
01855   {
01856      cpp << "  , mParam" << (*it).name << "(" << (*it).name << ")" << endl;
01857   }
01858 
01859   cpp << "{" << endl;
01860 
01861   if (dpointer)
01862     cpp << "  d = new " + className + "Private;" << endl;
01863   // Needed in case the singleton class is used as baseclass for
01864   // another singleton.
01865   if (singleton) {
01866     cpp << "  Q_ASSERT(!s_global" << className << "->q);" << endl;
01867     cpp << "  s_global" << className << "->q = this;" << endl;
01868   }
01869 
01870   group.clear();
01871 
01872   for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01873     if ( (*itEntry)->group() != group ) {
01874       if ( !group.isEmpty() ) cpp << endl;
01875       group = (*itEntry)->group();
01876       cpp << "  setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl;
01877     }
01878 
01879     QString key = paramString( (*itEntry)->key(), parameters );
01880     if ( !(*itEntry)->code().isEmpty() ) {
01881       cpp << (*itEntry)->code() << endl;
01882     }
01883     if ( (*itEntry)->type() == "Enum" ) {
01884       cpp << "  QList<KConfigSkeleton::ItemEnum::Choice2> values"
01885           << (*itEntry)->name() << ";" << endl;
01886       QList<CfgEntry::Choice> choices = (*itEntry)->choices().choices;
01887       QList<CfgEntry::Choice>::ConstIterator it;
01888       for( it = choices.constBegin(); it != choices.constEnd(); ++it ) {
01889         cpp << "  {" << endl;
01890         cpp << "    KConfigSkeleton::ItemEnum::Choice2 choice;" << endl;
01891         cpp << "    choice.name = QLatin1String(\"" << (*it).name << "\");" << endl;
01892         if ( setUserTexts ) {
01893           if ( !(*it).label.isEmpty() ) {
01894             cpp << "    choice.label = ";
01895             if ( !(*it).context.isEmpty() )
01896               cpp << "i18nc(" + quoteString((*it).context) + ", ";
01897             else
01898               cpp << "i18n(";
01899             cpp << quoteString((*it).label) << ");" << endl;
01900           }
01901           if ( !(*it).toolTip.isEmpty() ) {
01902             cpp << "    choice.toolTip = ";
01903             if ( !(*it).context.isEmpty() )
01904               cpp << "i18nc(" + quoteString((*it).context) + ", ";
01905             else
01906               cpp << "i18n(";
01907             cpp << quoteString((*it).toolTip) << ");" << endl;
01908           }
01909           if ( !(*it).whatsThis.isEmpty() ) {
01910             cpp << "    choice.whatsThis = ";
01911             if ( !(*it).context.isEmpty() )
01912               cpp << "i18nc(" + quoteString((*it).context) + ", ";
01913             else
01914               cpp << "i18n(";
01915             cpp << quoteString((*it).whatsThis) << ");" << endl;
01916           }
01917         }
01918         cpp << "    values" << (*itEntry)->name() << ".append( choice );" << endl;
01919         cpp << "  }" << endl;
01920       }
01921     }
01922 
01923     if (!dpointer)
01924       cpp << itemDeclaration( *itEntry );
01925 
01926     if ( (*itEntry)->param().isEmpty() )
01927     {
01928       // Normal case
01929       cpp << "  " << itemPath( *itEntry ) << " = "
01930           << newItem( (*itEntry)->type(), (*itEntry)->name(), key, (*itEntry)->defaultValue() ) << endl;
01931 
01932       if ( !(*itEntry)->minValue().isEmpty() )
01933         cpp << "  " << itemPath( *itEntry ) << "->setMinValue(" << (*itEntry)->minValue() << ");" << endl;
01934       if ( !(*itEntry)->maxValue().isEmpty() )
01935         cpp << "  " << itemPath( *itEntry ) << "->setMaxValue(" << (*itEntry)->maxValue() << ");" << endl;
01936 
01937       if ( setUserTexts )
01938         cpp << userTextsFunctions( (*itEntry) );
01939 
01940       cpp << "  addItem( " << itemPath( *itEntry );
01941       QString quotedName = (*itEntry)->name();
01942       addQuotes( quotedName );
01943       if ( quotedName != key ) cpp << ", QLatin1String( \"" << (*itEntry)->name() << "\" )";
01944       cpp << " );" << endl;
01945     }
01946     else
01947     {
01948       // Indexed
01949       for(int i = 0; i <= (*itEntry)->paramMax(); i++)
01950       {
01951         QString defaultStr;
01952         QString itemVarStr(itemPath( *itEntry )+QString("[%1]").arg(i));
01953 
01954         if ( !(*itEntry)->paramDefaultValue(i).isEmpty() )
01955           defaultStr = (*itEntry)->paramDefaultValue(i);
01956         else if ( !(*itEntry)->defaultValue().isEmpty() )
01957           defaultStr = paramString( (*itEntry)->defaultValue(), (*itEntry), i );
01958         else
01959           defaultStr = defaultValue( (*itEntry)->type() );
01960 
01961         cpp << "  " << itemVarStr << " = "
01962             << newItem( (*itEntry)->type(), (*itEntry)->name(), paramString(key, *itEntry, i), defaultStr, QString("[%1]").arg(i) )
01963             << endl;
01964 
01965         if ( setUserTexts )
01966           cpp << userTextsFunctions( *itEntry, itemVarStr, (*itEntry)->paramName() );
01967 
01968         // Make mutators for enum parameters work by adding them with $(..) replaced by the
01969         // param name. The check for isImmutable in the set* functions doesn't have the param
01970         // name available, just the corresponding enum value (int), so we need to store the
01971         // param names in a separate static list!.
01972         cpp << "  addItem( " << itemVarStr << ", QLatin1String( \"";
01973         if ( (*itEntry)->paramType()=="Enum" )
01974           cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg((*itEntry)->paramValues()[i] );
01975         else
01976           cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg(i);
01977         cpp << "\" ) );" << endl;
01978       }
01979     }
01980   }
01981 
01982   cpp << "}" << endl << endl;
01983 
01984   if (dpointer)
01985   {
01986     // setters and getters go in Cpp if in dpointer mode
01987     for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
01988       QString n = (*itEntry)->name();
01989       QString t = (*itEntry)->type();
01990 
01991       // Manipulator
01992       if (allMutators || mutators.contains(n))
01993       {
01994         cpp << "void " << setFunction(n, className) << "( ";
01995         if ( !(*itEntry)->param().isEmpty() )
01996           cpp << cppType( (*itEntry)->paramType() ) << " i, ";
01997         if (useEnumTypes && t == "Enum")
01998           cpp << enumType(*itEntry);
01999         else
02000           cpp << param( t );
02001         cpp << " v )";
02002         // function body inline only if not using dpointer
02003         // for BC mode
02004         cpp << "{" << endl;
02005         cpp << indent(memberMutatorBody( *itEntry ), 6);
02006         cpp << "}" << endl << endl;
02007       }
02008 
02009       // Accessor
02010       if (useEnumTypes && t == "Enum")
02011         cpp << enumType(*itEntry);
02012       else
02013         cpp << cppType(t);
02014       cpp << " " << getFunction(n, className) << "(";
02015       if ( !(*itEntry)->param().isEmpty() )
02016         cpp << " " << cppType( (*itEntry)->paramType() ) <<" i ";
02017       cpp << ")" << Const << endl;
02018       // function body inline only if not using dpointer
02019       // for BC mode
02020       cpp << "{" << endl;
02021       cpp << indent(memberAccessorBody( *itEntry ), 2);
02022       cpp << "}" << endl << endl;
02023 
02024       // Item accessor
02025       if ( itemAccessors )
02026       {
02027         cpp << endl;
02028         cpp << "KConfigSkeleton::Item" << itemType( (*itEntry)->type() ) << " *"
02029           << getFunction( n, className ) << "Item(";
02030         if ( !(*itEntry)->param().isEmpty() ) {
02031           cpp << " " << cppType( (*itEntry)->paramType() ) << " i ";
02032         }
02033         cpp << ")" << endl;
02034         cpp << "{" << endl;
02035         cpp << indent(itemAccessorBody( *itEntry ), 2);
02036         cpp << "}" << endl;
02037       }
02038 
02039       cpp << endl;
02040     }
02041   }
02042 
02043   // Destructor
02044   cpp << className << "::~" << className << "()" << endl;
02045   cpp << "{" << endl;
02046   if ( singleton ) {
02047     if ( dpointer )
02048       cpp << "  delete d;" << endl;
02049     cpp << "  if (!s_global" << className << ".isDestroyed()) {" << endl;
02050     cpp << "    s_global" << className << "->q = 0;" << endl;
02051     cpp << "  }" << endl;
02052   }
02053   cpp << "}" << endl << endl;
02054 
02055   if ( hasSignals ) {
02056     cpp << "void " << className << "::" << "usrWriteConfig()" << endl;
02057     cpp << "{" << endl;
02058     cpp << "  " << inherits << "::usrWriteConfig();" << endl << endl;
02059     foreach(const Signal &signal, signalList) {
02060       cpp << "  if ( " << varPath("settingsChanged") << " & " << signalEnumName(signal.name) << " ) " << endl;
02061       cpp << "    emit " << signal.name << "(";
02062       QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
02063       for ( it = signal.arguments.constBegin(); it != itEnd; ) {
02064         SignalArguments argument = *it;
02065         bool cast = false;
02066         if ( useEnumTypes && argument.type == "Enum" ) {
02067           for ( int i = 0, end = entries.count(); i < end; ++i ) {
02068             if ( entries[i]->name() == argument.variableName ) {
02069               cpp << "static_cast<" << enumType(entries[i]) << ">(";
02070               cast = true;
02071               break;
02072             }
02073           }
02074         }
02075         cpp << varPath(argument.variableName);
02076         if ( cast )
02077           cpp << ")";
02078         if ( ++it != itEnd )
02079           cpp << ", ";
02080       }
02081       cpp << ");" << endl << endl;
02082     }
02083     cpp << "  " << varPath("settingsChanged") << " = 0;" << endl;
02084     cpp << "}" << endl;
02085   }
02086 
02087   // Add includemoc if they are signals defined.
02088   if( hasSignals ) {
02089     cpp << endl;
02090     cpp << "#include \"" << mocFileName << "\"" << endl;
02091     cpp << endl;
02092   }
02093 
02094   // clear entries list
02095   qDeleteAll( entries );
02096 
02097   implementation.close();
02098 }

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
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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