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->