00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00141 kdDebug() << " code: " << mCode << endl;
00142
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";
00480
00481 if (!param.isEmpty())
00482 {
00483
00484 paramName = name;
00485 name.replace("$("+param+")", QString::null);
00486
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";
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";
00631 }
00632 }
00633
00634 QString defaultValue( const QString &type )
00635 {
00636 if ( type == "String" ) return "\"\"";
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 "\"\"";
00653 else if ( type == "PathList" ) return "QStringList()";
00654 else if ( type == "Password" ) return "\"\"";
00655 else {
00656 kdWarning()<<"Error, kconfig_compiler doesn't support the \""<< type <<"\" type!"<<endl;
00657 return "QString";
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 ¶m = 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> ¶meters)
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
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;
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
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
00978 h << "class " << visibility << className << " : public " << inherits << endl;
00979 h << "{" << endl;
00980 h << " public:" << endl;
00981
00982
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
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
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
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
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
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
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
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
01154 if ( !memberVariables.isEmpty() && memberVariables != "private" ) {
01155 h << " " << memberVariables << ":" << endl;
01156 }
01157
01158
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
01222 for( it = includes.begin(); it != includes.end(); ++it ) {
01223 cpp << "#include <" << *it << ">" << endl;
01224 }
01225
01226
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
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
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
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
01305
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
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
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
01385
01386
01387
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
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 }