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   QString visibility = codegenConfig.readEntry("Visibility");
00777   if (!visibility.isEmpty()) visibility+=" ";
00778   bool singleton = codegenConfig.readBoolEntry("Singleton", false);
00779   bool staticAccessors = singleton;
00780   bool customAddons = codegenConfig.readBoolEntry("CustomAdditions");
00781   QString memberVariables = codegenConfig.readEntry("MemberVariables");
00782   QStringList headerIncludes = codegenConfig.readListEntry("IncludeFiles");
00783   QStringList mutators = codegenConfig.readListEntry("Mutators");
00784   bool allMutators = false;
00785   if ((mutators.count() == 1) && (mutators[0].lower() == "true"))
00786      allMutators = true;
00787   itemAccessors = codegenConfig.readBoolEntry( "ItemAccessors", false );
00788   bool setUserTexts = codegenConfig.readBoolEntry( "SetUserTexts", false );
00789 
00790   globalEnums = codegenConfig.readBoolEntry( "GlobalEnums", false );
00791 
00792   QFile input( inputFilename );
00793 
00794   QDomDocument doc;
00795   QString errorMsg;
00796   int errorRow;
00797   int errorCol;
00798   if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
00799     kdError() << "Unable to load document." << endl;
00800     kdError() << "Parse error in " << args->url( 0 ).fileName() << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl;
00801     return 1;
00802   }
00803 
00804   QDomElement cfgElement = doc.documentElement();
00805 
00806   if ( cfgElement.isNull() ) {
00807     kdError() << "No document in kcfg file" << endl;
00808     return 1;
00809   }
00810 
00811   QString cfgFileName;
00812   bool cfgFileNameArg = false;
00813   QStringList parameters;
00814   QStringList includes;
00815 
00816   QPtrList<CfgEntry> entries;
00817   entries.setAutoDelete( true );
00818 
00819   QDomNode n;
00820   for ( n = cfgElement.firstChild(); !n.isNull(); n = n.nextSibling() ) {
00821     QDomElement e = n.toElement();
00822 
00823     QString tag = e.tagName();
00824 
00825     if ( tag == "include" ) {
00826       QString includeFile = e.text();
00827       if (!includeFile.isEmpty())
00828         includes.append(includeFile);
00829 
00830     } else if ( tag == "kcfgfile" ) {
00831       cfgFileName = e.attribute( "name" );
00832       cfgFileNameArg = e.attribute( "arg" ).lower() == "true";
00833       QDomNode n2;
00834       for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
00835         QDomElement e2 = n2.toElement();
00836         if ( e2.tagName() == "parameter" ) {
00837           parameters.append( e2.attribute( "name" ) );
00838         }
00839       }
00840 
00841     } else if ( tag == "group" ) {
00842       QString group = e.attribute( "name" );
00843       if ( group.isEmpty() ) {
00844         kdError() << "Group without name" << endl;
00845         return 1;
00846       }
00847       QDomNode n2;
00848       for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
00849         QDomElement e2 = n2.toElement();
00850         if ( e2.tagName() != "entry" ) continue;
00851         CfgEntry *entry = parseEntry( group, e2 );
00852         if ( entry ) entries.append( entry );
00853         else {
00854           kdError() << "Can't parse entry." << endl;
00855           return 1;
00856         }
00857       }
00858     }
00859   }
00860 
00861   if ( inherits.isEmpty() ) inherits = "KConfigSkeleton";
00862 
00863   if ( className.isEmpty() ) {
00864     kdError() << "Class name missing" << endl;
00865     return 1;
00866   }
00867 
00868   if ( singleton && !parameters.isEmpty() ) {
00869     kdError() << "Singleton class can not have parameters" << endl;
00870     return 1;
00871   }
00872 
00873   if ( singleton && cfgFileNameArg)
00874   {
00875     kdError() << "Singleton class can not use filename as argument." << endl;
00876     return 1;
00877   }
00878 
00879   if ( !cfgFileName.isEmpty() && cfgFileNameArg)
00880   {
00881     kdError() << "Having both a fixed filename and a filename as argument is not possible." << endl;
00882     return 1;
00883   }
00884 
00885   if ( entries.isEmpty() ) {
00886     kdWarning() << "No entries." << endl;
00887   }
00888 
00889 #if 0
00890   CfgEntry *cfg;
00891   for( cfg = entries.first(); cfg; cfg = entries.next() ) {
00892     cfg->dump();
00893   }
00894 #endif
00895 
00896   QString headerFileName = baseName + ".h";
00897   QString implementationFileName = baseName + ".cpp";
00898   QString cppPreamble; // code to be inserted at the beginnin of the cpp file, e.g. initialization of static values
00899 
00900   QFile header( baseDir + headerFileName );
00901   if ( !header.open( IO_WriteOnly ) ) {
00902     kdError() << "Can't open '" << headerFileName << "for writing." << endl;
00903     return 1;
00904   }
00905 
00906   QTextStream h( &header );
00907 
00908   h << "// This file is generated by kconfig_compiler from " << args->url(0).fileName() << "." << endl;
00909   h << "// All changes you do to this file will be lost." << endl;
00910 
00911   h << "#ifndef " << ( !nameSpace.isEmpty() ? nameSpace.upper() + "_" : "" )
00912     << className.upper() << "_H" << endl;
00913   h << "#define " << ( !nameSpace.isEmpty() ? nameSpace.upper() + "_" : "" )
00914     << className.upper() << "_H" << endl << endl;
00915 
00916   // Includes
00917   QStringList::ConstIterator it;
00918   for( it = headerIncludes.begin(); it != headerIncludes.end(); ++it ) {
00919     h << "#include <" << *it << ">" << endl;
00920   }
00921 
00922   if ( headerIncludes.count() > 0 ) h << endl;
00923 
00924   h << "#include <kconfigskeleton.h>" << endl << endl;
00925 
00926   if ( !nameSpace.isEmpty() )
00927     h << "namespace " << nameSpace << " {" << endl << endl;
00928 
00929   // Class declaration header
00930   h << "class " << visibility << className << " : public " << inherits << endl;
00931   h << "{" << endl;
00932   h << "  public:" << endl;
00933 
00934   // enums
00935   CfgEntry *e;
00936   for( e = entries.first(); e; e = entries.next() ) {
00937     QValueList<CfgEntry::Choice> choices = e->choices();
00938     if ( !choices.isEmpty() ) {
00939       QStringList values;
00940       QValueList<CfgEntry::Choice>::ConstIterator itChoice;
00941       for( itChoice = choices.begin(); itChoice != choices.end(); ++itChoice ) {
00942         values.append( (*itChoice).name );
00943       }
00944       if ( globalEnums ) {
00945         h << "    enum { " << values.join( ", " ) << " };" << endl;
00946       } else {
00947         h << "    class " << enumName(e->name()) << endl;
00948         h << "    {" << endl;
00949         h << "      public:" << endl;
00950         h << "      enum { " << values.join( ", " ) << ", COUNT };" << endl;
00951         h << "    };" << endl;
00952       }
00953     }
00954     QStringList values = e->paramValues();
00955     if ( !values.isEmpty() ) {
00956       if ( globalEnums ) {
00957         h << "    enum { " << values.join( ", " ) << " };" << endl;
00958         h << "    static const char* const " << enumName(e->param()) << "ToString[];" << endl;
00959         cppPreamble += "const char* const " + className + "::" + enumName(e->param()) + "ToString[] = " +
00960             "{ \"" + values.join( "\", \"" ) + "\" };\n";
00961       } else {
00962         h << "    class " << enumName(e->param()) << endl;
00963         h << "    {" << endl;
00964         h << "      public:" << endl;
00965         h << "      enum { " << values.join( ", " ) << ", COUNT };" << endl;
00966         h << "      static const char* const enumToString[];" << endl;
00967         h << "    };" << endl;
00968         cppPreamble += "const char* const " + className + "::" + enumName(e->param()) + "::enumToString[] = " +
00969             "{ \"" + values.join( "\", \"" ) + "\" };\n";
00970       }
00971     }
00972   }
00973 
00974   h << endl;
00975 
00976   // Constructor or singleton accessor
00977   if ( !singleton ) {
00978     h << "    " << className << "(";
00979     if (cfgFileNameArg)
00980        h << " KSharedConfig::Ptr config" << (parameters.isEmpty() ? " " : ", ");
00981     for (QStringList::ConstIterator it = parameters.begin();
00982          it != parameters.end(); ++it)
00983     {
00984        if (it != parameters.begin())
00985          h << ",";
00986        h << " const QString &" << *it;
00987     }
00988     h << " );" << endl;
00989   } else {
00990     h << "    static " << className << " *self();" << endl;
00991   }
00992 
00993   // Destructor
00994   h << "    ~" << className << "();" << endl << endl;
00995 
00996   QString This;
00997   QString Const;
00998   if (staticAccessors)
00999     This = "self()->";
01000   else
01001     Const = " const";
01002 
01003   for( e = entries.first(); e; e = entries.next() ) {
01004     QString n = e->name();
01005     QString t = e->type();
01006 
01007     // Manipulator
01008     if (allMutators || mutators.contains(n))
01009     {
01010       h << "    /**" << endl;
01011       h << "      Set " << e->label() << endl;
01012       h << "    */" << endl;
01013       if (staticAccessors)
01014         h << "    static" << endl;
01015       h << "    void " << setFunction(n) << "( ";
01016       if (!e->param().isEmpty())
01017         h << cppType(e->paramType()) << " i, ";
01018       h << param( t ) << " v )" << endl;
01019       h << "    {" << endl;
01020       h << "      if (!" << This << "isImmutable( QString::fromLatin1( \"";
01021       if (!e->param().isEmpty()) {
01022         h << e->paramName().replace("$("+e->param()+")", "%1") << "\" ).arg( ";
01023         if ( e->paramType() == "Enum" ) {
01024           h << "QString::fromLatin1( ";
01025           if (globalEnums) 
01026             h << enumName(e->name()) << "ToString[i]";
01027           else 
01028             h << enumName(e->param()) << "::enumToString[i]";
01029           h << " )";
01030         } else {
01031           h << "i";
01032         }
01033         h << " )";
01034       } else
01035         h << n << "\" )";
01036       h << " ))" << endl;
01037       h << "        " << This << varName(n);
01038       if (!e->param().isEmpty())
01039         h << "[i]";
01040       h << " = v;" << endl;
01041       h << "    }" << endl << endl;
01042     }
01043 
01044     // Accessor
01045     h << "    /**" << endl;
01046     h << "      Get " << e->label() << endl;
01047     h << "    */" << endl;
01048     if (staticAccessors)
01049       h << "    static" << endl;
01050     h << "    " << cppType(t) << " " << getFunction(n) << "(";
01051     if (!e->param().isEmpty())
01052       h << " " << cppType(e->paramType()) <<" i ";
01053     h << ")" << Const << endl;
01054     h << "    {" << endl;
01055     h << "      return " << This << varName(n);
01056     if (!e->param().isEmpty()) h << "[i]";
01057     h << ";" << endl;
01058     h << "    }" << endl;
01059 
01060     // Item accessor
01061     if ( itemAccessors ) {
01062       h << endl;
01063       h << "    /**" << endl;
01064       h << "      Get Item object corresponding to " << n << "()"
01065         << endl;
01066       h << "    */" << endl;
01067       h << "    Item" << itemType( e->type() ) << " *"
01068         << getFunction( n ) << "Item(";
01069       if (!e->param().isEmpty()) {
01070         h << " " << cppType(e->paramType()) << " i ";
01071       }
01072       h << ")" << endl;
01073       h << "    {" << endl;
01074       h << "      return " << itemVar(e);
01075       if (!e->param().isEmpty()) h << "[i]";
01076       h << ";" << endl;
01077       h << "    }" << endl;
01078     }
01079 
01080     h << endl;
01081   }
01082 
01083   // Static writeConfig method for singleton
01084   if ( singleton ) {
01085     h << "    static" << endl;
01086     h << "    void writeConfig()" << endl;
01087     h << "    {" << endl;
01088     h << "      static_cast<KConfigSkeleton*>(self())->writeConfig();" << endl;
01089     h << "    }" << endl;
01090   }
01091 
01092   h << "  protected:" << endl;
01093 
01094   // Private constructor for singleton
01095   if ( singleton ) {
01096     h << "    " << className << "();" << endl;
01097     h << "    static " << className << " *mSelf;" << endl << endl;
01098   }
01099 
01100   // Member variables
01101   if ( !memberVariables.isEmpty() && memberVariables != "private" ) {
01102     h << "  " << memberVariables << ":" << endl;
01103   }
01104 
01105   // Class Parameters
01106   for (QStringList::ConstIterator it = parameters.begin();
01107        it != parameters.end(); ++it)
01108   {
01109      h << "    QString mParam" << *it << ";" << endl;
01110   }
01111 
01112   QString group;
01113   for( e = entries.first(); e; e = entries.next() ) {
01114     if ( e->group() != group ) {
01115       group = e->group();
01116       h << endl;
01117       h << "    // " << group << endl;
01118     }
01119     h << "    " << cppType(e->type()) << " " << varName(e->name());
01120     if (!e->param().isEmpty())
01121     {
01122       h << QString("[%1]").arg(e->paramMax()+1);
01123     }
01124     h << ";" << endl;
01125   }
01126 
01127   h << endl << "  private:" << endl;
01128   if ( itemAccessors ) {
01129     for( e = entries.first(); e; e = entries.next() ) {
01130       h << "    Item" << itemType( e->type() ) << " *" << itemVar( e );
01131       if (!e->param().isEmpty() ) h << QString("[%1]").arg( e->paramMax()+1 );
01132       h << ";" << endl;
01133     }
01134   }
01135 
01136   if (customAddons)
01137   {
01138      h << "    // Include custom additions" << endl;
01139      h << "    #include \"" << filenameOnly(baseName) << "_addons.h\"" <<endl;
01140   }
01141 
01142   h << "};" << endl << endl;
01143 
01144   if ( !nameSpace.isEmpty() ) h << "}" << endl << endl;
01145 
01146   h << "#endif" << endl;
01147 
01148 
01149   header.close();
01150 
01151   QFile implementation( baseDir + implementationFileName );
01152   if ( !implementation.open( IO_WriteOnly ) ) {
01153     kdError() << "Can't open '" << implementationFileName << "for writing."
01154               << endl;
01155     return 1;
01156   }
01157 
01158   QTextStream cpp( &implementation );
01159 
01160 
01161   cpp << "// This file is generated by kconfig_compiler from " << args->url(0).fileName() << "." << endl;
01162   cpp << "// All changes you do to this file will be lost." << endl << endl;
01163 
01164   cpp << "#include \"" << headerFileName << "\"" << endl << endl;
01165 
01166   if ( setUserTexts ) cpp << "#include <klocale.h>" << endl << endl;
01167 
01168   // Includes
01169   for( it = includes.begin(); it != includes.end(); ++it ) {
01170     cpp << "#include <" << *it << ">" << endl;
01171   }
01172 
01173   // Header required by singleton implementation
01174   if ( singleton )
01175     cpp << "#include <kstaticdeleter.h>" << endl << endl;
01176 
01177   if ( !nameSpace.isEmpty() )
01178     cpp << "using namespace " << nameSpace << ";" << endl << endl;
01179 
01180   // Singleton implementation
01181   if ( singleton ) {
01182     cpp << className << " *" << className << "::mSelf = 0;" << endl;
01183     cpp << "static KStaticDeleter<" << className << "> static" << className << "Deleter;" << endl << endl;
01184 
01185     cpp << className << " *" << className << "::self()" << endl;
01186     cpp << "{" << endl;
01187     cpp << "  if ( !mSelf ) {" << endl;
01188     cpp << "    static" << className << "Deleter.setObject( mSelf, new " << className << "() );" << endl;
01189     cpp << "    mSelf->readConfig();" << endl;
01190     cpp << "  }" << endl << endl;
01191     cpp << "  return mSelf;" << endl;
01192     cpp << "}" << endl << endl;
01193   }
01194   
01195   if ( !cppPreamble.isEmpty() )
01196     cpp << cppPreamble << endl;
01197 
01198   // Constructor
01199   cpp << className << "::" << className << "( ";
01200   if (cfgFileNameArg)
01201      cpp << " KSharedConfig::Ptr config" << (parameters.isEmpty() ? " " : ", ");
01202   for (QStringList::ConstIterator it = parameters.begin();
01203        it != parameters.end(); ++it)
01204   {
01205      if (it != parameters.begin())
01206        cpp << ",";
01207      cpp << " const QString &" << *it;
01208   }
01209   cpp << " )" << endl;
01210 
01211   cpp << "  : " << inherits << "(";
01212   if ( !cfgFileName.isEmpty() ) cpp << " QString::fromLatin1( \"" << cfgFileName << "\" ";
01213   if ( cfgFileNameArg ) cpp << " config ";
01214   if ( !cfgFileName.isEmpty() ) cpp << ") ";
01215   cpp << ")" << endl;
01216 
01217   // Store parameters
01218   for (QStringList::ConstIterator it = parameters.begin();
01219        it != parameters.end(); ++it)
01220   {
01221      cpp << "  , mParam" << *it << "(" << *it << ")" << endl;
01222   }
01223 
01224   cpp << "{" << endl;
01225 
01226   // Needed in case the singleton class is used as baseclass for
01227   // another singleton.
01228   if ( singleton )
01229     cpp << "  mSelf = this;" << endl;
01230 
01231   group = QString::null;
01232   for( e = entries.first(); e; e = entries.next() ) {
01233     if ( e->group() != group ) {
01234       if ( !group.isEmpty() ) cpp << endl;
01235       group = e->group();
01236       cpp << "  setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl;
01237     }
01238 
01239     QString key = paramString(e->key(), parameters);
01240     if ( !e->code().isEmpty())
01241     {
01242       cpp << e->code() << endl;
01243     }
01244     if ( e->type() == "Enum" ) {
01245       cpp << "  QValueList<KConfigSkeleton::ItemEnum::Choice> values"
01246           << e->name() << ";" << endl;
01247       QValueList<CfgEntry::Choice> choices = e->choices();
01248       QValueList<CfgEntry::Choice>::ConstIterator it;
01249       for( it = choices.begin(); it != choices.end(); ++it ) {
01250         cpp << "  {" << endl;
01251         cpp << "    KConfigSkeleton::ItemEnum::Choice choice;" << endl;
01252         cpp << "    choice.name = QString::fromLatin1( \"" << (*it).name << "\" );" << endl;
01253         if ( setUserTexts ) {
01254           if ( !(*it).label.isEmpty() )
01255             cpp << "    choice.label = i18n(" << quoteString((*it).label) << ");" << endl;
01256           if ( !(*it).whatsThis.isEmpty() )
01257             cpp << "    choice.whatsThis = i18n(" << quoteString((*it).whatsThis) << ");" << endl;
01258         }
01259         cpp << "    values" << e->name() << ".append( choice );" << endl;
01260         cpp << "  }" << endl;
01261       }
01262     }
01263     cpp << itemDeclaration(e);
01264     if (e->param().isEmpty())
01265     {
01266       // Normal case
01267       cpp << "  " << itemVar(e) << " = "
01268           << newItem( e->type(), e->name(), key, e->defaultValue() ) << endl;
01269 
01270       if ( !e->minValue().isEmpty() )
01271         cpp << "  " << itemVar(e) << "->setMinValue(" << e->minValue() << ");" << endl;
01272       if ( !e->maxValue().isEmpty() )
01273         cpp << "  " << itemVar(e) << "->setMaxValue(" << e->maxValue() << ");" << endl;
01274 
01275       if ( setUserTexts )
01276         cpp << userTextsFunctions( e );
01277 
01278       cpp << "  addItem( " << itemVar(e);
01279       QString quotedName = e->name();
01280       addQuotes( quotedName );
01281       if ( quotedName != key ) cpp << ", QString::fromLatin1( \"" << e->name() << "\" )";
01282       cpp << " );" << endl;
01283     }
01284     else
01285     {
01286       // Indexed
01287       for(int i = 0; i <= e->paramMax(); i++)
01288       {
01289         QString defaultStr;
01290         QString itemVarStr(itemVar(e)+QString("[%1]").arg(i));
01291         
01292         if ( !e->paramDefaultValue(i).isEmpty() )
01293           defaultStr = e->paramDefaultValue(i);
01294         else if ( !e->defaultValue().isEmpty() )
01295           defaultStr = paramString(e->defaultValue(), e, i);
01296         else
01297           defaultStr = defaultValue( e->type() );
01298 
01299         cpp << "  " << itemVarStr << " = "
01300             << newItem( e->type(), e->name(), paramString(key, e, i), defaultStr, QString("[%1]").arg(i) )
01301             << endl;
01302 
01303         if ( setUserTexts )
01304           cpp << userTextsFunctions( e, itemVarStr, e->paramName() );
01305 
01306         // Make mutators for enum parameters work by adding them with $(..) replaced by the 
01307         // param name. The check for isImmutable in the set* functions doesn't have the param 
01308         // name available, just the corresponding enum value (int), so we need to store the 
01309         // param names in a separate static list!.
01310         cpp << "  addItem( " << itemVarStr << ", QString::fromLatin1( \"";
01311         if ( e->paramType()=="Enum" )
01312           cpp << e->paramName().replace( "$("+e->param()+")", "%1").arg(e->paramValues()[i] );
01313         else
01314           cpp << e->paramName().replace( "$("+e->param()+")", "%1").arg(i);
01315         cpp << "\" ) );" << endl;
01316       }
01317     }
01318   }
01319 
01320   cpp << "}" << endl << endl;
01321 
01322   // Destructor
01323   cpp << className << "::~" << className << "()" << endl;
01324   cpp << "{" << endl;
01325   if ( singleton ) {
01326     cpp << "  if ( mSelf == this )" << endl;
01327     cpp << "    static" << className << "Deleter.setObject( mSelf, 0, false );" << endl;
01328   }
01329   cpp << "}" << endl << endl;
01330 
01331   implementation.close();
01332 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.3.90.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 30 10:09:38 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003