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

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
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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