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