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