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.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 17 11:26:06 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003