kdecore Library API Documentation

kconfig_compiler.cpp

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 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Library General Public
00011     License as published by the Free Software Foundation; either
00012     version 2 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Library General Public License for more details.
00018 
00019     You should have received a copy of the GNU Library General Public License
00020     along with this library; see the file COPYING.LIB.  If not, write to
00021     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00022     Boston, MA 02111-1307, USA.
00023 */
00024 
00025 #include <qfile.h>
00026 #include <qtextstream.h>
00027 #include <qdom.h>
00028 #include <qregexp.h>
00029 
00030 #include <kaboutdata.h>
00031 #include <kapplication.h>
00032 #include <kdebug.h>
00033 #include <klocale.h>
00034 #include <kcmdlineargs.h>
00035 #include <kglobal.h>
00036 #include <kconfig.h>
00037 #include <ksimpleconfig.h>
00038 #include <kstandarddirs.h>
00039 
00040 #include <iostream>
00041 
00042 static const KCmdLineOptions options[] =
00043 {
00044   { "d", 0, 0 },
00045   { "directory <dir>", I18N_NOOP("Directory to generate files in"), "." },
00046   { "+file.kcfg", I18N_NOOP("Input kcfg XML file"), 0 },
00047   { "+file.kcfgc", I18N_NOOP("Code generation options file"), 0 },
00048   KCmdLineLastOption
00049 };
00050 
00051 
00052 bool globalEnums;
00053 bool itemAccessors;
00054 
00055 class CfgEntry
00056 {
00057   public:
00058     struct Choice
00059     {
00060       QString name;
00061       QString label;
00062       QString whatsThis;
00063     };
00064 
00065     CfgEntry( const QString &group, const QString &type, const QString &key,
00066               const QString &name, const QString &label,
00067               const QString &whatsThis, const QString &code,
00068               const QString &defaultValue, const QValueList<Choice> &choices,
00069               bool hidden )
00070       : mGroup( group ), mType( type ), mKey( key ), mName( name ),
00071         mLabel( label ), mWhatsThis( whatsThis ), mCode( code ),
00072         mDefaultValue( defaultValue ),
00073         mChoices( choices ), mHidden( hidden )
00074     {
00075     }
00076 
00077     void setGroup( const QString &group ) { mGroup = group; }
00078     QString group() const { return mGroup; }
00079 
00080     void setType( const QString &type ) { mType = type; }
00081     QString type() const { return mType; }
00082 
00083     void setKey( const QString &key ) { mKey = key; }
00084     QString key() const { return mKey; }
00085 
00086     void setName( const QString &name ) { mName = name; }
00087     QString name() const { return mName; }
00088 
00089     void setLabel( const QString &label ) { mLabel = label; }
00090     QString label() const { return mLabel; }
00091 
00092     void setWhatsThis( const QString &whatsThis ) { mWhatsThis = whatsThis; }
00093     QString whatsThis() const { return mWhatsThis; }
00094 
00095     void setDefaultValue( const QString &d ) { mDefaultValue = d; }
00096     QString defaultValue() const { return mDefaultValue; }
00097 
00098     void setCode( const QString &d ) { mCode = d; }
00099     QString code() const { return mCode; }
00100 
00101     void setMinValue( const QString &d ) { mMin = d; }
00102     QString minValue() const { return mMin; }
00103 
00104     void setMaxValue( const QString &d ) { mMax = d; }
00105     QString maxValue() const { return mMax; }
00106 
00107     void setParam( const QString &d ) { mParam = d; }
00108     QString param() const { return mParam; }
00109 
00110     void setParamName( const QString &d ) { mParamName = d; }
00111     QString paramName() const { return mParamName; }
00112 
00113     void setParamType( const QString &d ) { mParamType = d; }
00114     QString paramType() const { return mParamType; }
00115 
00116     void setChoices( const QValueList<Choice> &d ) { mChoices = d; }
00117     QValueList<Choice> choices() const { return mChoices; }
00118 
00119     void setParamValues( const QStringList &d ) { mParamValues = d; }
00120     QStringList paramValues() const { return mParamValues; }
00121 
00122     void setParamDefaultValues( const QStringList &d ) { mParamDefaultValues = d; }
00123     QString paramDefaultValue(int i) const { return mParamDefaultValues[i]; }
00124 
00125     void setParamMax( int d ) { mParamMax = d; }
00126     int paramMax() const { return mParamMax; }
00127 
00128     bool hidden() const { return mHidden; }
00129 
00130     void dump() const
00131     {
00132       kdDebug() << "<entry>" << endl;
00133       kdDebug() << "  group: " << mGroup << endl;
00134       kdDebug() << "  type: " << mType << endl;
00135       kdDebug() << "  key: " << mKey << endl;
00136       kdDebug() << "  name: " << mName << endl;
00137       kdDebug() << "  label: " << mLabel << endl;
00138 // whatsthis
00139       kdDebug() << "  code: " << mCode << endl;
00140 //      kdDebug() << "  values: " << mValues.join(":") << endl;
00141       
00142       if (!param().isEmpty())
00143       {
00144         kdDebug() << "  param name: "<< mParamName << endl;
00145         kdDebug() << "  param type: "<< mParamType << endl;
00146         kdDebug() << "  paramvalues: " << mParamValues.join(":") << endl;
00147       }
00148       kdDebug() << "  default: " << mDefaultValue << endl;
00149       kdDebug() << "  hidden: " << mHidden << endl;
00150       kdDebug() << "  min: " << mMin << endl;
00151       kdDebug() << "  max: " << mMax << endl;
00152       kdDebug() << "</entry>" << endl;
00153     }
00154 
00155   private:
00156     QString mGroup;
00157     QString mType;
00158     QString mKey;
00159     QString mName;
00160     QString mLabel;
00161     QString mWhatsThis;
00162     QString mCode;
00163     QString mDefaultValue;
00164     QString mParam;
00165     QString mParamName;
00166     QString mParamType;
00167     QValueList<Choice> mChoices;
00168     QStringList mParamValues;
00169     QStringList mParamDefaultValues;
00170     int mParamMax;
00171     bool mHidden;
00172     QString mMin;
00173     QString mMax;
00174 };
00175 
00176 
00177 static QString varName(const QString &n)
00178 {
00179   QString result = "m"+n;
00180   result[1] = result[1].upper();
00181   return result;
00182 }
00183 
00184 static QString enumName(const QString &n)
00185 {
00186   QString result = "Enum"+n;
00187   result[4] = result[4].upper();
00188   return result;
00189 }
00190 
00191 static QString setFunction(const QString &n)
00192 {
00193   QString result = "set"+n;
00194   result[3] = result[3].upper();
00195   return result;
00196 }
00197 
00198 
00199 static QString getFunction(const QString &n)
00200 {
00201   QString result = n;
00202   result[0] = result[0].lower();
00203   return result;
00204 }
00205 
00206 
00207 static void addQuotes( QString &s )
00208 {
00209   if ( s.left( 1 ) != "\"" ) s.prepend( "\"" );
00210   if ( s.right( 1 ) != "\"" ) s.append( "\"" );
00211 }
00212 
00213 static QString quoteString( const QString &s )
00214 {
00215   QString r = s;
00216   r.replace( "\\", "\\\\" );
00217   r.replace( "\"", "\\\"" );
00218   r.replace( "\r", "" );
00219   r.replace( "\n", "\\n\"\n\"" );
00220   return "\"" + r + "\"";
00221 }
00222 
00223 static QString dumpNode(const QDomNode &node)
00224 {
00225   QString msg;
00226   QTextStream s(&msg, IO_WriteOnly );
00227   node.save(s, 0);
00228 
00229   msg = msg.simplifyWhiteSpace();
00230   if (msg.length() > 40)
00231     return msg.left(37)+"...";
00232   return msg;
00233 }
00234 
00235 static QString filenameOnly(QString path)
00236 {
00237    int i = path.findRev('/');
00238    if (i >= 0)
00239       return path.mid(i+1);
00240    return path;
00241 }
00242 
00243 static void preProcessDefault( QString &defaultValue, const QString &name,
00244                                const QString &type,
00245                                const QValueList<CfgEntry::Choice> &choices,
00246                                QString &code )
00247 {
00248     if ( type == "String" && !defaultValue.isEmpty() ) {
00249       addQuotes( defaultValue );
00250 
00251     } else if ( type == "Path" && !defaultValue.isEmpty() ) {
00252       addQuotes( defaultValue );
00253 
00254     } else if ( type == "StringList" && !defaultValue.isEmpty() ) {
00255       QTextStream cpp( &code, IO_WriteOnly | IO_Append );
00256       if (!code.isEmpty())
00257          cpp << endl;
00258 
00259       cpp << "  QStringList default" << name << ";" << endl;
00260       QStringList defaults = QStringList::split( ",", defaultValue );
00261       QStringList::ConstIterator it;
00262       for( it = defaults.begin(); it != defaults.end(); ++it ) {
00263         cpp << "  default" << name << ".append( QString::fromUtf8( \"" << *it << "\" ) );"
00264             << endl;
00265       }
00266       defaultValue = "default" + name;
00267 
00268     } else if ( type == "Color" && !defaultValue.isEmpty() ) {
00269       QRegExp colorRe("\\d+,\\s*\\d+,\\s*\\d+");
00270       if (colorRe.exactMatch(defaultValue))
00271       {
00272         defaultValue = "QColor( " + defaultValue + " )";
00273       }
00274       else
00275       {
00276         defaultValue = "QColor( \"" + defaultValue + "\" )";
00277       }
00278 
00279     } else if ( type == "Enum" ) {
00280       if ( !globalEnums ) {
00281         QValueList<CfgEntry::Choice>::ConstIterator it;
00282         for( it = choices.begin(); it != choices.end(); ++it ) {
00283           if ( (*it).name == defaultValue ) {
00284             defaultValue.prepend( enumName(name) + "::");
00285             break;
00286           }
00287         }
00288       }
00289 
00290     } else if ( type == "IntList" ) {
00291       QTextStream cpp( &code, IO_WriteOnly | IO_Append );
00292       if (!code.isEmpty())
00293          cpp << endl;
00294 
00295       cpp << "  QValueList<int> default" << name << ";" << endl;
00296       QStringList defaults = QStringList::split( ",", defaultValue );
00297       QStringList::ConstIterator it;
00298       for( it = defaults.begin(); it != defaults.end(); ++it ) {
00299         cpp << "  default" << name << ".append( " << *it << " );"
00300             << endl;
00301       }
00302       defaultValue = "default" + name;
00303     }
00304 }
00305 
00306 
00307 CfgEntry *parseEntry( const QString &group, const QDomElement &element )
00308 {
00309   bool defaultCode = false;
00310   QString type = element.attribute( "type" );
00311   QString name = element.attribute( "name" );
00312   QString key = element.attribute( "key" );
00313   QString hidden = element.attribute( "hidden" );
00314   QString label;
00315   QString whatsThis;
00316   QString defaultValue;
00317   QString code;
00318   QString param;
00319   QString paramName;
00320   QString paramType;
00321   QValueList<CfgEntry::Choice> choices;
00322   QStringList paramValues;
00323   QStringList paramDefaultValues;
00324   QString minValue;
00325   QString maxValue;
00326   int paramMax = 0;
00327 
00328   QDomNode n;
00329   for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
00330     QDomElement e = n.toElement();
00331     QString tag = e.tagName();
00332     if ( tag == "label" ) label = e.text();
00333     else if ( tag == "whatsthis" ) whatsThis = e.text();
00334     else if ( tag == "min" ) minValue = e.text();
00335     else if ( tag == "max" ) maxValue = e.text();
00336     else if ( tag == "code" ) code = e.text();
00337     else if ( tag == "parameter" )
00338     {
00339       param = e.attribute( "name" );
00340       paramType = e.attribute( "type" );
00341       if ( param.isEmpty() ) {
00342         kdError() << "Parameter must have a name: " << dumpNode(e) << endl;
00343         return 0;
00344       }
00345       if ( paramType.isEmpty() ) {
00346         kdError() << "Parameter must have a type: " << dumpNode(e) << endl;
00347         return 0;
00348       }
00349       if ((paramType == "Int") || (paramType == "UInt"))
00350       {
00351          bool ok;
00352          paramMax = e.attribute("max").toInt(&ok);
00353          if (!ok)
00354          {
00355            kdError() << "Integer parameter must have a maximum (e.g. max=\"0\"): " << dumpNode(e) << endl;
00356            return 0;
00357          }
00358       }
00359       else if (paramType == "Enum")
00360       {
00361          QDomNode n2;
00362          for ( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
00363            QDomElement e2 = n2.toElement();
00364            if (e2.tagName() == "values")
00365            {
00366              QDomNode n3;
00367              for ( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) {
00368                QDomElement e3 = n3.toElement();
00369                if (e3.tagName() == "value")
00370                {
00371                   paramValues.append( e3.text() );
00372                }
00373              }
00374              break;
00375            }
00376          }
00377          if (paramValues.isEmpty())
00378          {
00379            kdError() << "No values specified for parameter '" << param << "'." << endl;
00380            return 0;
00381          }
00382          paramMax = paramValues.count()-1;
00383       }
00384       else
00385       {
00386         kdError() << "Parameter '" << param << "' has type " << paramType << " but must be of type int, uint or Enum." << endl;
00387         return 0;
00388       }
00389     }
00390     else if ( tag == "default" )
00391     {
00392       if (e.attribute("param").isEmpty())
00393       {
00394         defaultValue = e.text();
00395         if (e.attribute( "code" ) == "true")
00396           defaultCode = true;
00397       }
00398     }
00399     else if ( tag == "choices" ) {
00400       QDomNode n2;
00401       for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
00402         QDomElement e2 = n2.toElement();
00403         if ( e2.tagName() == "choice" ) {
00404           QDomNode n3;
00405           CfgEntry::Choice choice;
00406           choice.name = e2.attribute( "name" );
00407           if ( choice.name.isEmpty() ) {
00408             kdError() << "Tag <choice> requires attribute 'name'." << endl;
00409           }
00410           for( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) {
00411             QDomElement e3 = n3.toElement();
00412             if ( e3.tagName() == "label" ) choice.label = e3.text();
00413             if ( e3.tagName() == "whatsthis" ) choice.whatsThis = e3.text();
00414           }
00415           choices.append( choice );
00416         }
00417       }
00418     }
00419   }
00420 
00421   if ( name.isEmpty() && key.isEmpty() ) {
00422     kdError() << "Entry must have a name or a key: " << dumpNode(element) << endl;
00423     return 0;
00424   }
00425 
00426   if ( key.isEmpty() ) {
00427     key = name;
00428   }
00429 
00430   if ( name.isEmpty() ) {
00431     name = key;
00432     name.replace( " ", QString::null );
00433   } else if ( name.contains( ' ' ) ) {
00434     kdWarning()<<"Entry '"<<name<<"' contains spaces! <name> elements can't contain speces!"<<endl;
00435     name.remove( ' ' );
00436   }
00437 
00438   if (name.contains("$("))
00439   {
00440     if (param.isEmpty())
00441     {
00442       kdError() << "Name may not be parameterized: " << name << endl;
00443       return 0;
00444     }
00445   }
00446   else
00447   {
00448     if (!param.isEmpty())
00449     {
00450       kdError() << "Name must contain '$(" << param << ")': " << name << endl;
00451       return 0;
00452     }
00453   }
00454 
00455   if ( label.isEmpty() ) {
00456     label = key;
00457   }
00458 
00459   if ( type.isEmpty() ) type = "String"; // XXX : implicit type might be bad
00460 
00461   if (!param.isEmpty())
00462   {
00463     // Adjust name
00464     paramName = name;
00465     name.replace("$("+param+")", QString::null);
00466     // Lookup defaults for indexed entries
00467     for(int i = 0; i <= paramMax; i++)
00468     {
00469       paramDefaultValues.append(QString::null);
00470     }
00471 
00472     QDomNode n;
00473     for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
00474       QDomElement e = n.toElement();
00475       QString tag = e.tagName();
00476       if ( tag == "default" )
00477       {
00478         QString index = e.attribute("param");
00479         if (index.isEmpty())
00480            continue;
00481 
00482         bool ok;
00483         int i = index.toInt(&ok);
00484         if (!ok)
00485         {
00486           i = paramValues.findIndex(index);
00487           if (i == -1)
00488           {
00489             kdError() << "Index '" << index << "' for default value is unknown." << endl;
00490             return 0;
00491           }
00492         }
00493 
00494         if ((i < 0) || (i > paramMax))
00495         {
00496           kdError() << "Index '" << i << "' for default value is out of range [0, "<< paramMax<<"]." << endl;
00497           return 0;
00498         }
00499 
00500         QString tmpDefaultValue = e.text();
00501 
00502         if (e.attribute( "code" ) != "true")
00503            preProcessDefault(tmpDefaultValue, name, type, choices, code);
00504 
00505         paramDefaultValues[i] = tmpDefaultValue;
00506       }
00507     }
00508   }
00509 
00510   if (!defaultCode)
00511   {
00512     preProcessDefault(defaultValue, name, type, choices, code);
00513   }
00514 
00515   CfgEntry *result = new CfgEntry( group, type, key, name, label, whatsThis,
00516                                    code, defaultValue, choices,
00517                                    hidden == "true" );
00518   if (!param.isEmpty())
00519   {
00520     result->setParam(param);
00521     result->setParamName(paramName);
00522     result->setParamType(paramType);
00523     result->setParamValues(paramValues);
00524     result->setParamDefaultValues(paramDefaultValues);
00525     result->setParamMax(paramMax);
00526   }
00527   result->setMinValue(minValue);
00528   result->setMaxValue(maxValue);
00529 
00530   return result;
00531 }
00532 
00536 QString param( const QString &type )
00537 {
00538     if ( type == "String" )           return "const QString &";
00539     else if ( type == "StringList" )  return "const QStringList &";
00540     else if ( type == "Font" )        return "const QFont &";
00541     else if ( type == "Rect" )        return "const QRect &";
00542     else if ( type == "Size" )        return "const QSize &";
00543     else if ( type == "Color" )       return "const QColor &";
00544     else if ( type == "Point" )       return "const QPoint &";
00545     else if ( type == "Int" )         return "int";
00546     else if ( type == "UInt" )        return "uint";
00547     else if ( type == "Bool" )        return "bool";
00548     else if ( type == "Double" )      return "double";
00549     else if ( type == "DateTime" )    return "const QDateTime &";
00550     else if ( type == "Int64" )       return "Q_INT64";
00551     else if ( type == "UInt64" )      return "Q_UINT64";
00552     else if ( type == "IntList" )     return "const QValueList<int> &";
00553     else if ( type == "Enum" )        return "int";
00554     else if ( type == "Path" )        return "const QString &";
00555     else if ( type == "Password" )    return "const QString &";
00556     else {
00557         kdError() <<"kconfig_compiler does not support type \""<< type <<"\""<<endl;
00558         return "QString"; //For now, but an assert would be better
00559     }
00560 }
00561 
00565 QString cppType( const QString &type )
00566 {
00567     if ( type == "String" )           return "QString";
00568     else if ( type == "StringList" )  return "QStringList";
00569     else if ( type == "Font" )        return "QFont";
00570     else if ( type == "Rect" )        return "QRect";
00571     else if ( type == "Size" )        return "QSize";
00572     else if ( type == "Color" )       return "QColor";
00573     else if ( type == "Point" )       return "QPoint";
00574     else if ( type == "Int" )         return "int";
00575     else if ( type == "UInt" )        return "uint";
00576     else if ( type == "Bool" )        return "bool";
00577     else if ( type == "Double" )      return "double";
00578     else if ( type == "DateTime" )    return "QDateTime";
00579     else if ( type == "Int64" )       return "Q_INT64";
00580     else if ( type == "UInt64" )      return "Q_UINT64";
00581     else if ( type == "IntList" )     return "QValueList<int>";
00582     else if ( type == "Enum" )        return "int";
00583     else if ( type == "Path" )        return "QString";
00584     else if ( type == "Password" )    return "QString";
00585     else {
00586         kdError()<<"kconfig_compiler does not support type \""<< type <<"\""<<endl;
00587         return "QString"; //For now, but an assert would be better
00588     }
00589 }
00590 
00591 QString defaultValue( const QString &type )
00592 {
00593     if ( type == "String" )           return "\"\""; // Use empty string, not null string!
00594     else if ( type == "StringList" )  return "QStringList()";
00595     else if ( type == "Font" )        return "KGlobalSettings::generalFont()";
00596     else if ( type == "Rect" )        return "QRect()";
00597     else if ( type == "Size" )        return "QSize()";
00598     else if ( type == "Color" )       return "QColor(128, 128, 128)";
00599     else if ( type == "Point" )       return "QPoint()";
00600     else if ( type == "Int" )         return "0";
00601     else if ( type == "UInt" )        return "0";
00602     else if ( type == "Bool" )        return "false";
00603     else if ( type == "Double" )      return "0.0";
00604     else if ( type == "DateTime" )    return "QDateTime()";
00605     else if ( type == "Int64" )       return "0";
00606     else if ( type == "UInt64" )      return "0";
00607     else if ( type == "IntList" )     return "QValueList<int>()";
00608     else if ( type == "Enum" )        return "0";
00609     else if ( type == "Path" )        return "\"\""; // Use empty string, not null string!
00610     else if ( type == "Password" )    return "\"\""; // Use empty string, not null string!
00611     else {
00612         kdWarning()<<"Error, kconfig_compiler doesn't support the \""<< type <<"\" type!"<<endl;
00613         return "QString"; //For now, but an assert would be better
00614     }
00615 }
00616 
00617 QString itemType( const QString &type )
00618 {
00619   QString t;
00620 
00621   t = type;
00622   t.replace( 0, 1, t.left( 1 ).upper() );
00623 
00624   return t;
00625 }
00626 
00627 static QString itemDeclaration(const CfgEntry *e)
00628 {
00629   if (itemAccessors)
00630      return QString::null;
00631 
00632   return "  KConfigSkeleton::Item"+itemType( e->type() ) +
00633          "  *item" + e->name() + 
00634          ( (!e->param().isEmpty())?(QString("[%1]").arg(e->paramMax()+1)) : QString::null) + 
00635          ";\n";
00636 }
00637 
00638 static QString itemVar(const CfgEntry *e)
00639 {
00640   if (itemAccessors)
00641      return varName( e->name() ) + "Item";
00642 
00643   return "item" + e->name();
00644 
00645 }
00646 
00647 QString newItem( const QString &type, const QString &name, const QString &key,
00648                  const QString &defaultValue, const QString &param = QString::null)
00649 {
00650   QString t = "new KConfigSkeleton::Item" + itemType( type ) +
00651               "( currentGroup(), " + key + ", " + varName( name ) + param;
00652   if ( type == "Enum" ) t += ", values" + name;
00653   if ( !defaultValue.isEmpty() ) {
00654     t += ", ";
00655     if ( type == "String" ) t += defaultValue;
00656     else t+= defaultValue;
00657   }
00658   t += " );";
00659 
00660   return t;
00661 }
00662 
00663 QString paramString(const QString &s, const CfgEntry *e, int i)
00664 {
00665   QString result = s;
00666   QString needle = "$("+e->param()+")";
00667   if (result.contains(needle))
00668   {
00669     QString tmp;
00670     if (e->paramType() == "Enum")
00671     {
00672       tmp = e->paramValues()[i];
00673     }
00674     else
00675     {
00676       tmp = QString::number(i);
00677     }
00678 
00679     result.replace(needle, tmp);
00680   }
00681   return result;
00682 }
00683 
00684 QString paramString(const QString &group, const QStringList &parameters)
00685 {
00686   QString paramString = group;
00687   QString arguments;
00688   int i = 1;
00689   for( QStringList::ConstIterator it = parameters.begin();
00690        it != parameters.end(); ++it)
00691   {
00692      if (paramString.contains("$("+*it+")"))
00693      {
00694        QString tmp;
00695        tmp.sprintf("%%%d", i++);
00696        paramString.replace("$("+*it+")", tmp);
00697        arguments += ".arg( mParam"+*it+" )";
00698      }
00699   }
00700   if (arguments.isEmpty())
00701     return "QString::fromLatin1( \""+group+"\" )";
00702 
00703   return "QString::fromLatin1( \""+paramString+"\" )"+arguments;
00704 }
00705 
00706 /* int i is the value of the parameter */
00707 QString userTextsFunctions( CfgEntry *e, QString itemVarStr=QString::null, QString i=QString::null )
00708 {
00709   QString txt;
00710   if (itemVarStr.isNull()) itemVarStr=itemVar(e);
00711   if ( !e->label().isEmpty() ) {
00712     txt += "  " + itemVarStr + "->setLabel( i18n(";
00713     if ( !e->param().isEmpty() )
00714       txt += quoteString(e->label().replace("$("+e->param()+")", i));
00715     else 
00716       txt+= quoteString(e->label());
00717     txt+= ") );\n";
00718   }
00719   if ( !e->whatsThis().isEmpty() ) {
00720     txt += "  " + itemVarStr + "->setWhatsThis( i18n(";
00721     if ( !e->param().isEmpty() )
00722       txt += quoteString(e->whatsThis().replace("$("+e->param()+")", i));
00723     else 
00724       txt+= quoteString(e->whatsThis());
00725     txt+=") );\n";
00726   }
00727   return txt;
00728 }
00729 
00730 int main( int argc, char **argv )
00731 {
00732   KAboutData aboutData( "kconfig_compiler", I18N_NOOP("KDE .kcfg compiler"), "0.3",
00733     I18N_NOOP("KConfig Compiler") , KAboutData::License_LGPL );
00734   aboutData.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );
00735   aboutData.addAuthor( "Waldo Bastian", 0, "bastian@kde.org" );
00736   aboutData.addAuthor( "Zack Rusin", 0, "zack@kde.org" );
00737   aboutData.addCredit( "Reinhold Kainhofer", "Fix for parametrized entries", 
00738       "reinhold@kainhofer.com", "http://reinhold.kainhofer.com" );
00739 
00740   KCmdLineArgs::init( argc, argv, &aboutData );
00741   KCmdLineArgs::addCmdLineOptions( options );
00742 
00743   KInstance app( &aboutData );
00744 
00745   KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00746 
00747   if ( args->count() < 2 ) {
00748     kdError() << "Too few arguments." << endl;
00749     return 1;
00750   }
00751   if ( args->count() > 2 ) {
00752     kdError() << "Too many arguments." << endl;
00753     return 1;
00754   }
00755 
00756   QString baseDir = QFile::decodeName(args->getOption("directory"));
00757   if (!baseDir.endsWith("/"))
00758     baseDir.append("/");
00759 
00760   QString inputFilename = args->url( 0 ).path();
00761   QString codegenFilename = args->url( 1 ).path();
00762 
00763   if (!codegenFilename.endsWith(".kcfgc"))
00764   {
00765     kdError() << "Codegen options file must have extension .kcfgc" << endl;
00766     return 1;
00767   }
00768   QString baseName = args->url( 1 ).fileName();
00769   baseName = baseName.left(baseName.length() - 6);
00770 
00771   KSimpleConfig codegenConfig( codegenFilename, true );
00772 
00773   QString nameSpace = codegenConfig.readEntry("NameSpace");
00774   QString className = codegenConfig.readEntry("ClassName");
00775   QString inherits = codegenConfig.readEntry("Inherits");
00776   bool singleton = codegenConfig.readBoolEntry("Singleton", false);
00777   bool staticAccessors = singleton;
00778   bool customAddons = codegenConfig.readBoolEntry("CustomAdditions");
00779   QString memberVariables = codegenConfig.readEntry("MemberVariables");
00780   QStringList headerIncludes = codegenConfig.readListEntry("IncludeFiles");
00781   QStringList mutators = codegenConfig.readListEntry("Mutators");
00782   bool allMutators = false;
00783   if ((mutators.count() == 1) && (mutators[0].lower() == "true"))
00784      allMutators = true;
00785   itemAccessors = codegenConfig.readBoolEntry( "ItemAccessors", false );
00786   bool setUserTexts = codegenConfig.readBoolEntry( "SetUserTexts", false );
00787 
00788   globalEnums = codegenConfig.readBoolEntry( "GlobalEnums", false );
00789 
00790   QFile input( inputFilename );
00791 
00792   QDomDocument doc;
00793   QString errorMsg;
00794   int errorRow;
00795   int errorCol;
00796   if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
00797     kdError() << "Unable to load document." << endl;
00798     kdError() << "Parse error in " << args->url( 0 ).fileName() << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl;
00799     return 1;
00800   }
00801 
00802   QDomElement cfgElement = doc.documentElement();
00803 
00804   if ( cfgElement.isNull() ) {
00805     kdError() << "No document in kcfg file" << endl;
00806     return 1;
00807   }
00808 
00809   QString cfgFileName;
00810   bool cfgFileNameArg = false;
00811   QStringList parameters;
00812   QStringList includes;
00813 
00814   QPtrList<CfgEntry> entries;
00815   entries.setAutoDelete( true );
00816 
00817   QDomNode n;
00818   for ( n = cfgElement.firstChild(); !n.isNull(); n = n.nextSibling() ) {
00819     QDomElement e = n.toElement();
00820 
00821     QString tag = e.tagName();
00822 
00823     if ( tag == "include" ) {
00824       QString includeFile = e.text();
00825       if (!includeFile.isEmpty())
00826         includes.append(includeFile);
00827 
00828     } else if ( tag == "kcfgfile" ) {
00829       cfgFileName = e.attribute( "name" );
00830       cfgFileNameArg = e.attribute( "arg" ).lower() == "true";
00831       QDomNode n2;
00832       for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
00833         QDomElement e2 = n2.toElement();
00834         if ( e2.tagName() == "parameter" ) {
00835           parameters.append( e2.attribute( "name" ) );
00836         }
00837       }
00838 
00839     } else if ( tag == "group" ) {
00840       QString group = e.attribute( "name" );
00841       if ( group.isEmpty() ) {
00842         kdError() << "Group without name" << endl;
00843         return 1;
00844       }
00845       QDomNode n2;
00846       for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
00847         QDomElement e2 = n2.toElement();
00848         if ( e2.tagName() != "entry" ) continue;
00849         CfgEntry *entry = parseEntry( group, e2 );
00850         if ( entry ) entries.append( entry );
00851         else {
00852           kdError() << "Can't parse entry." << endl;
00853           return 1;
00854         }
00855       }
00856     }
00857   }
00858 
00859   if ( inherits.isEmpty() ) inherits = "KConfigSkeleton";
00860 
00861   if ( className.isEmpty() ) {
00862     kdError() << "Class name missing" << endl;
00863     return 1;
00864   }
00865 
00866   if ( singleton && !parameters.isEmpty() ) {
00867     kdError() << "Singleton class can not have parameters" << endl;
00868     return 1;
00869   }
00870 
00871   if ( singleton && cfgFileNameArg)
00872   {
00873     kdError() << "Singleton class can not use filename as argument." << endl;
00874     return 1;
00875   }
00876 
00877   if ( !cfgFileName.isEmpty() && cfgFileNameArg)
00878   {
00879     kdError() << "Having both a fixed filename and a filename as argument is not possible." << endl;
00880     return 1;
00881   }
00882 
00883   if ( entries.isEmpty() ) {
00884     kdWarning() << "No entries." << endl;
00885   }
00886 
00887 #if 0
00888   CfgEntry *cfg;
00889   for( cfg = entries.first(); cfg; cfg = entries.next() ) {
00890     cfg->dump();
00891   }
00892 #endif
00893 
00894   QString headerFileName = baseName + ".h";
00895   QString implementationFileName = baseName + ".cpp";
00896   QString cppPreamble; // code to be inserted at the beginnin of the cpp file, e.g. initialization of static values
00897 
00898   QFile header( baseDir + headerFileName );
00899   if ( !header.open( IO_WriteOnly ) ) {
00900     kdError() << "Can't open '" << headerFileName << "for writing." << endl;
00901     return 1;
00902   }
00903 
00904   QTextStream h( &header );
00905 
00906   h << "// This file is generated by kconfig_compiler from " << args->url(0).fileName() << "." << endl;
00907   h << "// All changes you do to this file will be lost." << endl;
00908 
00909   h << "#ifndef " << ( !nameSpace.isEmpty() ? nameSpace.upper() + "_" : "" )
00910     << className.upper() << "_H" << endl;
00911   h << "#define " << ( !nameSpace.isEmpty() ? nameSpace.upper() + "_" : "" )
00912     << className.upper() << "_H" << endl << endl;
00913 
00914   // Includes
00915   QStringList::ConstIterator it;
00916   for( it = headerIncludes.begin(); it != headerIncludes.end(); ++it ) {
00917     h << "#include <" << *it << ">" << endl;
00918   }
00919 
00920   if ( headerIncludes.count() > 0 ) h << endl;
00921 
00922   h << "#include <kconfigskeleton.h>" << endl << endl;
00923 
00924   if ( !nameSpace.isEmpty() )
00925     h << "namespace " << nameSpace << " {" << endl << endl;
00926 
00927   // Class declaration header
00928   h << "class " << className << " : public " << inherits << endl;
00929   h << "{" << endl;
00930   h << "  public:" << endl;
00931 
00932   // enums
00933   CfgEntry *e;
00934   for( e = entries.first(); e; e = entries.next() ) {
00935     QValueList<CfgEntry::Choice> choices = e->choices();
00936     if ( !choices.isEmpty() ) {
00937       QStringList values;
00938       QValueList<CfgEntry::Choice>::ConstIterator itChoice;
00939       for( itChoice = choices.begin(); itChoice != choices.end(); ++itChoice ) {
00940         values.append( (*itChoice).name );
00941       }
00942       if ( globalEnums ) {
00943         h << "    enum { " << values.join( ", " ) << " };" << endl;
00944       } else {
00945         h << "    class " << enumName(e->name()) << endl;
00946         h << "    {" << endl;
00947         h << "      public:" << endl;
00948         h << "      enum { " << values.join( ", " ) << ", COUNT };" << endl;
00949         h << "    };" << endl;
00950       }
00951     }
00952     QStringList values = e->paramValues();
00953     if ( !values.isEmpty() ) {
00954       if ( globalEnums ) {
00955         h << "    enum { " << values.join( ", " ) << " };" << endl;
00956         h << "    static const char* const " << enumName(e->param()) << "ToString[];" << endl;
00957         cppPreamble += "const char* const " + className + "::" + enumName(e->param()) + "ToString[] = " +
00958             "{ \"" + values.join( "\", \"" ) + "\" };\n";
00959       } else {
00960         h << "    class " << enumName(e->param()) << endl;
00961         h << "    {" << endl;
00962         h << "      public:" << endl;
00963         h << "      enum { " << values.join( ", " ) << ", COUNT };" << endl;
00964         h << "      static const char* const enumToString[];" << endl;
00965         h << "    };" << endl;
00966         cppPreamble += "const char* const " + className + "::" + enumName(e->param()) + "::enumToString[] = " +
00967             "{ \"" + values.join( "\", \"" ) + "\" };\n";
00968       }
00969     }
00970   }
00971 
00972   h << endl;
00973 
00974   // Constructor or singleton accessor
00975   if ( !singleton ) {
00976     h << "    " << className << "(";
00977     if (cfgFileNameArg)
00978        h << " KSharedConfig::Ptr config" << (parameters.isEmpty() ? " " : ", ");
00979     for (QStringList::ConstIterator it = parameters.begin();
00980          it != parameters.end(); ++it)
00981     {
00982        if (it != parameters.begin())
00983          h << ",";
00984        h << " const QString &" << *it;
00985     }
00986     h << " );" << endl;
00987   } else {
00988     h << "    static " << className << " *self();" << endl;
00989   }
00990 
00991   // Destructor
00992   h << "    ~" << className << "();" << endl << endl;
00993 
00994   QString This;
00995   QString Const;
00996   if (staticAccessors)
00997     This = "self()->";
00998   else
00999     Const = " const";
01000 
01001   for( e = entries.first(); e; e = entries.next() ) {
01002     QString n = e->name();
01003     QString t = e->type();
01004 
01005     // Manipulator
01006     if (allMutators || mutators.contains(n))
01007     {
01008       h << "    /**" << endl;
01009       h << "      Set " << e->label() << endl;
01010       h << "    */" << endl;
01011       if (staticAccessors)
01012         h << "    static" << endl;
01013       h << "    void " << setFunction(n) << "( ";
01014       if (!e->param().isEmpty())
01015         h << cppType(e->paramType()) << " i, ";
01016       h << param( t ) << " v )" << endl;
01017       h << "    {" << endl;
01018       h << "      if (!" << This << "isImmutable( QString::fromLatin1( \"";
01019       if (!e->param().isEmpty()) {
01020         h << e->paramName().replace("$("+e->param()+")", "%1") << "\" ).arg( ";
01021         if ( e->paramType() == "Enum" ) {
01022           h << "QString::fromLatin1( ";
01023           if (globalEnums) 
01024             h << enumName(e->name()) << "ToString[i]";
01025           else 
01026             h << enumName(e->param()) << "::enumToString[i]";
01027           h << " )";
01028         } else {
01029           h << "i";
01030         }
01031         h << " )";
01032       } else
01033         h << n << "\" )";
01034       h << " ))" << endl;
01035       h << "        " << This << varName(n);
01036       if (!e->param().isEmpty())
01037         h << "[i]";
01038       h << " = v;" << endl;
01039       h << "    }" << endl << endl;
01040     }
01041 
01042     // Accessor
01043     h << "    /**" << endl;
01044     h << "      Get " << e->label() << endl;
01045     h << "    */" << endl;
01046     if (staticAccessors)
01047       h << "    static" << endl;
01048     h << "    " << cppType(t) << " " << getFunction(n) << "(";
01049     if (!e->param().isEmpty())
01050       h << " " << cppType(e->paramType()) <<" i ";
01051     h << ")" << Const << endl;
01052     h << "    {" << endl;
01053     h << "      return " << This << varName(n);
01054     if (!e->param().isEmpty()) h << "[i]";
01055     h << ";" << endl;
01056     h << "    }" << endl;
01057 
01058     // Item accessor
01059     if ( itemAccessors ) {
01060       h << endl;
01061       h << "    /**" << endl;
01062       h << "      Get Item object corresponding to " << n << "()"
01063         << endl;
01064       h << "    */" << endl;
01065       h << "    Item" << itemType( e->type() ) << " *"
01066         << getFunction( n ) << "Item(";
01067       if (!e->param().isEmpty()) {
01068         h << " " << cppType(e->paramType()) << " i ";
01069       }
01070       h << ")" << endl;
01071       h << "    {" << endl;
01072       h << "      return " << itemVar(e);
01073       if (!e->param().isEmpty()) h << "[i]";
01074       h << ";" << endl;
01075       h << "    }" << endl;
01076     }
01077 
01078     h << endl;
01079   }
01080 
01081   // Static writeConfig method for singleton
01082   if ( singleton ) {
01083     h << "    static" << endl;
01084     h << "    void writeConfig()" << endl;
01085     h << "    {" << endl;
01086     h << "      static_cast<KConfigSkeleton*>(self())->writeConfig();" << endl;
01087     h << "    }" << endl;
01088   }
01089 
01090   h << "  protected:" << endl;
01091 
01092   // Private constructor for singleton
01093   if ( singleton ) {
01094     h << "    " << className << "();" << endl;
01095     h << "    static " << className << " *mSelf;" << endl << endl;
01096   }
01097 
01098   // Member variables
01099   if ( !memberVariables.isEmpty() && memberVariables != "private" ) {
01100     h << "  " << memberVariables << ":" << endl;
01101   }
01102 
01103   // Class Parameters
01104   for (QStringList::ConstIterator it = parameters.begin();
01105        it != parameters.end(); ++it)
01106   {
01107      h << "    QString mParam" << *it << ";" << endl;
01108   }
01109 
01110   QString group;
01111   for( e = entries.first(); e; e = entries.next() ) {
01112     if ( e->group() != group ) {
01113       group = e->group();
01114       h << endl;
01115       h << "    // " << group << endl;
01116     }
01117     h << "    " << cppType(e->type()) << " " << varName(e->name());
01118     if (!e->param().isEmpty())
01119     {
01120       h << QString("[%1]").arg(e->paramMax()+1);
01121     }
01122     h << ";" << endl;
01123   }
01124 
01125   h << endl << "  private:" << endl;
01126   if ( itemAccessors ) {
01127     for( e = entries.first(); e; e = entries.next() ) {
01128       h << "    Item" << itemType( e->type() ) << " *" << itemVar( e );
01129       if (!e->param().isEmpty() ) h << QString("[%1]").arg( e->paramMax()+1 );
01130       h << ";" << endl;
01131     }
01132   }
01133 
01134   if (customAddons)
01135   {
01136      h << "    // Include custom additions" << endl;
01137      h << "    #include \"" << filenameOnly(baseName) << "_addons.h\"" <<endl;
01138   }
01139 
01140   h << "};" << endl << endl;
01141 
01142   if ( !nameSpace.isEmpty() ) h << "}" << endl << endl;
01143 
01144   h << "#endif" << endl;
01145 
01146 
01147   header.close();
01148 
01149   QFile implementation( baseDir + implementationFileName );
01150   if ( !implementation.open( IO_WriteOnly ) ) {
01151     kdError() << "Can't open '" << implementationFileName << "for writing."
01152               << endl;
01153     return 1;
01154   }
01155 
01156   QTextStream cpp( &implementation );
01157 
01158 
01159   cpp << "// This file is generated by kconfig_compiler from " << args->url(0).fileName() << "." << endl;
01160   cpp << "// All changes you do to this file will be lost." << endl << endl;
01161 
01162   cpp << "#include \"" << headerFileName << "\"" << endl << endl;
01163 
01164   if ( setUserTexts ) cpp << "#include <klocale.h>" << endl << endl;
01165 
01166   // Includes
01167   for( it = includes.begin(); it != includes.end(); ++it ) {
01168     cpp << "#include <" << *it << ">" << endl;
01169   }
01170 
01171   // Header required by singleton implementation
01172   if ( singleton )
01173     cpp << "#include <kstaticdeleter.h>" << endl << endl;
01174 
01175   if ( !nameSpace.isEmpty() )
01176     cpp << "using namespace " << nameSpace << ";" << endl << endl;
01177 
01178   // Singleton implementation
01179   if ( singleton ) {
01180     cpp << className << " *" << className << "::mSelf = 0;" << endl;
01181     cpp << "static KStaticDeleter<" << className << "> static" << className << "Deleter;" << endl << endl;
01182 
01183     cpp << className << " *" << className << "::self()" << endl;
01184     cpp << "{" << endl;
01185     cpp << "  if ( !mSelf ) {" << endl;
01186     cpp << "    static" << className << "Deleter.setObject( mSelf, new " << className << "() );" << endl;
01187     cpp << "    mSelf->readConfig();" << endl;
01188     cpp << "  }" << endl << endl;
01189     cpp << "  return mSelf;" << endl;
01190     cpp << "}" << endl << endl;
01191   }
01192   
01193   if ( !cppPreamble.isEmpty() )
01194     cpp << cppPreamble << endl;
01195 
01196   // Constructor
01197   cpp << className << "::" << className << "( ";
01198   if (cfgFileNameArg)
01199      cpp << " KSharedConfig::Ptr config" << (parameters.isEmpty() ? " " : ", ");
01200   for (QStringList::ConstIterator it = parameters.begin();
01201        it != parameters.end(); ++it)
01202   {
01203      if (it != parameters.begin())
01204        cpp << ",";
01205      cpp << " const QString &" << *it;
01206   }
01207   cpp << " )" << endl;
01208 
01209   cpp << "  : " << inherits << "(";
01210   if ( !cfgFileName.isEmpty() ) cpp << " QString::fromLatin1( \"" << cfgFileName << "\" ";
01211   if ( cfgFileNameArg ) cpp << " config ";
01212   if ( !cfgFileName.isEmpty() ) cpp << ") ";
01213   cpp << ")" << endl;
01214 
01215   // Store parameters
01216   for (QStringList::ConstIterator it = parameters.begin();
01217        it != parameters.end(); ++it)
01218   {
01219      cpp << "  , mParam" << *it << "(" << *it << ")" << endl;
01220   }
01221 
01222   cpp << "{" << endl;
01223 
01224   // Needed in case the singleton class is used as baseclass for
01225   // another singleton.
01226   if ( singleton )
01227     cpp << "  mSelf = this;" << endl;
01228 
01229   group = QString::null;
01230   for( e = entries.first(); e; e = entries.next() ) {
01231     if ( e->group() != group ) {
01232       if ( !group.isEmpty() ) cpp << endl;
01233       group = e->group();
01234       cpp << "  setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl;
01235     }
01236 
01237     QString key = paramString(e->key(), parameters);
01238     if ( !e->code().isEmpty())
01239     {
01240       cpp << e->code() << endl;
01241     }
01242     if ( e->type() == "Enum" ) {
01243       cpp << "  QValueList<KConfigSkeleton::ItemEnum::Choice> values"
01244           << e->name() << ";" << endl;
01245       QValueList<CfgEntry::Choice> choices = e->choices();
01246       QValueList<CfgEntry::Choice>::ConstIterator it;
01247       for( it = choices.begin(); it != choices.end(); ++it ) {
01248         cpp << "  {" << endl;
01249         cpp << "    KConfigSkeleton::ItemEnum::Choice choice;" << endl;
01250         cpp << "    choice.name = QString::fromLatin1( \"" << (*it).name << "\" );" << endl;
01251         if ( setUserTexts ) {
01252           if ( !(*it).label.isEmpty() )
01253             cpp << "    choice.label = i18n(" << quoteString((*it).label) << ");" << endl;
01254           if ( !(*it).whatsThis.isEmpty() )
01255             cpp << "    choice.whatsThis = i18n(" << quoteString((*it).whatsThis) << ");" << endl;
01256         }
01257         cpp << "    values" << e->name() << ".append( choice );" << endl;
01258         cpp << "  }" << endl;
01259       }
01260     }
01261     cpp << itemDeclaration(e);
01262     if (e->param().isEmpty())
01263     {
01264       // Normal case
01265       cpp << "  " << itemVar(e) << " = "
01266           << newItem( e->type(), e->name(), key, e->defaultValue() ) << endl;
01267 
01268       if ( !e->minValue().isEmpty() )
01269         cpp << "  " << itemVar(e) << "->setMinValue(" << e->minValue() << ");" << endl;
01270       if ( !e->maxValue().isEmpty() )
01271         cpp << "  " << itemVar(e) << "->setMaxValue(" << e->maxValue() << ");" << endl;
01272 
01273       if ( setUserTexts )
01274         cpp << userTextsFunctions( e );
01275 
01276       cpp << "  addItem( " << itemVar(e);
01277       QString quotedName = e->name();
01278       addQuotes( quotedName );
01279       if ( quotedName != key ) cpp << ", QString::fromLatin1( \"" << e->name() << "\" )";
01280       cpp << " );" << endl;
01281     }
01282     else
01283     {
01284       // Indexed
01285       for(int i = 0; i <= e->paramMax(); i++)
01286       {
01287         QString defaultStr;
01288         QString itemVarStr(itemVar(e)+QString("[%1]").arg(i));
01289         
01290         if ( !e->paramDefaultValue(i).isEmpty() )
01291           defaultStr = e->paramDefaultValue(i);
01292         else if ( !e->defaultValue().isEmpty() )
01293           defaultStr = paramString(e->defaultValue(), e, i);
01294         else
01295           defaultStr = defaultValue( e->type() );
01296 
01297         cpp << "  " << itemVarStr << " = "
01298             << newItem( e->type(), e->name(), paramString(key, e, i), defaultStr, QString("[%1]").arg(i) )
01299             << endl;
01300 
01301         if ( setUserTexts )
01302           cpp << userTextsFunctions( e, itemVarStr, e->paramName() );
01303 
01304         // Make mutators for enum parameters work by adding them with $(..) replaced by the 
01305         // param name. The check for isImmutable in the set* functions doesn't have the param 
01306         // name available, just the corresponding enum value (int), so we need to store the 
01307         // param names in a separate static list!.
01308         cpp << "  addItem( " << itemVarStr << ", QString::fromLatin1( \"";
01309         if ( e->paramType()=="Enum" )
01310           cpp << e->paramName().replace( "$("+e->param()+")", "%1").arg(e->paramValues()[i] );
01311         else
01312           cpp << e->paramName().replace( "$("+e->param()+")", "%1").arg(i);
01313         cpp << "\" ) );" << endl;
01314       }
01315     }
01316   }
01317 
01318   cpp << "}" << endl << endl;
01319 
01320   // Destructor
01321   cpp << className << "::~" << className << "()" << endl;
01322   cpp << "{" << endl;
01323   if ( singleton ) {
01324     cpp << "  if ( mSelf == this )" << endl;
01325     cpp << "    static" << className << "Deleter.setObject( mSelf, 0, false );" << endl;
01326   }
01327   cpp << "}" << endl << endl;
01328 
01329   implementation.close();
01330 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Nov 27 13:41:10 2004 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003