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
00026 #include <QtCore/QCoreApplication>
00027 #include <QtCore/QFile>
00028 #include <QtCore/QFileInfo>
00029 #include <QtCore/QSettings>
00030 #include <QtCore/QTextStream>
00031 #include <QtXml/QDomAttr>
00032 #include <QtCore/QRegExp>
00033 #include <QtCore/QStringList>
00034
00035 #include <ostream>
00036 #include <iostream>
00037 #include <stdlib.h>
00038
00039
00040 static inline std::ostream &operator<<(std::ostream &o, const QString &str)
00041 {
00042 o << str.toLocal8Bit().constData();
00043 return o;
00044 }
00045
00046 static void parseArgs(const QStringList &args, QString &directory, QString &file1, QString &file2)
00047 {
00048 int fileCount = 0;
00049 directory = ".";
00050
00051 for (int i = 1; i < args.count(); ++i) {
00052 if (args.at(i) == "-d" || args.at(i) == "--directory") {
00053 if (i + 1 > args.count()) {
00054 std::cerr << qPrintable(args.at(i)) << " needs an argument" << std::endl;
00055 exit(1);
00056 }
00057 directory = args.at(++i);
00058 } else if (args.at(i).startsWith("-d")) {
00059 directory = args.at(i).mid(2);
00060 } else if (args.at(i) == "--help" || args.at(i) == "-h") {
00061 std::cout << "Options:" << std::endl;
00062 std::cout << " -L --license Display software license" << std::endl;
00063 std::cout << " -d, --directory <dir> Directory to generate files in [.]" << std::endl;
00064 std::cout << " -h, --help Display this help" << std::endl;
00065 std::cout << std::endl;
00066 std::cout << "Arguments:" << std::endl;
00067 std::cout << " file.kcfg Input kcfg XML file" << std::endl;
00068 std::cout << " file.kcfgc Code generation options file" << std::endl;
00069 exit(0);
00070 } else if (args.at(i) == "--license" || args.at(i) == "-L") {
00071 std::cout << "Copyright 2003 Cornelius Schumacher, Waldo Bastian, Zack Rusin," << std::endl;
00072 std::cout << " Reinhold Kainhofer, Duncan Mac-Vicar P., Harald Fernengel" << std::endl;
00073 std::cout << "This program comes with ABSOLUTELY NO WARRANTY." << std::endl;
00074 std::cout << "You may redistribute copies of this program" << std::endl;
00075 std::cout << "under the terms of the GNU Library Public License." << std::endl;
00076 std::cout << "For more information about these matters, see the file named COPYING." << std::endl;
00077 exit(0);
00078 } else if (args.at(i).startsWith('-')) {
00079 std::cerr << "Unknown option: " << qPrintable(args.at(i)) << std::endl;
00080 exit(1);
00081 } else if (fileCount == 0) {
00082 file1 = args.at(i);
00083 ++fileCount;
00084 } else if (fileCount == 1) {
00085 file2 = args.at(i);
00086 ++fileCount;
00087 } else {
00088 std::cerr << "Too many arguments" << std::endl;
00089 exit(1);
00090 }
00091 }
00092 if (fileCount < 2) {
00093 std::cerr << "Too few arguments" << std::endl;
00094 exit(1);
00095 }
00096 }
00097
00098 bool globalEnums;
00099 bool useEnumTypes;
00100 bool itemAccessors;
00101 bool dpointer;
00102 QStringList allNames;
00103 QRegExp *validNameRegexp;
00104 QString This;
00105 QString Const;
00106
00107 struct SignalArguments
00108 {
00109 QString type;
00110 QString variableName;
00111 };
00112
00113 class Signal {
00114 public:
00115 QString name;
00116 QString label;
00117 QList<SignalArguments> arguments;
00118 };
00119
00120 class CfgEntry
00121 {
00122 public:
00123 struct Choice
00124 {
00125 QString name;
00126 QString context;
00127 QString label;
00128 QString whatsThis;
00129 };
00130 class Choices
00131 {
00132 public:
00133 Choices() {}
00134 Choices( const QList<Choice> &d, const QString &n, const QString &p )
00135 : prefix(p), choices(d), mName(n)
00136 {
00137 int i = n.indexOf("::");
00138 if (i >= 0)
00139 mExternalQual = n.left(i + 2);
00140 }
00141 QString prefix;
00142 QList<Choice> choices;
00143 const QString& name() const { return mName; }
00144 const QString& externalQualifier() const { return mExternalQual; }
00145 bool external() const { return !mExternalQual.isEmpty(); }
00146 private:
00147 QString mName;
00148 QString mExternalQual;
00149 };
00150
00151 CfgEntry( const QString &group, const QString &type, const QString &key,
00152 const QString &name, const QString &context, const QString &label,
00153 const QString &whatsThis, const QString &code,
00154 const QString &defaultValue, const Choices &choices, const QList<Signal> signalList,
00155 bool hidden )
00156 : mGroup( group ), mType( type ), mKey( key ), mName( name ),
00157 mContext( context ), mLabel( label ), mWhatsThis( whatsThis ),
00158 mCode( code ), mDefaultValue( defaultValue ), mChoices( choices ),
00159 mSignalList(signalList), mHidden( hidden )
00160 {
00161 }
00162
00163 void setGroup( const QString &group ) { mGroup = group; }
00164 QString group() const { return mGroup; }
00165
00166 void setType( const QString &type ) { mType = type; }
00167 QString type() const { return mType; }
00168
00169 void setKey( const QString &key ) { mKey = key; }
00170 QString key() const { return mKey; }
00171
00172 void setName( const QString &name ) { mName = name; }
00173 QString name() const { return mName; }
00174
00175 void setContext( const QString &context ) { mContext = context; }
00176 QString context() const { return mContext; }
00177
00178 void setLabel( const QString &label ) { mLabel = label; }
00179 QString label() const { return mLabel; }
00180
00181 void setWhatsThis( const QString &whatsThis ) { mWhatsThis = whatsThis; }
00182 QString whatsThis() const { return mWhatsThis; }
00183
00184 void setDefaultValue( const QString &d ) { mDefaultValue = d; }
00185 QString defaultValue() const { return mDefaultValue; }
00186
00187 void setCode( const QString &d ) { mCode = d; }
00188 QString code() const { return mCode; }
00189
00190 void setMinValue( const QString &d ) { mMin = d; }
00191 QString minValue() const { return mMin; }
00192
00193 void setMaxValue( const QString &d ) { mMax = d; }
00194 QString maxValue() const { return mMax; }
00195
00196 void setParam( const QString &d ) { mParam = d; }
00197 QString param() const { return mParam; }
00198
00199 void setParamName( const QString &d ) { mParamName = d; }
00200 QString paramName() const { return mParamName; }
00201
00202 void setParamType( const QString &d ) { mParamType = d; }
00203 QString paramType() const { return mParamType; }
00204
00205 void setChoices( const QList<Choice> &d, const QString &n, const QString &p ) { mChoices = Choices( d, n, p ); }
00206 Choices choices() const { return mChoices; }
00207
00208 void setParamValues( const QStringList &d ) { mParamValues = d; }
00209 QStringList paramValues() const { return mParamValues; }
00210
00211 void setParamDefaultValues( const QStringList &d ) { mParamDefaultValues = d; }
00212 QString paramDefaultValue(int i) const { return mParamDefaultValues[i]; }
00213
00214 void setParamMax( int d ) { mParamMax = d; }
00215 int paramMax() const { return mParamMax; }
00216
00217 void setSignalList( const QList<Signal> &value ) { mSignalList = value; }
00218 QList<Signal> signalList() const { return mSignalList; }
00219
00220 bool hidden() const { return mHidden; }
00221
00222 void dump() const
00223 {
00224 std::cerr << "<entry>" << std::endl;
00225 std::cerr << " group: " << qPrintable(mGroup) << std::endl;
00226 std::cerr << " type: " << qPrintable(mType) << std::endl;
00227 std::cerr << " key: " << qPrintable(mKey) << std::endl;
00228 std::cerr << " name: " << qPrintable(mName) << std::endl;
00229 std::cerr << " context: " << qPrintable(mContext) << std::endl;
00230 std::cerr << " label: " << qPrintable(mLabel) << std::endl;
00231
00232 std::cerr << " code: " << qPrintable(mCode) << std::endl;
00233
00234
00235 if (!param().isEmpty())
00236 {
00237 std::cerr << " param name: "<< qPrintable(mParamName) << std::endl;
00238 std::cerr << " param type: "<< qPrintable(mParamType) << std::endl;
00239 std::cerr << " paramvalues: " << qPrintable(mParamValues.join(":")) << std::endl;
00240 }
00241 std::cerr << " default: " << qPrintable(mDefaultValue) << std::endl;
00242 std::cerr << " hidden: " << mHidden << std::endl;
00243 std::cerr << " min: " << qPrintable(mMin) << std::endl;
00244 std::cerr << " max: " << qPrintable(mMax) << std::endl;
00245 std::cerr << "</entry>" << std::endl;
00246 }
00247
00248 private:
00249 QString mGroup;
00250 QString mType;
00251 QString mKey;
00252 QString mName;
00253 QString mContext;
00254 QString mLabel;
00255 QString mWhatsThis;
00256 QString mCode;
00257 QString mDefaultValue;
00258 QString mParam;
00259 QString mParamName;
00260 QString mParamType;
00261 Choices mChoices;
00262 QList<Signal> mSignalList;
00263 QStringList mParamValues;
00264 QStringList mParamDefaultValues;
00265 int mParamMax;
00266 bool mHidden;
00267 QString mMin;
00268 QString mMax;
00269 };
00270
00271 class Param {
00272 public:
00273 QString name;
00274 QString type;
00275 };
00276
00277
00278
00279
00280 static QString varName(const QString &n)
00281 {
00282 QString result;
00283 if ( !dpointer ) {
00284 result = 'm'+n;
00285 result[1] = result[1].toUpper();
00286 }
00287 else {
00288 result = n;
00289 result[0] = result[0].toLower();
00290 }
00291 return result;
00292 }
00293
00294 static QString varPath(const QString &n)
00295 {
00296 QString result;
00297 if ( dpointer ) {
00298 result = "d->"+varName(n);
00299 }
00300 else {
00301 result = varName(n);
00302 }
00303 return result;
00304 }
00305
00306 static QString enumName(const QString &n)
00307 {
00308 QString result = "Enum" + n;
00309 result[4] = result[4].toUpper();
00310 return result;
00311 }
00312
00313 static QString enumName(const QString &n, const CfgEntry::Choices &c)
00314 {
00315 QString result = c.name();
00316 if ( result.isEmpty() )
00317 {
00318 result = "Enum" + n;
00319 result[4] = result[4].toUpper();
00320 }
00321 return result;
00322 }
00323
00324 static QString enumType(const CfgEntry *e)
00325 {
00326 QString result = e->choices().name();
00327 if ( result.isEmpty() )
00328 {
00329 result = "Enum" + e->name() + "::type";
00330 result[4] = result[4].toUpper();
00331 }
00332 return result;
00333 }
00334
00335 static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
00336 {
00337 QString result = c.name();
00338 if ( result.isEmpty() )
00339 {
00340 result = "Enum" + n + "::";
00341 result[4] = result[4].toUpper();
00342 }
00343 else if ( c.external() )
00344 result = c.externalQualifier();
00345 else
00346 result.clear();
00347 return result;
00348 }
00349
00350 static QString setFunction(const QString &n, const QString &className = QString())
00351 {
00352 QString result = "set"+n;
00353 result[3] = result[3].toUpper();
00354
00355 if ( !className.isEmpty() )
00356 result = className + "::" + result;
00357 return result;
00358 }
00359
00360
00361 static QString getFunction(const QString &n, const QString &className = QString())
00362 {
00363 QString result = n;
00364 result[0] = result[0].toLower();
00365
00366 if ( !className.isEmpty() )
00367 result = className + "::" + result;
00368 return result;
00369 }
00370
00371
00372 static void addQuotes( QString &s )
00373 {
00374 if ( !s.startsWith( '"' ) ) s.prepend( '"' );
00375 if ( !s.endsWith( '"' ) ) s.append( '"' );
00376 }
00377
00378 static QString quoteString( const QString &s )
00379 {
00380 QString r = s;
00381 r.replace( "\\", "\\\\" );
00382 r.replace( "\"", "\\\"" );
00383 r.remove( "\r" );
00384 r.replace( "\n", "\\n\"\n\"" );
00385 return "\"" + r + "\"";
00386 }
00387
00388 static QString literalString( const QString &s )
00389 {
00390 bool isAscii = true;
00391 for(int i = s.length(); i--;)
00392 if (s[i].unicode() > 127) isAscii = false;
00393
00394 if (isAscii)
00395 return "QLatin1String( " + quoteString(s) + " )";
00396 else
00397 return "QString::fromUtf8( " + quoteString(s) + " )";
00398 }
00399
00400 static QString dumpNode(const QDomNode &node)
00401 {
00402 QString msg;
00403 QTextStream s(&msg, QIODevice::WriteOnly );
00404 node.save(s, 0);
00405
00406 msg = msg.simplified();
00407 if (msg.length() > 40)
00408 return msg.left(37)+"...";
00409 return msg;
00410 }
00411
00412 static QString filenameOnly(const QString& path)
00413 {
00414 int i = path.lastIndexOf(QRegExp("[/\\]"));
00415 if (i >= 0)
00416 return path.mid(i+1);
00417 return path;
00418 }
00419
00420 static QString signalEnumName(const QString &signalName)
00421 {
00422 QString result;
00423 result = "signal" + signalName;
00424 result[6] = result[6].toUpper();
00425
00426 return result;
00427 }
00428
00429 static void preProcessDefault( QString &defaultValue, const QString &name,
00430 const QString &type,
00431 const CfgEntry::Choices &choices,
00432 QString &code )
00433 {
00434 if ( type == "String" && !defaultValue.isEmpty() ) {
00435 defaultValue = literalString(defaultValue);
00436
00437 } else if ( type == "Path" && !defaultValue.isEmpty() ) {
00438 defaultValue = literalString( defaultValue );
00439
00440 } else if ( (type == "StringList" || type == "PathList") && !defaultValue.isEmpty() ) {
00441 QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
00442 if (!code.isEmpty())
00443 cpp << endl;
00444
00445 cpp << " QStringList default" << name << ";" << endl;
00446 const QStringList defaults = defaultValue.split( "," );
00447 QStringList::ConstIterator it;
00448 for( it = defaults.begin(); it != defaults.end(); ++it ) {
00449 cpp << " default" << name << ".append( QString::fromUtf8( \"" << *it << "\" ) );"
00450 << endl;
00451 }
00452 defaultValue = "default" + name;
00453
00454 } else if ( type == "Color" && !defaultValue.isEmpty() ) {
00455 QRegExp colorRe("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?");
00456 if (colorRe.exactMatch(defaultValue))
00457 {
00458 defaultValue = "QColor( " + defaultValue + " )";
00459 }
00460 else
00461 {
00462 defaultValue = "QColor( \"" + defaultValue + "\" )";
00463 }
00464
00465 } else if ( type == "Enum" ) {
00466 QList<CfgEntry::Choice>::ConstIterator it;
00467 for( it = choices.choices.begin(); it != choices.choices.end(); ++it ) {
00468 if ( (*it).name == defaultValue ) {
00469 if ( globalEnums && choices.name().isEmpty() )
00470 defaultValue.prepend( choices.prefix );
00471 else
00472 defaultValue.prepend( enumTypeQualifier(name, choices) + choices.prefix );
00473 break;
00474 }
00475 }
00476
00477 } else if ( type == "IntList" ) {
00478 QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
00479 if (!code.isEmpty())
00480 cpp << endl;
00481
00482 cpp << " QList<int> default" << name << ";" << endl;
00483 if (!defaultValue.isEmpty())
00484 {
00485 QStringList defaults = defaultValue.split( "," );
00486 QStringList::ConstIterator it;
00487 for( it = defaults.begin(); it != defaults.end(); ++it ) {
00488 cpp << " default" << name << ".append( " << *it << " );"
00489 << endl;
00490 }
00491 }
00492 defaultValue = "default" + name;
00493 }
00494 }
00495
00496
00497 CfgEntry *parseEntry( const QString &group, const QDomElement &element )
00498 {
00499 bool defaultCode = false;
00500 QString type = element.attribute( "type" );
00501 QString name = element.attribute( "name" );
00502 QString key = element.attribute( "key" );
00503 QString hidden = element.attribute( "hidden" );
00504 QString context = element.attribute( "context" );
00505 QString label;
00506 QString whatsThis;
00507 QString defaultValue;
00508 QString code;
00509 QString param;
00510 QString paramName;
00511 QString paramType;
00512 CfgEntry::Choices choices;
00513 QList<Signal> signalList;
00514 QStringList paramValues;
00515 QStringList paramDefaultValues;
00516 QString minValue;
00517 QString maxValue;
00518 int paramMax = 0;
00519
00520 for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
00521 QString tag = e.tagName();
00522 if ( tag == "label" ) {
00523 label = e.text();
00524 context = e.attribute( "context" );
00525 }
00526 else if ( tag == "whatsthis" ) {
00527 whatsThis = e.text();
00528 context = e.attribute( "context" );
00529 }
00530 else if ( tag == "min" ) minValue = e.text();
00531 else if ( tag == "max" ) maxValue = e.text();
00532 else if ( tag == "code" ) code = e.text();
00533 else if ( tag == "parameter" )
00534 {
00535 param = e.attribute( "name" );
00536 paramType = e.attribute( "type" );
00537 if ( param.isEmpty() ) {
00538 std::cerr << "Parameter must have a name: " << qPrintable(dumpNode(e)) << std::endl;
00539 return 0;
00540 }
00541 if ( paramType.isEmpty() ) {
00542 std::cerr << "Parameter must have a type: " << qPrintable(dumpNode(e)) << std::endl;
00543 return 0;
00544 }
00545 if ((paramType == "Int") || (paramType == "UInt"))
00546 {
00547 bool ok;
00548 paramMax = e.attribute("max").toInt(&ok);
00549 if (!ok)
00550 {
00551 std::cerr << "Integer parameter must have a maximum (e.g. max=\"0\"): "
00552 << qPrintable(dumpNode(e)) << std::endl;
00553 return 0;
00554 }
00555 }
00556 else if (paramType == "Enum")
00557 {
00558 for ( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
00559 if (e2.tagName() == "values")
00560 {
00561 for ( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) {
00562 if (e3.tagName() == "value")
00563 {
00564 paramValues.append( e3.text() );
00565 }
00566 }
00567 break;
00568 }
00569 }
00570 if (paramValues.isEmpty())
00571 {
00572 std::cerr << "No values specified for parameter '" << qPrintable(param)
00573 << "'." << std::endl;
00574 return 0;
00575 }
00576 paramMax = paramValues.count()-1;
00577 }
00578 else
00579 {
00580 std::cerr << "Parameter '" << qPrintable(param) << "' has type " << qPrintable(paramType)
00581 << " but must be of type int, uint or Enum." << std::endl;
00582 return 0;
00583 }
00584 }
00585 else if ( tag == "default" )
00586 {
00587 if (e.attribute("param").isEmpty())
00588 {
00589 defaultValue = e.text();
00590 if (e.attribute( "code" ) == "true")
00591 defaultCode = true;
00592 }
00593 }
00594 else if ( tag == "choices" ) {
00595 QString name = e.attribute( "name" );
00596 QString prefix = e.attribute( "prefix" );
00597 QList<CfgEntry::Choice> chlist;
00598 for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
00599 if ( e2.tagName() == "choice" ) {
00600 CfgEntry::Choice choice;
00601 choice.name = e2.attribute( "name" );
00602 if ( choice.name.isEmpty() ) {
00603 std::cerr << "Tag <choice> requires attribute 'name'." << std::endl;
00604 }
00605 for( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) {
00606 if ( e3.tagName() == "label" ) {
00607 choice.label = e3.text();
00608 choice.context = e3.attribute( "context" );
00609 }
00610 if ( e3.tagName() == "whatsthis" ) {
00611 choice.whatsThis = e3.text();
00612 choice.context = e3.attribute( "context" );
00613 }
00614 }
00615 chlist.append( choice );
00616 }
00617 }
00618 choices = CfgEntry::Choices( chlist, name, prefix );
00619 }
00620 else if ( tag == "emit" ) {
00621 QDomNode signalNode;
00622 Signal signal;
00623 signal.name = e.attribute( "signal" );
00624 signalList.append( signal);
00625 }
00626 }
00627
00628
00629 bool nameIsEmpty = name.isEmpty();
00630 if ( nameIsEmpty && key.isEmpty() ) {
00631 std::cerr << "Entry must have a name or a key: " << qPrintable(dumpNode(element)) << std::endl;
00632 return 0;
00633 }
00634
00635 if ( key.isEmpty() ) {
00636 key = name;
00637 }
00638
00639 if ( nameIsEmpty ) {
00640 name = key;
00641 name.remove( ' ' );
00642 } else if ( name.contains( ' ' ) ) {
00643 std::cout<<"Entry '"<<qPrintable(name)<<"' contains spaces! <name> elements can not contain spaces!"<<std::endl;
00644 name.remove( ' ' );
00645 }
00646
00647 if (name.contains("$("))
00648 {
00649 if (param.isEmpty())
00650 {
00651 std::cerr << "Name may not be parameterized: " << qPrintable(name) << std::endl;
00652 return 0;
00653 }
00654 }
00655 else
00656 {
00657 if (!param.isEmpty())
00658 {
00659 std::cerr << "Name must contain '$(" << qPrintable(param) << ")': " << qPrintable(name) << std::endl;
00660 return 0;
00661 }
00662 }
00663
00664 if ( label.isEmpty() ) {
00665 label = key;
00666 }
00667
00668 if ( type.isEmpty() ) type = "String";
00669
00670 if (!param.isEmpty())
00671 {
00672
00673 paramName = name;
00674 name.replace("$("+param+')', QString());
00675
00676 for(int i = 0; i <= paramMax; i++)
00677 {
00678 paramDefaultValues.append(QString());
00679 }
00680
00681 for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
00682 QString tag = e.tagName();
00683 if ( tag == "default" )
00684 {
00685 QString index = e.attribute("param");
00686 if (index.isEmpty())
00687 continue;
00688
00689 bool ok;
00690 int i = index.toInt(&ok);
00691 if (!ok)
00692 {
00693 i = paramValues.indexOf(index);
00694 if (i == -1)
00695 {
00696 std::cerr << "Index '" << qPrintable(index) << "' for default value is unknown." << std::endl;
00697 return 0;
00698 }
00699 }
00700
00701 if ((i < 0) || (i > paramMax))
00702 {
00703 std::cerr << "Index '" << i << "' for default value is out of range [0, "<< paramMax<<"]." << std::endl;
00704 return 0;
00705 }
00706
00707 QString tmpDefaultValue = e.text();
00708
00709 if (e.attribute( "code" ) != "true")
00710 preProcessDefault(tmpDefaultValue, name, type, choices, code);
00711
00712 paramDefaultValues[i] = tmpDefaultValue;
00713 }
00714 }
00715 }
00716
00717 if (!validNameRegexp->exactMatch(name))
00718 {
00719 if (nameIsEmpty)
00720 std::cerr << "The key '" << qPrintable(key) << "' can not be used as name for the entry because "
00721 "it is not a valid name. You need to specify a valid name for this entry." << std::endl;
00722 else
00723 std::cerr << "The name '" << qPrintable(name) << "' is not a valid name for an entry." << std::endl;
00724 return 0;
00725 }
00726
00727 if (allNames.contains(name))
00728 {
00729 if (nameIsEmpty)
00730 std::cerr << "The key '" << qPrintable(key) << "' can not be used as name for the entry because "
00731 "it does not result in a unique name. You need to specify a unique name for this entry." << std::endl;
00732 else
00733 std::cerr << "The name '" << qPrintable(name) << "' is not unique." << std::endl;
00734 return 0;
00735 }
00736 allNames.append(name);
00737
00738 if (!defaultCode)
00739 {
00740 preProcessDefault(defaultValue, name, type, choices, code);
00741 }
00742
00743 CfgEntry *result = new CfgEntry( group, type, key, name, context, label, whatsThis,
00744 code, defaultValue, choices, signalList,
00745 hidden == "true" );
00746 if (!param.isEmpty())
00747 {
00748 result->setParam(param);
00749 result->setParamName(paramName);
00750 result->setParamType(paramType);
00751 result->setParamValues(paramValues);
00752 result->setParamDefaultValues(paramDefaultValues);
00753 result->setParamMax(paramMax);
00754 }
00755 result->setMinValue(minValue);
00756 result->setMaxValue(maxValue);
00757
00758 return result;
00759 }
00760
00764 QString param( const QString &type )
00765 {
00766 if ( type == "String" ) return "const QString &";
00767 else if ( type == "StringList" ) return "const QStringList &";
00768 else if ( type == "Font" ) return "const QFont &";
00769 else if ( type == "Rect" ) return "const QRect &";
00770 else if ( type == "Size" ) return "const QSize &";
00771 else if ( type == "Color" ) return "const QColor &";
00772 else if ( type == "Point" ) return "const QPoint &";
00773 else if ( type == "Int" ) return "int";
00774 else if ( type == "UInt" ) return "uint";
00775 else if ( type == "Bool" ) return "bool";
00776 else if ( type == "Double" ) return "double";
00777 else if ( type == "DateTime" ) return "const QDateTime &";
00778 else if ( type == "LongLong" ) return "qint64";
00779 else if ( type == "ULongLong" ) return "quint64";
00780 else if ( type == "IntList" ) return "const QList<int> &";
00781 else if ( type == "Enum" ) return "int";
00782 else if ( type == "Path" ) return "const QString &";
00783 else if ( type == "PathList" ) return "const QStringList &";
00784 else if ( type == "Password" ) return "const QString &";
00785 else if ( type == "Url" ) return "const KUrl &";
00786 else if ( type == "UrlList" ) return "const KUrl::List &";
00787 else {
00788 std::cerr <<"kconfig_compiler does not support type \""<< type <<"\""<<std::endl;
00789 return "QString";
00790 }
00791 }
00792
00796 QString cppType( const QString &type )
00797 {
00798 if ( type == "String" ) return "QString";
00799 else if ( type == "StringList" ) return "QStringList";
00800 else if ( type == "Font" ) return "QFont";
00801 else if ( type == "Rect" ) return "QRect";
00802 else if ( type == "Size" ) return "QSize";
00803 else if ( type == "Color" ) return "QColor";
00804 else if ( type == "Point" ) return "QPoint";
00805 else if ( type == "Int" ) return "int";
00806 else if ( type == "UInt" ) return "uint";
00807 else if ( type == "Bool" ) return "bool";
00808 else if ( type == "Double" ) return "double";
00809 else if ( type == "DateTime" ) return "QDateTime";
00810 else if ( type == "LongLong" ) return "qint64";
00811 else if ( type == "ULongLong" ) return "quint64";
00812 else if ( type == "IntList" ) return "QList<int>";
00813 else if ( type == "Enum" ) return "int";
00814 else if ( type == "Path" ) return "QString";
00815 else if ( type == "PathList" ) return "QStringList";
00816 else if ( type == "Password" ) return "QString";
00817 else if ( type == "Url" ) return "KUrl";
00818 else if ( type == "UrlList" ) return "KUrl::List";
00819 else {
00820 std::cerr<<"kconfig_compiler does not support type \""<< type <<"\""<<std::endl;
00821 return "QString";
00822 }
00823 }
00824
00825 QString defaultValue( const QString &type )
00826 {
00827 if ( type == "String" ) return "\"\"";
00828 else if ( type == "StringList" ) return "QStringList()";
00829 else if ( type == "Font" ) return "QFont()";
00830 else if ( type == "Rect" ) return "QRect()";
00831 else if ( type == "Size" ) return "QSize()";
00832 else if ( type == "Color" ) return "QColor(128, 128, 128)";
00833 else if ( type == "Point" ) return "QPoint()";
00834 else if ( type == "Int" ) return "0";
00835 else if ( type == "UInt" ) return "0";
00836 else if ( type == "Bool" ) return "false";
00837 else if ( type == "Double" ) return "0.0";
00838 else if ( type == "DateTime" ) return "QDateTime()";
00839 else if ( type == "LongLong" ) return "0";
00840 else if ( type == "ULongLong" ) return "0";
00841 else if ( type == "IntList" ) return "QList<int>()";
00842 else if ( type == "Enum" ) return "0";
00843 else if ( type == "Path" ) return "\"\"";
00844 else if ( type == "PathList" ) return "QStringList()";
00845 else if ( type == "Password" ) return "\"\"";
00846 else if ( type == "Url" ) return "KUrl()";
00847 else if ( type == "UrlList" ) return "KUrl::List()";
00848 else {
00849 std::cerr<<"Error, kconfig_compiler does not support the \""<< type <<"\" type!"<<std::endl;
00850 return "QString";
00851 }
00852 }
00853
00854 QString itemType( const QString &type )
00855 {
00856 QString t;
00857
00858 t = type;
00859 t.replace( 0, 1, t.left( 1 ).toUpper() );
00860
00861 return t;
00862 }
00863
00864 static QString itemDeclaration(const CfgEntry *e)
00865 {
00866 if (itemAccessors)
00867 return QString();
00868
00869 QString fCap = e->name();
00870 fCap[0] = fCap[0].toUpper();
00871 return " KConfigSkeleton::Item"+itemType( e->type() ) +
00872 " *item" + fCap +
00873 ( (!e->param().isEmpty())?(QString("[%1]").arg(e->paramMax()+1)) : QString()) +
00874 ";\n";
00875 }
00876
00877
00878
00879
00880 static QString itemVar(const CfgEntry *e)
00881 {
00882 QString result;
00883 if (itemAccessors)
00884 {
00885 if ( !dpointer )
00886 {
00887 result = 'm' + e->name() + "Item";
00888 result[1] = result[1].toUpper();
00889 }
00890 else
00891 {
00892 result = e->name() + "Item";
00893 result[0] = result[0].toLower();
00894 }
00895 }
00896 else
00897 {
00898 result = "item" + e->name();
00899 result[4] = result[4].toUpper();
00900 }
00901 return result;
00902 }
00903
00904 static QString itemPath(const CfgEntry *e)
00905 {
00906 QString result;
00907 if ( dpointer ) {
00908 result = "d->"+itemVar(e);
00909 }
00910 else {
00911 result = itemVar(e);
00912 }
00913 return result;
00914 }
00915
00916 QString newItem( const QString &type, const QString &name, const QString &key,
00917 const QString &defaultValue, const QString ¶m = QString())
00918 {
00919 QString t = "new KConfigSkeleton::Item" + itemType( type ) +
00920 "( currentGroup(), " + key + ", " + varPath( name ) + param;
00921 if ( type == "Enum" ) t += ", values" + name;
00922 if ( !defaultValue.isEmpty() ) {
00923 t += ", ";
00924 if ( type == "String" ) t += defaultValue;
00925 else t+= defaultValue;
00926 }
00927 t += " );";
00928
00929 return t;
00930 }
00931
00932 QString paramString(const QString &s, const CfgEntry *e, int i)
00933 {
00934 QString result = s;
00935 QString needle = "$("+e->param()+')';
00936 if (result.contains(needle))
00937 {
00938 QString tmp;
00939 if (e->paramType() == "Enum")
00940 {
00941 tmp = e->paramValues()[i];
00942 }
00943 else
00944 {
00945 tmp = QString::number(i);
00946 }
00947
00948 result.replace(needle, tmp);
00949 }
00950 return result;
00951 }
00952
00953 QString paramString(const QString &group, const QList<Param> ¶meters)
00954 {
00955 QString paramString = group;
00956 QString arguments;
00957 int i = 1;
00958 for (QList<Param>::ConstIterator it = parameters.begin();
00959 it != parameters.end(); ++it)
00960 {
00961 if (paramString.contains("$("+(*it).name+')'))
00962 {
00963 QString tmp;
00964 tmp.sprintf("%%%d", i++);
00965 paramString.replace("$("+(*it).name+')', tmp);
00966 arguments += ".arg( mParam"+(*it).name+" )";
00967 }
00968 }
00969 if (arguments.isEmpty())
00970 return "QLatin1String( \""+group+"\" )";
00971
00972 return "QString( QLatin1String( \""+paramString+"\" ) )"+arguments;
00973 }
00974
00975
00976 QString userTextsFunctions( CfgEntry *e, QString itemVarStr=QString(), QString i=QString() )
00977 {
00978 QString txt;
00979 if (itemVarStr.isNull()) itemVarStr=itemPath(e);
00980 if ( !e->label().isEmpty() ) {
00981 txt += " " + itemVarStr + "->setLabel( ";
00982 if ( !e->context().isEmpty() )
00983 txt += "i18nc(" + quoteString(e->context()) + ", ";
00984 else
00985 txt += "i18n(";
00986 if ( !e->param().isEmpty() )
00987 txt += quoteString(e->label().replace("$("+e->param()+')', i));
00988 else
00989 txt+= quoteString(e->label());
00990 txt+= ") );\n";
00991 }
00992 if ( !e->whatsThis().isEmpty() ) {
00993 txt += " " + itemVarStr + "->setWhatsThis( ";
00994 if ( !e->context().isEmpty() )
00995 txt += "i18nc(" + quoteString(e->context()) + ", ";
00996 else
00997 txt += "i18n(";
00998 if ( !e->param().isEmpty() )
00999 txt += quoteString(e->whatsThis().replace("$("+e->param()+')', i));
01000 else
01001 txt+= quoteString(e->whatsThis());
01002 txt+=") );\n";
01003 }
01004 return txt;
01005 }
01006
01007
01008
01009
01010 QString memberAccessorBody( CfgEntry *e )
01011 {
01012 QString result;
01013 QTextStream out(&result, QIODevice::WriteOnly);
01014 QString n = e->name();
01015 QString t = e->type();
01016 bool useEnumType = useEnumTypes && t == "Enum";
01017
01018 out << "return ";
01019 if (useEnumType)
01020 out << "static_cast<" << enumType(e) << ">(";
01021 out << This << varPath(n);
01022 if (!e->param().isEmpty())
01023 out << "[i]";
01024 if (useEnumType)
01025 out << ")";
01026 out << ";" << endl;
01027
01028 return result;
01029 }
01030
01031
01032
01033
01034 QString memberMutatorBody( CfgEntry *e )
01035 {
01036 QString result;
01037 QTextStream out(&result, QIODevice::WriteOnly);
01038 QString n = e->name();
01039 QString t = e->type();
01040
01041 if (!e->minValue().isEmpty())
01042 {
01043 out << "if (v < " << e->minValue() << ")" << endl;
01044 out << "{" << endl;
01045 out << " kDebug() << \"" << setFunction(n);
01046 out << ": value \" << v << \" is less than the minimum value of ";
01047 out << e->minValue()<< "\" << endl;" << endl;
01048 out << " v = " << e->minValue() << ";" << endl;
01049 out << "}" << endl;
01050 }
01051
01052 if (!e->maxValue().isEmpty())
01053 {
01054 out << endl << "if (v > " << e->maxValue() << ")" << endl;
01055 out << "{" << endl;
01056 out << " kDebug() << \"" << setFunction(n);
01057 out << ": value \" << v << \" is greater than the maximum value of ";
01058 out << e->maxValue()<< "\" << endl;" << endl;
01059 out << " v = " << e->maxValue() << ";" << endl;
01060 out << "}" << endl << endl;
01061 }
01062
01063 out << "if (!" << This << "isImmutable( QString::fromLatin1 ( \"";
01064 if (!e->param().isEmpty())
01065 {
01066 out << e->paramName().replace("$("+e->param()+")", "%1") << "\" ).arg( ";
01067 if ( e->paramType() == "Enum" ) {
01068 out << "QLatin1String( ";
01069
01070 if (globalEnums)
01071 out << enumName(e->param()) << "ToString[i]";
01072 else
01073 out << enumName(e->param()) << "::enumToString[i]";
01074
01075 out << " )";
01076 }
01077 else
01078 {
01079 out << "i";
01080 }
01081 out << " )";
01082 }
01083 else
01084 {
01085 out << n << "\" )";
01086 }
01087 out << " ))" << (!e->signalList().empty() ? " {" : "") << endl;
01088 out << " " << This << varPath(n);
01089 if (!e->param().isEmpty())
01090 out << "[i]";
01091 out << " = v;" << endl;
01092
01093 if ( !e->signalList().empty() ) {
01094 foreach(const Signal &signal, e->signalList()) {
01095 out << " " << This << varPath("settingsChanged") << " |= " << signalEnumName(signal.name) << ";" << endl;
01096 }
01097 out << "}" << endl;
01098 }
01099
01100 return result;
01101 }
01102
01103
01104
01105
01106 QString itemAccessorBody( CfgEntry *e )
01107 {
01108 QString result;
01109 QTextStream out(&result, QIODevice::WriteOnly);
01110
01111 out << "return " << itemPath(e);
01112 if (!e->param().isEmpty()) out << "[i]";
01113 out << ";" << endl;
01114
01115 return result;
01116 }
01117
01118
01119 QString indent(QString text, int spaces)
01120 {
01121 QString result;
01122 QTextStream out(&result, QIODevice::WriteOnly);
01123 QTextStream in(&text, QIODevice::ReadOnly);
01124 QString currLine;
01125 while ( !in.atEnd() )
01126 {
01127 currLine = in.readLine();
01128 if (!currLine.isEmpty())
01129 for (int i=0; i < spaces; i++)
01130 out << " ";
01131 out << currLine << endl;
01132 }
01133 return result;
01134 }
01135
01136
01137 int main( int argc, char **argv )
01138 {
01139 QCoreApplication app(argc, argv);
01140
01141 validNameRegexp = new QRegExp("[a-zA-Z_][a-zA-Z0-9_]*");
01142
01143 QString directoryName, inputFilename, codegenFilename;
01144 parseArgs(app.arguments(), directoryName, inputFilename, codegenFilename);
01145
01146 QString baseDir = directoryName;
01147 #ifdef Q_OS_WIN
01148 if (!baseDir.endsWith('/') && !baseDir.endsWith('\\'))
01149 #else
01150 if (!baseDir.endsWith('/'))
01151 #endif
01152 baseDir.append("/");
01153
01154 if (!codegenFilename.endsWith(".kcfgc"))
01155 {
01156 std::cerr << "Codegen options file must have extension .kcfgc" << std::endl;
01157 return 1;
01158 }
01159 QString baseName = QFileInfo(codegenFilename).fileName();
01160 baseName = baseName.left(baseName.length() - 6);
01161
01162 QSettings codegenConfig(codegenFilename, QSettings::IniFormat);
01163
01164 QString nameSpace = codegenConfig.value("NameSpace").toString();
01165 QString className = codegenConfig.value("ClassName").toString();
01166 QString inherits = codegenConfig.value("Inherits").toString();
01167 QString visibility = codegenConfig.value("Visibility").toString();
01168 if (!visibility.isEmpty()) visibility+=' ';
01169 bool forceStringFilename = codegenConfig.value("ForceStringFilename", false).toBool();
01170 bool singleton = codegenConfig.value("Singleton", false).toBool();
01171 bool staticAccessors = singleton;
01172
01173 bool customAddons = codegenConfig.value("CustomAdditions", false).toBool();
01174 QString memberVariables = codegenConfig.value("MemberVariables").toString();
01175 QStringList headerIncludes = codegenConfig.value("IncludeFiles", QStringList()).toStringList();
01176 QStringList sourceIncludes = codegenConfig.value("SourceIncludeFiles", QStringList()).toStringList();
01177 QStringList mutators = codegenConfig.value("Mutators", QStringList()).toStringList();
01178 bool allMutators = false;
01179 if ((mutators.count() == 1) && (mutators.at(0).toLower() == "true"))
01180 allMutators = true;
01181 itemAccessors = codegenConfig.value("ItemAccessors", false).toBool();
01182 bool setUserTexts = codegenConfig.value("SetUserTexts", false).toBool();
01183
01184 globalEnums = codegenConfig.value("GlobalEnums", false).toBool();
01185 useEnumTypes = codegenConfig.value("UseEnumTypes", false).toBool();
01186
01187 dpointer = (memberVariables == "dpointer");
01188
01189 QFile input( inputFilename );
01190
01191 QDomDocument doc;
01192 QString errorMsg;
01193 int errorRow;
01194 int errorCol;
01195 if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
01196 std::cerr << "Unable to load document." << std::endl;
01197 std::cerr << "Parse error in " << inputFilename << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << std::endl;
01198 return 1;
01199 }
01200
01201 QDomElement cfgElement = doc.documentElement();
01202
01203 if ( cfgElement.isNull() ) {
01204 std::cerr << "No document in kcfg file" << std::endl;
01205 return 1;
01206 }
01207
01208 QString cfgFileName;
01209 bool cfgFileNameArg = false;
01210 QList<Param> parameters;
01211 QList<Signal> signalList;
01212 QStringList includes;
01213 bool hasSignals = false;
01214
01215 QList<CfgEntry*> entries;
01216
01217 for ( QDomElement e = cfgElement.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
01218 QString tag = e.tagName();
01219
01220 if ( tag == "include" ) {
01221 QString includeFile = e.text();
01222 if (!includeFile.isEmpty())
01223 includes.append(includeFile);
01224
01225 } else if ( tag == "kcfgfile" ) {
01226 cfgFileName = e.attribute( "name" );
01227 cfgFileNameArg = e.attribute( "arg" ).toLower() == "true";
01228 for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
01229 if ( e2.tagName() == "parameter" ) {
01230 Param p;
01231 p.name = e2.attribute( "name" );
01232 p.type = e2.attribute( "type" );
01233 if (p.type.isEmpty())
01234 p.type = "String";
01235 parameters.append( p );
01236 }
01237 }
01238
01239 } else if ( tag == "group" ) {
01240 QString group = e.attribute( "name" );
01241 if ( group.isEmpty() ) {
01242 std::cerr << "Group without name" << std::endl;
01243 return 1;
01244 }
01245 for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
01246 if ( e2.tagName() != "entry" ) continue;
01247 CfgEntry *entry = parseEntry( group, e2 );
01248 if ( entry ) entries.append( entry );
01249 else {
01250 std::cerr << "Can not parse entry." << std::endl;
01251 return 1;
01252 }
01253 }
01254 }
01255 else if ( tag == "signal" ) {
01256 QString signalName = e.attribute( "name" );
01257 if ( signalName.isEmpty() ) {
01258 std::cerr << "Signal without name." << std::endl;
01259 return 1;
01260 }
01261 Signal theSignal;
01262 theSignal.name = signalName;
01263
01264 for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
01265 if ( e2.tagName() == "argument") {
01266 SignalArguments argument;
01267 argument.type = e2.attribute("type");
01268 if ( argument.type.isEmpty() ) {
01269 std::cerr << "Signal argument without type." << std::endl;
01270 return 1;
01271 }
01272 argument.variableName = e2.text();
01273 theSignal.arguments.append(argument);
01274 }
01275 else if( e2.tagName() == "label") {
01276 theSignal.label = e2.text();
01277 }
01278 }
01279 signalList.append(theSignal);
01280 }
01281 }
01282
01283 if ( inherits.isEmpty() ) inherits = "KConfigSkeleton";
01284
01285 if ( className.isEmpty() ) {
01286 std::cerr << "Class name missing" << std::endl;
01287 return 1;
01288 }
01289
01290 if ( singleton && !parameters.isEmpty() ) {
01291 std::cerr << "Singleton class can not have parameters" << std::endl;
01292 return 1;
01293 }
01294
01295 if ( !cfgFileName.isEmpty() && cfgFileNameArg)
01296 {
01297 std::cerr << "Having both a fixed filename and a filename as argument is not possible." << std::endl;
01298 return 1;
01299 }
01300
01301 if ( entries.isEmpty() ) {
01302 std::cerr << "No entries." << std::endl;
01303 }
01304
01305 #if 0
01306 CfgEntry *cfg;
01307 for( cfg = entries.first(); cfg; cfg = entries.next() ) {
01308 cfg->dump();
01309 }
01310 #endif
01311
01312 hasSignals = !signalList.empty();
01313 QString headerFileName = baseName + ".h";
01314 QString implementationFileName = baseName + ".cpp";
01315 QString mocFileName = baseName + ".moc";
01316 QString cppPreamble;
01317
01318 QFile header( baseDir + headerFileName );
01319 if ( !header.open( QIODevice::WriteOnly ) ) {
01320 std::cerr << "Can not open '" << baseDir << headerFileName << "for writing." << std::endl;
01321 return 1;
01322 }
01323
01324 QTextStream h( &header );
01325
01326 h << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
01327 h << "// All changes you do to this file will be lost." << endl;
01328
01329 h << "#ifndef " << ( !nameSpace.isEmpty() ? nameSpace.toUpper() + '_' : "" )
01330 << className.toUpper() << "_H" << endl;
01331 h << "#define " << ( !nameSpace.isEmpty() ? nameSpace.toUpper() + '_' : "" )
01332 << className.toUpper() << "_H" << endl << endl;
01333
01334
01335 QStringList::ConstIterator it;
01336 for( it = headerIncludes.begin(); it != headerIncludes.end(); ++it ) {
01337 if ( (*it).startsWith('"') )
01338 h << "#include " << *it << endl;
01339 else
01340 h << "#include <" << *it << ">" << endl;
01341 }
01342
01343 if ( headerIncludes.count() > 0 ) h << endl;
01344
01345 if ( !singleton && parameters.isEmpty() )
01346 h << "#include <kglobal.h>" << endl;
01347
01348 h << "#include <kconfigskeleton.h>" << endl;
01349 h << "#include <kdebug.h>" << endl << endl;
01350
01351
01352 for( it = includes.begin(); it != includes.end(); ++it ) {
01353 if ( (*it).startsWith('"') )
01354 h << "#include " << *it << endl;
01355 else
01356 h << "#include <" << *it << ">" << endl;
01357 }
01358
01359 if ( !nameSpace.isEmpty() )
01360 h << "namespace " << nameSpace << " {" << endl << endl;
01361
01362
01363 if ( dpointer )
01364 h << "class " << className << "Private;" << endl << endl;
01365
01366
01367 h << "class " << visibility << className << " : public " << inherits << endl;
01368
01369 h << "{" << endl;
01370
01371 if( hasSignals )
01372 h << " Q_OBJECT" << endl;
01373 h << " public:" << endl;
01374
01375
01376 QList<CfgEntry*>::ConstIterator itEntry;
01377 for( itEntry = entries.begin(); itEntry != entries.end(); ++itEntry ) {
01378 const CfgEntry::Choices &choices = (*itEntry)->choices();
01379 QList<CfgEntry::Choice> chlist = choices.choices;
01380 if ( !chlist.isEmpty() ) {
01381 QStringList values;
01382 QList<CfgEntry::Choice>::ConstIterator itChoice;
01383 for( itChoice = chlist.begin(); itChoice != chlist.end(); ++itChoice ) {
01384 values.append( choices.prefix + (*itChoice).name );
01385 }
01386 if ( choices.name().isEmpty() ) {
01387 if ( globalEnums ) {
01388 h << " enum { " << values.join( ", " ) << " };" << endl;
01389 } else {
01390
01391 h << " class " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << endl;
01392 h << " {" << endl;
01393 h << " public:" << endl;
01394 h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl;
01395 h << " };" << endl;
01396 }
01397 } else if ( !choices.external() ) {
01398
01399 h << " enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << " { " << values.join( ", " ) << " };" << endl;
01400 }
01401 }
01402 QStringList values = (*itEntry)->paramValues();
01403 if ( !values.isEmpty() ) {
01404 if ( globalEnums ) {
01405
01406
01407
01408 h << " enum { " << values.join( ", " ) << " };" << endl;
01409 h << " static const char* const " << enumName( (*itEntry)->param() ) << "ToString[];" << endl;
01410 cppPreamble += "const char* const " + className + "::" + enumName( (*itEntry)->param() ) +
01411 "ToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
01412 } else {
01413 h << " class " << enumName( (*itEntry)->param() ) << endl;
01414 h << " {" << endl;
01415 h << " public:" << endl;
01416 h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl;
01417 h << " static const char* const enumToString[];" << endl;
01418 h << " };" << endl;
01419 cppPreamble += "const char* const " + className + "::" + enumName( (*itEntry)->param() ) +
01420 "::enumToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
01421 }
01422 }
01423 }
01424 if ( hasSignals ) {
01425 h << "\n enum {" << endl;
01426 unsigned val = 1;
01427 QList<Signal>::ConstIterator it, itEnd = signalList.constEnd();
01428 for ( it = signalList.constBegin(); it != itEnd; val <<= 1) {
01429 if ( !val ) {
01430 std::cerr << "Too many signals to create unique bit masks" << std::endl;
01431 exit(1);
01432 }
01433 Signal signal = *it;
01434 h << " " << signalEnumName(signal.name) << " = 0x" << hex << val;
01435 if ( ++it != itEnd )
01436 h << ",";
01437 h << endl;
01438 }
01439 h << " };" << dec << endl;
01440 }
01441 h << endl;
01442
01443 if ( !singleton ) {
01444 h << " " << className << "(";
01445 if (cfgFileNameArg)
01446 {
01447 if(forceStringFilename)
01448 h << " const QString &cfgfilename"
01449 << (parameters.isEmpty() ? " = QString()" : ", ");
01450 else
01451 h << " KSharedConfig::Ptr config"
01452 << (parameters.isEmpty() ? " = KGlobal::config()" : ", ");
01453 }
01454 for (QList<Param>::ConstIterator it = parameters.begin();
01455 it != parameters.end(); ++it)
01456 {
01457 if (it != parameters.begin())
01458 h << ",";
01459 h << " " << param((*it).type) << " " << (*it).name;
01460 }
01461 h << " );" << endl;
01462 } else {
01463 h << " static " << className << " *self();" << endl;
01464 if (cfgFileNameArg)
01465 {
01466 h << " static void instance(const QString& cfgfilename);" << endl;
01467 }
01468 }
01469
01470
01471 h << " ~" << className << "();" << endl << endl;
01472
01473
01474 if (staticAccessors)
01475 This = "self()->";
01476 else
01477 Const = " const";
01478
01479 for( itEntry = entries.begin(); itEntry != entries.end(); ++itEntry ) {
01480 QString n = (*itEntry)->name();
01481 QString t = (*itEntry)->type();
01482
01483
01484 if (allMutators || mutators.contains(n))
01485 {
01486 h << " /**" << endl;
01487 h << " Set " << (*itEntry)->label() << endl;
01488 h << " */" << endl;
01489 if (staticAccessors)
01490 h << " static" << endl;
01491 h << " void " << setFunction(n) << "( ";
01492 if (!(*itEntry)->param().isEmpty())
01493 h << cppType((*itEntry)->paramType()) << " i, ";
01494 if (useEnumTypes && t == "Enum")
01495 h << enumType(*itEntry);
01496 else
01497 h << param( t );
01498 h << " v )";
01499
01500
01501 if ( !dpointer )
01502 {
01503 h << endl << " {" << endl;
01504 h << indent(memberMutatorBody(*itEntry), 6 );
01505 h << " }" << endl;
01506 }
01507 else
01508 {
01509 h << ";" << endl;
01510 }
01511 }
01512 h << endl;
01513
01514 h << " /**" << endl;
01515 h << " Get " << (*itEntry)->label() << endl;
01516 h << " */" << endl;
01517 if (staticAccessors)
01518 h << " static" << endl;
01519 h << " ";
01520 if (useEnumTypes && t == "Enum")
01521 h << enumType(*itEntry);
01522 else
01523 h << cppType(t);
01524 h << " " << getFunction(n) << "(";
01525 if (!(*itEntry)->param().isEmpty())
01526 h << " " << cppType((*itEntry)->paramType()) <<" i ";
01527 h << ")" << Const;
01528
01529
01530 if ( !dpointer )
01531 {
01532 h << endl << " {" << endl;
01533 h << indent(memberAccessorBody((*itEntry)), 6 );
01534 h << " }" << endl;
01535 }
01536 else
01537 {
01538 h << ";" << endl;
01539 }
01540
01541
01542 if ( itemAccessors ) {
01543 h << endl;
01544 h << " /**" << endl;
01545 h << " Get Item object corresponding to " << n << "()"
01546 << endl;
01547 h << " */" << endl;
01548 h << " Item" << itemType( (*itEntry)->type() ) << " *"
01549 << getFunction( n ) << "Item(";
01550 if (!(*itEntry)->param().isEmpty()) {
01551 h << " " << cppType((*itEntry)->paramType()) << " i ";
01552 }
01553 h << ")";
01554 if (! dpointer )
01555 {
01556 h << endl << " {" << endl;
01557 h << indent( itemAccessorBody((*itEntry)), 6);
01558 h << " }" << endl;
01559 }
01560 else
01561 {
01562 h << ";" << endl;
01563 }
01564 }
01565
01566 h << endl;
01567 }
01568
01569
01570
01571 if( hasSignals ) {
01572 h << endl;
01573 h << " Q_SIGNALS:";
01574 foreach(const Signal &signal, signalList) {
01575 h << endl;
01576 if ( !signal.label.isEmpty() ) {
01577 h << " /**" << endl;
01578 h << " " << signal.label << endl;
01579 h << " */" << endl;
01580 }
01581 h << " void " << signal.name << "(";
01582 QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
01583 for ( it = signal.arguments.constBegin(); it != itEnd; ) {
01584 SignalArguments argument = *it;
01585 QString type = param(argument.type);
01586 if ( useEnumTypes && argument.type == "Enum" ) {
01587 for ( int i = 0, end = entries.count(); i < end; ++i ) {
01588 if ( entries[i]->name() == argument.variableName ) {
01589 type = enumType(entries[i]);
01590 break;
01591 }
01592 }
01593 }
01594 h << type << " " << argument.variableName;
01595 if ( ++it != itEnd ) {
01596 h << ", ";
01597 }
01598 }
01599 h << ");" << endl;
01600 }
01601 h << endl;
01602 }
01603
01604 h << " protected:" << endl;
01605
01606
01607 if ( singleton ) {
01608 h << " " << className << "(";
01609 if ( cfgFileNameArg )
01610 h << "const QString& arg";
01611 h << ");" << endl;
01612 h << " friend class " << className << "Helper;" << endl << endl;
01613 }
01614
01615 if ( hasSignals ) {
01616 h << " virtual void usrWriteConfig();" << endl;
01617 }
01618
01619
01620 if ( !memberVariables.isEmpty() && memberVariables != "private" && memberVariables != "dpointer") {
01621 h << " " << memberVariables << ":" << endl;
01622 }
01623
01624
01625 for (QList<Param>::ConstIterator it = parameters.begin();
01626 it != parameters.end(); ++it)
01627 {
01628 h << " " << cppType((*it).type) << " mParam" << (*it).name << ";" << endl;
01629 }
01630
01631 if ( memberVariables != "dpointer" )
01632 {
01633 QString group;
01634 for( itEntry = entries.begin(); itEntry != entries.end(); ++itEntry ) {
01635 if ( (*itEntry)->group() != group ) {
01636 group = (*itEntry)->group();
01637 h << endl;
01638 h << " // " << group << endl;
01639 }
01640 h << " " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name() );
01641 if ( !(*itEntry)->param().isEmpty() )
01642 {
01643 h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01644 }
01645 h << ";" << endl;
01646 }
01647
01648 h << endl << " private:" << endl;
01649 if ( itemAccessors ) {
01650 for( itEntry = entries.begin(); itEntry != entries.end(); ++itEntry ) {
01651 h << " Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry );
01652 if ( !(*itEntry)->param().isEmpty() ) h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01653 h << ";" << endl;
01654 }
01655 }
01656 if ( hasSignals )
01657 h << " uint " << varName("settingsChanged") << ";" << endl;
01658
01659 }
01660 else
01661 {
01662
01663 h << " private:" << endl;
01664 h << " " + className + "Private *d;" << endl;
01665 }
01666
01667 if (customAddons)
01668 {
01669 h << " // Include custom additions" << endl;
01670 h << " #include \"" << filenameOnly(baseName) << "_addons.h\"" <<endl;
01671 }
01672
01673 h << "};" << endl << endl;
01674
01675 if ( !nameSpace.isEmpty() ) h << "}" << endl << endl;
01676
01677 h << "#endif" << endl << endl;
01678
01679
01680 header.close();
01681
01682 QFile implementation( baseDir + implementationFileName );
01683 if ( !implementation.open( QIODevice::WriteOnly ) ) {
01684 std::cerr << "Can not open '" << qPrintable(implementationFileName) << "for writing."
01685 << std::endl;
01686 return 1;
01687 }
01688
01689 QTextStream cpp( &implementation );
01690
01691
01692 cpp << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
01693 cpp << "// All changes you do to this file will be lost." << endl << endl;
01694
01695 cpp << "#include \"" << headerFileName << "\"" << endl << endl;
01696
01697 for( it = sourceIncludes.begin(); it != sourceIncludes.end(); ++it ) {
01698 if ( (*it).startsWith('"') )
01699 cpp << "#include " << *it << endl;
01700 else
01701 cpp << "#include <" << *it << ">" << endl;
01702 }
01703
01704 if ( sourceIncludes.count() > 0 ) cpp << endl;
01705
01706 if ( setUserTexts ) cpp << "#include <klocale.h>" << endl << endl;
01707
01708
01709 if ( singleton )
01710 cpp << "#include <kglobal.h>" << endl << "#include <QtCore/QFile>" << endl << endl;
01711 if ( singleton && cfgFileNameArg )
01712 cpp << "#include <kdebug.h>" << endl << endl;
01713
01714 if ( !nameSpace.isEmpty() )
01715 cpp << "using namespace " << nameSpace << ";" << endl << endl;
01716
01717 QString group;
01718
01719
01720 if ( dpointer )
01721 {
01722 if ( !nameSpace.isEmpty() )
01723 cpp << "namespace " << nameSpace << " {" << endl;
01724 cpp << "class " << className << "Private" << endl;
01725 cpp << "{" << endl;
01726 cpp << " public:" << endl;
01727 for( itEntry = entries.begin(); itEntry != entries.end(); ++itEntry ) {
01728 if ( (*itEntry)->group() != group ) {
01729 group = (*itEntry)->group();
01730 cpp << endl;
01731 cpp << " // " << group << endl;
01732 }
01733 cpp << " " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name() );
01734 if ( !(*itEntry)->param().isEmpty() )
01735 {
01736 cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01737 }
01738 cpp << ";" << endl;
01739 }
01740 cpp << endl << " // items" << endl;
01741 for( itEntry = entries.begin(); itEntry != entries.end(); ++itEntry ) {
01742 cpp << " KConfigSkeleton::Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry );
01743 if ( !(*itEntry)->param().isEmpty() ) cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
01744 cpp << ";" << endl;
01745 }
01746 if ( hasSignals ) {
01747 cpp << " uint " << varName("settingsChanged") << ";" << endl;
01748 }
01749
01750 cpp << "};" << endl << endl;
01751 if ( !nameSpace.isEmpty() )
01752 cpp << "}" << endl << endl;
01753 }
01754
01755
01756 if ( singleton ) {
01757 if( !nameSpace.isEmpty() )
01758 cpp << "namespace " << nameSpace << " {" << endl;
01759 cpp << "class " << className << "Helper" << endl;
01760 cpp << '{' << endl;
01761 cpp << " public:" << endl;
01762 cpp << " " << className << "Helper() : q(0) {}" << endl;
01763 cpp << " ~" << className << "Helper() { delete q; }" << endl;
01764 cpp << " " << className << " *q;" << endl;
01765 cpp << "};" << endl;
01766 if( !nameSpace.isEmpty() )
01767 cpp << "}" << endl;
01768 cpp << "K_GLOBAL_STATIC(" << className << "Helper, s_global" << className << ")" << endl;
01769
01770 cpp << className << " *" << className << "::self()" << endl;
01771 cpp << "{" << endl;
01772 if ( cfgFileNameArg ) {
01773 cpp << " if (!s_global" << className << "->q)" << endl;
01774 cpp << " kFatal() << \"you need to call " << className << "::instance before using\";" << endl;
01775 } else {
01776 cpp << " if (!s_global" << className << "->q) {" << endl;
01777 cpp << " new " << className << ';' << endl;
01778 cpp << " s_global" << className << "->q->readConfig();" << endl;
01779 cpp << " }" << endl << endl;
01780 }
01781 cpp << " return s_global" << className << "->q;" << endl;
01782 cpp << "}" << endl << endl;
01783
01784 if ( cfgFileNameArg ) {
01785 cpp << "void " << className << "::instance(const QString& cfgfilename)" << endl;
01786 cpp << "{" << endl;
01787 cpp << " if (s_global" << className << "->q) {" << endl;
01788 cpp << " kDebug() << \"" << className << "::instance called after the first use - ignoring\";" << endl;
01789 cpp << " return;" << endl;
01790 cpp << " }" << endl;
01791 cpp << " new " << className << "(cfgfilename);" << endl;
01792 cpp << " s_global" << className << "->q->readConfig();" << endl;
01793 cpp << "}" << endl << endl;
01794 }
01795 }
01796
01797 if ( !cppPreamble.isEmpty() )
01798 cpp << cppPreamble << endl;
01799
01800
01801 cpp << className << "::" << className << "( ";
01802 if ( cfgFileNameArg ) {
01803 if ( !singleton && ! forceStringFilename)
01804 cpp << " KSharedConfig::Ptr config";
01805 else
01806 cpp << " const QString& config";
01807 cpp << (parameters.isEmpty() ? " " : ", ");
01808 }
01809
01810 for (QList<Param>::ConstIterator it = parameters.begin();
01811 it != parameters.end(); ++it)
01812 {
01813 if (it != parameters.begin())
01814 cpp << ",";
01815 cpp << " " << param((*it).type) << " " << (*it).name;
01816 }
01817 cpp << " )" << endl;
01818
01819 cpp << " : " << inherits << "(";
01820 if ( !cfgFileName.isEmpty() ) cpp << " QLatin1String( \"" << cfgFileName << "\" ";
01821 if ( cfgFileNameArg ) cpp << " config ";
01822 if ( !cfgFileName.isEmpty() ) cpp << ") ";
01823 cpp << ")" << endl;
01824
01825
01826 for (QList<Param>::ConstIterator it = parameters.begin();
01827 it != parameters.end(); ++it)
01828 {
01829 cpp << " , mParam" << (*it).name << "(" << (*it).name << ")" << endl;
01830 }
01831
01832 cpp << "{" << endl;
01833
01834 if (dpointer)
01835 cpp << " d = new " + className + "Private;" << endl;
01836
01837
01838 if (singleton) {
01839 cpp << " Q_ASSERT(!s_global" << className << "->q);" << endl;
01840 cpp << " s_global" << className << "->q = this;" << endl;
01841 }
01842
01843 group.clear();
01844
01845 for( itEntry = entries.begin(); itEntry != entries.end(); ++itEntry ) {
01846 if ( (*itEntry)->group() != group ) {
01847 if ( !group.isEmpty() ) cpp << endl;
01848 group = (*itEntry)->group();
01849 cpp << " setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl;
01850 }
01851
01852 QString key = paramString( (*itEntry)->key(), parameters );
01853 if ( !(*itEntry)->code().isEmpty() ) {
01854 cpp << (*itEntry)->code() << endl;
01855 }
01856 if ( (*itEntry)->type() == "Enum" ) {
01857 cpp << " QList<KConfigSkeleton::ItemEnum::Choice> values"
01858 << (*itEntry)->name() << ";" << endl;
01859 QList<CfgEntry::Choice> choices = (*itEntry)->choices().choices;
01860 QList<CfgEntry::Choice>::ConstIterator it;
01861 for( it = choices.begin(); it != choices.end(); ++it ) {
01862 cpp << " {" << endl;
01863 cpp << " KConfigSkeleton::ItemEnum::Choice choice;" << endl;
01864 cpp << " choice.name = QLatin1String( \"" << (*it).name << "\" );" << endl;
01865 if ( setUserTexts ) {
01866 if ( !(*it).label.isEmpty() ) {
01867 cpp << " choice.label = ";
01868 if ( !(*it).context.isEmpty() )
01869 cpp << "i18nc(" + quoteString((*it).context) + ", ";
01870 else
01871 cpp << "i18n(";
01872 cpp << quoteString((*it).label) << ");" << endl;
01873 }
01874 if ( !(*it).whatsThis.isEmpty() ) {
01875 cpp << " choice.whatsThis = ";
01876 if ( !(*it).context.isEmpty() )
01877 cpp << "i18nc(" + quoteString((*it).context) + ", ";
01878 else
01879 cpp << "i18n(";
01880 cpp << quoteString((*it).whatsThis) << ");" << endl;
01881 }
01882 }
01883 cpp << " values" << (*itEntry)->name() << ".append( choice );" << endl;
01884 cpp << " }" << endl;
01885 }
01886 }
01887
01888 if (!dpointer)
01889 cpp << itemDeclaration( *itEntry );
01890
01891 if ( (*itEntry)->param().isEmpty() )
01892 {
01893
01894 cpp << " " << itemPath( *itEntry ) << " = "
01895 << newItem( (*itEntry)->type(), (*itEntry)->name(), key, (*itEntry)->defaultValue() ) << endl;
01896
01897 if ( !(*itEntry)->minValue().isEmpty() )
01898 cpp << " " << itemPath( *itEntry ) << "->setMinValue(" << (*itEntry)->minValue() << ");" << endl;
01899 if ( !(*itEntry)->maxValue().isEmpty() )
01900 cpp << " " << itemPath( *itEntry ) << "->setMaxValue(" << (*itEntry)->maxValue() << ");" << endl;
01901
01902 if ( setUserTexts )
01903 cpp << userTextsFunctions( (*itEntry) );
01904
01905 cpp << " addItem( " << itemPath( *itEntry );
01906 QString quotedName = (*itEntry)->name();
01907 addQuotes( quotedName );
01908 if ( quotedName != key ) cpp << ", QLatin1String( \"" << (*itEntry)->name() << "\" )";
01909 cpp << " );" << endl;
01910 }
01911 else
01912 {
01913
01914 for(int i = 0; i <= (*itEntry)->paramMax(); i++)
01915 {
01916 QString defaultStr;
01917 QString itemVarStr(itemPath( *itEntry )+QString("[%1]").arg(i));
01918
01919 if ( !(*itEntry)->paramDefaultValue(i).isEmpty() )
01920 defaultStr = (*itEntry)->paramDefaultValue(i);
01921 else if ( !(*itEntry)->defaultValue().isEmpty() )
01922 defaultStr = paramString( (*itEntry)->defaultValue(), (*itEntry), i );
01923 else
01924 defaultStr = defaultValue( (*itEntry)->type() );
01925
01926 cpp << " " << itemVarStr << " = "
01927 << newItem( (*itEntry)->type(), (*itEntry)->name(), paramString(key, *itEntry, i), defaultStr, QString("[%1]").arg(i) )
01928 << endl;
01929
01930 if ( setUserTexts )
01931 cpp << userTextsFunctions( *itEntry, itemVarStr, (*itEntry)->paramName() );
01932
01933
01934
01935
01936
01937 cpp << " addItem( " << itemVarStr << ", QLatin1String( \"";
01938 if ( (*itEntry)->paramType()=="Enum" )
01939 cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg((*itEntry)->paramValues()[i] );
01940 else
01941 cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg(i);
01942 cpp << "\" ) );" << endl;
01943 }
01944 }
01945 }
01946
01947 cpp << "}" << endl << endl;
01948
01949 if (dpointer)
01950 {
01951
01952 for( itEntry = entries.begin(); itEntry != entries.end(); ++itEntry ) {
01953 QString n = (*itEntry)->name();
01954 QString t = (*itEntry)->type();
01955
01956
01957 if (allMutators || mutators.contains(n))
01958 {
01959 cpp << "void " << setFunction(n, className) << "( ";
01960 if ( !(*itEntry)->param().isEmpty() )
01961 cpp << cppType( (*itEntry)->paramType() ) << " i, ";
01962 if (useEnumTypes && t == "Enum")
01963 cpp << enumType(*itEntry);
01964 else
01965 cpp << param( t );
01966 cpp << " v )";
01967
01968
01969 cpp << "{" << endl;
01970 cpp << indent(memberMutatorBody( *itEntry ), 6);
01971 cpp << "}" << endl << endl;
01972 }
01973
01974
01975 if (useEnumTypes && t == "Enum")
01976 cpp << enumType(*itEntry);
01977 else
01978 cpp << cppType(t);
01979 cpp << " " << getFunction(n, className) << "(";
01980 if ( !(*itEntry)->param().isEmpty() )
01981 cpp << " " << cppType( (*itEntry)->paramType() ) <<" i ";
01982 cpp << ")" << Const << endl;
01983
01984
01985 cpp << "{" << endl;
01986 cpp << indent(memberAccessorBody( *itEntry ), 2);
01987 cpp << "}" << endl << endl;
01988
01989
01990 if ( itemAccessors )
01991 {
01992 cpp << endl;
01993 cpp << "KConfigSkeleton::Item" << itemType( (*itEntry)->type() ) << " *"
01994 << getFunction( n, className ) << "Item(";
01995 if ( !(*itEntry)->param().isEmpty() ) {
01996 cpp << " " << cppType( (*itEntry)->paramType() ) << " i ";
01997 }
01998 cpp << ")" << endl;
01999 cpp << "{" << endl;
02000 cpp << indent(itemAccessorBody( *itEntry ), 2);
02001 cpp << "}" << endl;
02002 }
02003
02004 cpp << endl;
02005 }
02006 }
02007
02008
02009 cpp << className << "::~" << className << "()" << endl;
02010 cpp << "{" << endl;
02011 if ( singleton ) {
02012 if ( dpointer )
02013 cpp << " delete d;" << endl;
02014 cpp << " if (!s_global" << className << ".isDestroyed()) {" << endl;
02015 cpp << " s_global" << className << "->q = 0;" << endl;
02016 cpp << " }" << endl;
02017 }
02018 cpp << "}" << endl << endl;
02019
02020 if ( hasSignals ) {
02021 cpp << "void " << className << "::" << "usrWriteConfig()" << endl;
02022 cpp << "{" << endl;
02023 cpp << " " << inherits << "::usrWriteConfig();" << endl << endl;
02024 foreach(const Signal &signal, signalList) {
02025 cpp << " if ( " << varPath("settingsChanged") << " & " << signalEnumName(signal.name) << " ) " << endl;
02026 cpp << " emit " << signal.name << "(";
02027 QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
02028 for ( it = signal.arguments.constBegin(); it != itEnd; ) {
02029 SignalArguments argument = *it;
02030 bool cast = false;
02031 if ( useEnumTypes && argument.type == "Enum" ) {
02032 for ( int i = 0, end = entries.count(); i < end; ++i ) {
02033 if ( entries[i]->name() == argument.variableName ) {
02034 cpp << "static_cast<" << enumType(entries[i]) << ">(";
02035 cast = true;
02036 break;
02037 }
02038 }
02039 }
02040 cpp << varPath(argument.variableName);
02041 if ( cast )
02042 cpp << ")";
02043 if ( ++it != itEnd )
02044 cpp << ", ";
02045 }
02046 cpp << ");" << endl << endl;
02047 }
02048 cpp << " " << varPath("settingsChanged") << " = 0;" << endl;
02049 cpp << "}" << endl;
02050 }
02051
02052
02053 if( hasSignals ) {
02054 cpp << endl;
02055 cpp << "#include \"" << mocFileName << "\"" << endl;
02056 cpp << endl;
02057 }
02058
02059
02060 qDeleteAll( entries );
02061
02062 implementation.close();
02063 }