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