00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
#include <qfile.h>
00026
#include <qtextstream.h>
00027
#include <qdom.h>
00028
#include <qregexp.h>
00029
00030
#include <kaboutdata.h>
00031
#include <kapplication.h>
00032
#include <kdebug.h>
00033
#include <klocale.h>
00034
#include <kcmdlineargs.h>
00035
#include <kglobal.h>
00036
#include <kconfig.h>
00037
#include <ksimpleconfig.h>
00038
#include <kstandarddirs.h>
00039
00040
static const KCmdLineOptions options[] =
00041 {
00042 {
"d", 0, 0 },
00043 {
"directory <dir>", I18N_NOOP(
"Directory to generate files in"),
"." },
00044 {
"+file.kfcg", I18N_NOOP(
"Input kcfg XML file."), 0 },
00045 {
"+file.kcfgc", I18N_NOOP(
"Code generation options file."), 0 },
00046 KCmdLineLastOption
00047 };
00048
00049
00050
bool globalEnums;
00051
bool itemAccessors;
00052
00053
class CfgEntry
00054 {
00055
public:
00056
struct Choice
00057 {
00058
QString name;
00059
QString label;
00060
QString whatsThis;
00061 };
00062
00063 CfgEntry(
const QString &group,
const QString &type,
const QString &key,
00064
const QString &name,
const QString &label,
00065
const QString &whatsThis,
const QString &code,
00066
const QString &defaultValue,
const QValueList<Choice> &choices,
00067
bool hidden )
00068 : mGroup( group ), mType( type ), mKey(
key ), mName(
name ),
00069 mLabel(
label ), mWhatsThis(
whatsThis ), mCode( code ),
00070 mDefaultValue( defaultValue ),
00071 mChoices( choices ), mHidden( hidden )
00072 {
00073 }
00074
00075
void setGroup(
const QString &group ) { mGroup = group; }
00076
QString group()
const {
return mGroup; }
00077
00078
void setType(
const QString &type ) { mType = type; }
00079
QString type()
const {
return mType; }
00080
00081
void setKey(
const QString &key ) { mKey =
key; }
00082
QString key()
const {
return mKey; }
00083
00084
void setName(
const QString &name ) { mName =
name; }
00085
QString name()
const {
return mName; }
00086
00087
void setLabel(
const QString &label ) { mLabel =
label; }
00088
QString label()
const {
return mLabel; }
00089
00090
void setWhatsThis(
const QString &whatsThis ) { mWhatsThis =
whatsThis; }
00091
QString whatsThis()
const {
return mWhatsThis; }
00092
00093
void setDefaultValue(
const QString &d ) { mDefaultValue = d; }
00094
QString defaultValue()
const {
return mDefaultValue; }
00095
00096
void setCode(
const QString &d ) { mCode = d; }
00097
QString code()
const {
return mCode; }
00098
00099
void setMinValue(
const QString &d ) { mMin = d; }
00100
QString minValue()
const {
return mMin; }
00101
00102
void setMaxValue(
const QString &d ) { mMax = d; }
00103
QString maxValue()
const {
return mMax; }
00104
00105
void setParam(
const QString &d ) { mParam = d; }
00106
QString param()
const {
return mParam; }
00107
00108
void setParamName(
const QString &d ) { mParamName = d; }
00109
QString paramName()
const {
return mParamName; }
00110
00111
void setParamType(
const QString &d ) { mParamType = d; }
00112
QString paramType()
const {
return mParamType; }
00113
00114
void setChoices(
const QValueList<Choice> &d ) { mChoices = d; }
00115
QValueList<Choice> choices()
const {
return mChoices; }
00116
00117
void setParamValues(
const QStringList &d ) { mParamValues = d; }
00118
QStringList paramValues()
const {
return mParamValues; }
00119
00120
void setParamDefaultValues(
const QStringList &d ) { mParamDefaultValues = d; }
00121
QString paramDefaultValue(
int i)
const {
return mParamDefaultValues[i]; }
00122
00123
void setParamMax(
int d ) { mParamMax = d; }
00124
int paramMax()
const {
return mParamMax; }
00125
00126
bool hidden()
const {
return mHidden; }
00127
00128
void dump()
const
00129
{
00130 kdDebug() <<
"<entry>" <<
endl;
00131 kdDebug() <<
" group: " << mGroup <<
endl;
00132 kdDebug() <<
" type: " << mType <<
endl;
00133 kdDebug() <<
" key: " << mKey <<
endl;
00134 kdDebug() <<
" name: " << mName <<
endl;
00135 kdDebug() <<
" label: " << mLabel <<
endl;
00136
00137 kdDebug() <<
" code: " << mCode <<
endl;
00138
00139 kdDebug() <<
" paramvalues: " << mParamValues.join(
":") <<
endl;
00140 kdDebug() <<
" default: " << mDefaultValue <<
endl;
00141 kdDebug() <<
" hidden: " << mHidden <<
endl;
00142 kdDebug() <<
" min: " << mMin <<
endl;
00143 kdDebug() <<
" max: " << mMax <<
endl;
00144 kdDebug() <<
"</entry>" <<
endl;
00145 }
00146
00147
private:
00148
QString mGroup;
00149
QString mType;
00150
QString mKey;
00151
QString mName;
00152
QString mLabel;
00153
QString mWhatsThis;
00154
QString mCode;
00155
QString mDefaultValue;
00156
QString mParam;
00157
QString mParamName;
00158
QString mParamType;
00159
QValueList<Choice> mChoices;
00160
QStringList mParamValues;
00161
QStringList mParamDefaultValues;
00162
int mParamMax;
00163
bool mHidden;
00164
QString mMin;
00165
QString mMax;
00166 };
00167
00168
00169
static QString varName(
const QString &n)
00170 {
00171
QString result =
"m"+n;
00172 result[1] = result[1].
upper();
00173
return result;
00174 }
00175
00176
static QString enumName(
const QString &n)
00177 {
00178
QString result =
"Enum"+n;
00179 result[4] = result[4].
upper();
00180
return result;
00181 }
00182
00183
static QString setFunction(
const QString &n)
00184 {
00185
QString result =
"set"+n;
00186 result[3] = result[3].
upper();
00187
return result;
00188 }
00189
00190
00191
static QString getFunction(
const QString &n)
00192 {
00193
QString result = n;
00194 result[0] = result[0].
lower();
00195
return result;
00196 }
00197
00198
00199
static void addQuotes(
QString &s )
00200 {
00201
if ( s.
left( 1 ) !=
"\"" ) s.
prepend(
"\"" );
00202
if ( s.
right( 1 ) !=
"\"" ) s.
append(
"\"" );
00203 }
00204
00205
static QString dumpNode(
const QDomNode &node)
00206 {
00207
QString msg;
00208
QTextStream s(&msg, IO_WriteOnly );
00209 node.
save(s, 0);
00210
00211 msg = msg.
simplifyWhiteSpace();
00212
if (msg.
length() > 40)
00213
return msg.
left(37)+
"...";
00214
return msg;
00215 }
00216
00217
static QString filenameOnly(
QString path)
00218 {
00219
int i = path.
findRev(
'/');
00220
if (i >= 0)
00221
return path.
mid(i+1);
00222
return path;
00223 }
00224
00225
static void preProcessDefault(
QString &defaultValue,
const QString &name,
00226
const QString &type,
00227
const QValueList<CfgEntry::Choice> &choices,
00228
QString &code )
00229 {
00230
if ( type ==
"String" && !defaultValue.
isEmpty() ) {
00231 addQuotes( defaultValue );
00232
00233 }
else if ( type ==
"Path" && !defaultValue.
isEmpty() ) {
00234 addQuotes( defaultValue );
00235
00236 }
else if ( type ==
"StringList" && !defaultValue.
isEmpty() ) {
00237
QTextStream cpp( &code, IO_WriteOnly | IO_Append );
00238
if (!code.
isEmpty())
00239 cpp <<
endl;
00240
00241 cpp <<
" QStringList default" <<
name <<
";" <<
endl;
00242
QStringList defaults =
QStringList::split(
",", defaultValue );
00243 QStringList::ConstIterator it;
00244
for( it = defaults.begin(); it != defaults.end(); ++it ) {
00245 cpp <<
" default" <<
name <<
".append( \"" << *it <<
"\" );"
00246 <<
endl;
00247 }
00248 defaultValue =
"default" +
name;
00249
00250 }
else if ( type ==
"Color" && !defaultValue.
isEmpty() ) {
00251
QRegExp colorRe(
"\\d+,\\s*\\d+,\\s*\\d+");
00252
if (colorRe.
exactMatch(defaultValue))
00253 {
00254 defaultValue =
"QColor( " + defaultValue +
" )";
00255 }
00256
else
00257 {
00258 defaultValue =
"QColor( \"" + defaultValue +
"\" )";
00259 }
00260
00261 }
else if ( type ==
"Enum" ) {
00262
if ( !globalEnums ) {
00263
QValueList<CfgEntry::Choice>::ConstIterator it;
00264
for( it = choices.
begin(); it != choices.
end(); ++it ) {
00265
if ( (*it).name == defaultValue ) {
00266 defaultValue.
prepend( enumName(name) +
"::");
00267
break;
00268 }
00269 }
00270 }
00271
00272 }
else if ( type ==
"IntList" ) {
00273
QTextStream cpp( &code, IO_WriteOnly | IO_Append );
00274
if (!code.
isEmpty())
00275 cpp <<
endl;
00276
00277 cpp <<
" QValueList<int> default" <<
name <<
";" <<
endl;
00278
QStringList defaults =
QStringList::split(
",", defaultValue );
00279 QStringList::ConstIterator it;
00280
for( it = defaults.begin(); it != defaults.end(); ++it ) {
00281 cpp <<
" default" <<
name <<
".append( " << *it <<
" );"
00282 <<
endl;
00283 }
00284 defaultValue =
"default" +
name;
00285 }
00286 }
00287
00288
00289 CfgEntry *parseEntry(
const QString &group,
const QDomElement &element )
00290 {
00291
bool defaultCode =
false;
00292
QString type = element.
attribute(
"type" );
00293
QString name = element.
attribute(
"name" );
00294
QString key = element.
attribute(
"key" );
00295
QString hidden = element.
attribute(
"hidden" );
00296
QString label;
00297
QString whatsThis;
00298
QString defaultValue;
00299
QString code;
00300
QString param;
00301
QString paramName;
00302
QString paramType;
00303
QValueList<CfgEntry::Choice> choices;
00304
QStringList paramValues;
00305
QStringList paramDefaultValues;
00306
QString minValue;
00307
QString maxValue;
00308
int paramMax = 0;
00309
00310
QDomNode n;
00311
for ( n = element.firstChild(); !n.
isNull(); n = n.
nextSibling() ) {
00312
QDomElement e = n.
toElement();
00313
QString tag = e.
tagName();
00314
if ( tag ==
"label" )
label = e.
text();
00315
else if ( tag ==
"whatsthis" )
whatsThis = e.
text();
00316
else if ( tag ==
"min" ) minValue = e.
text();
00317
else if ( tag ==
"max" ) maxValue = e.
text();
00318
else if ( tag ==
"code" ) code = e.
text();
00319
else if ( tag ==
"parameter" )
00320 {
00321 param = e.
attribute(
"name" );
00322 paramType = e.
attribute(
"type" );
00323
if ( param.
isEmpty() ) {
00324 kdError() <<
"Parameter must have a name: " << dumpNode(e) <<
endl;
00325
return 0;
00326 }
00327
if ( paramType.
isEmpty() ) {
00328 kdError() <<
"Parameter must have a type: " << dumpNode(e) <<
endl;
00329
return 0;
00330 }
00331
if ((paramType ==
"Int") || (paramType ==
"UInt"))
00332 {
00333
bool ok;
00334 paramMax = e.
attribute(
"max").toInt(&ok);
00335
if (!ok)
00336 {
00337 kdError() <<
"Integer parameter must have a maximum (e.g. max=\"0\"): " << dumpNode(e) <<
endl;
00338
return 0;
00339 }
00340 }
00341
else if (paramType ==
"Enum")
00342 {
00343
QDomNode n2;
00344
for ( n2 = e.firstChild(); !n2.
isNull(); n2 = n2.
nextSibling() ) {
00345
QDomElement e2 = n2.
toElement();
00346
if (e2.
tagName() ==
"values")
00347 {
00348
QDomNode n3;
00349
for ( n3 = e2.firstChild(); !n3.
isNull(); n3 = n3.
nextSibling() ) {
00350
QDomElement e3 = n3.
toElement();
00351
if (e3.
tagName() ==
"value")
00352 {
00353 paramValues.append( e3.
text() );
00354 }
00355 }
00356
break;
00357 }
00358 }
00359
if (paramValues.isEmpty())
00360 {
00361 kdError() <<
"No values specified for parameter '" << param <<
"'." <<
endl;
00362
return 0;
00363 }
00364 paramMax = paramValues.count()-1;
00365 }
00366
else
00367 {
00368 kdError() <<
"Parameter '" << param <<
"' has type " << paramType <<
" but must be of type int, uint or Enum." <<
endl;
00369
return 0;
00370 }
00371 }
00372
else if ( tag ==
"default" )
00373 {
00374
if (e.
attribute(
"param").isEmpty())
00375 {
00376 defaultValue = e.
text();
00377
if (e.
attribute(
"code" ) ==
"true")
00378 defaultCode =
true;
00379 }
00380 }
00381
else if ( tag ==
"choices" ) {
00382
QDomNode n2;
00383
for( n2 = e.firstChild(); !n2.
isNull(); n2 = n2.
nextSibling() ) {
00384
QDomElement e2 = n2.
toElement();
00385
if ( e2.
tagName() ==
"choice" ) {
00386
QDomNode n3;
00387 CfgEntry::Choice choice;
00388 choice.name = e2.
attribute(
"name" );
00389
if ( choice.name.isEmpty() ) {
00390 kdError() <<
"Tag <choice> requires attribute 'name'." <<
endl;
00391 }
00392
for( n3 = e2.firstChild(); !n3.
isNull(); n3 = n3.
nextSibling() ) {
00393
QDomElement e3 = n3.
toElement();
00394
if ( e3.
tagName() ==
"label" ) choice.label = e3.
text();
00395
if ( e3.
tagName() ==
"whatsthis" ) choice.whatsThis = e3.
text();
00396 }
00397 choices.
append( choice );
00398 }
00399 }
00400 }
00401 }
00402
00403
if (
name.isEmpty() &&
key.isEmpty() ) {
00404 kdError() <<
"Entry must have a name or a key: " << dumpNode(element) <<
endl;
00405
return 0;
00406 }
00407
00408
if (
key.isEmpty() ) {
00409
key =
name;
00410 }
00411
00412
if (
name.isEmpty() ) {
00413
name =
key;
00414
name.replace(
" ",
"" );
00415 }
else if (
name.contains(
' ' ) ) {
00416 kdWarning()<<
"Entry '"<<
name<<
"' contains spaces! <name> elements can't contain speces!"<<
endl;
00417
name.remove(
' ' );
00418 }
00419
00420
if (
name.contains(
"$("))
00421 {
00422
if (param.
isEmpty())
00423 {
00424 kdError() <<
"Name may not be parameterized: " <<
name <<
endl;
00425
return 0;
00426 }
00427 }
00428
else
00429 {
00430
if (!param.
isEmpty())
00431 {
00432 kdError() <<
"Name must contain '$(" << param <<
")': " <<
name <<
endl;
00433
return 0;
00434 }
00435 }
00436
00437
if (
label.
isEmpty() ) {
00438
label =
key;
00439 }
00440
00441
if ( type.
isEmpty() ) type =
"String";
00442
00443
if (!param.
isEmpty())
00444 {
00445
00446 paramName =
name;
00447
name.replace(
"$("+param+
")", QString::null);
00448
00449
for(
int i = 0; i <= paramMax; i++)
00450 {
00451 paramDefaultValues.append(QString::null);
00452 }
00453
00454
QDomNode n;
00455
for ( n = element.firstChild(); !n.
isNull(); n = n.
nextSibling() ) {
00456
QDomElement e = n.
toElement();
00457
QString tag = e.
tagName();
00458
if ( tag ==
"default" )
00459 {
00460
QString index = e.
attribute(
"param");
00461
if (index.
isEmpty())
00462
continue;
00463
00464
bool ok;
00465
int i = index.
toInt(&ok);
00466
if (!ok)
00467 {
00468 i = paramValues.findIndex(index);
00469
if (i == -1)
00470 {
00471 kdError() <<
"Index '" << index <<
"' for default value is unknown." <<
endl;
00472
return 0;
00473 }
00474 }
00475
00476
if ((i < 0) || (i > paramMax))
00477 {
00478 kdError() <<
"Index '" << i <<
"' for default value is out of range [0, "<< paramMax<<
"]." <<
endl;
00479
return 0;
00480 }
00481
00482
QString tmpDefaultValue = e.
text();
00483
00484
if (e.
attribute(
"code" ) !=
"true")
00485 preProcessDefault(tmpDefaultValue, name, type, choices, code);
00486
00487 paramDefaultValues[i] = tmpDefaultValue;
00488 }
00489 }
00490 }
00491
00492
if (!defaultCode)
00493 {
00494 preProcessDefault(defaultValue, name, type, choices, code);
00495 }
00496
00497 CfgEntry *result =
new CfgEntry( group, type, key, name, label, whatsThis,
00498 code, defaultValue, choices,
00499 hidden ==
"true" );
00500
if (!param.
isEmpty())
00501 {
00502 result->setParam(param);
00503 result->setParamName(paramName);
00504 result->setParamType(paramType);
00505 result->setParamValues(paramValues);
00506 result->setParamDefaultValues(paramDefaultValues);
00507 result->setParamMax(paramMax);
00508 }
00509 result->setMinValue(minValue);
00510 result->setMaxValue(maxValue);
00511
00512
return result;
00513 }
00514
00518
QString param(
const QString &type )
00519 {
00520
if ( type ==
"String" )
return "const QString &";
00521
else if ( type ==
"StringList" )
return "const QStringList &";
00522
else if ( type ==
"Font" )
return "const QFont &";
00523
else if ( type ==
"Rect" )
return "const QRect &";
00524
else if ( type ==
"Size" )
return "const QSize &";
00525
else if ( type ==
"Color" )
return "const QColor &";
00526
else if ( type ==
"Point" )
return "const QPoint &";
00527
else if ( type ==
"Int" )
return "int";
00528
else if ( type ==
"UInt" )
return "uint";
00529
else if ( type ==
"Bool" )
return "bool";
00530
else if ( type ==
"Double" )
return "double";
00531
else if ( type ==
"DateTime" )
return "const QDateTime &";
00532
else if ( type ==
"Int64" )
return "Q_INT64";
00533
else if ( type ==
"UInt64" )
return "Q_UINT64";
00534
else if ( type ==
"IntList" )
return "const QValueList<int> &";
00535
else if ( type ==
"Enum" )
return "int";
00536
else if ( type ==
"Path" )
return "const QString &";
00537
else if ( type ==
"Password" )
return "const QString &";
00538
else {
00539 kdError() <<
"kconfig_compiler does not support type \""<< type <<
"\""<<
endl;
00540
return "QString";
00541 }
00542 }
00543
00547
QString cppType(
const QString &type )
00548 {
00549
if ( type ==
"String" )
return "QString";
00550
else if ( type ==
"StringList" )
return "QStringList";
00551
else if ( type ==
"Font" )
return "QFont";
00552
else if ( type ==
"Rect" )
return "QRect";
00553
else if ( type ==
"Size" )
return "QSize";
00554
else if ( type ==
"Color" )
return "QColor";
00555
else if ( type ==
"Point" )
return "QPoint";
00556
else if ( type ==
"Int" )
return "int";
00557
else if ( type ==
"UInt" )
return "uint";
00558
else if ( type ==
"Bool" )
return "bool";
00559
else if ( type ==
"Double" )
return "double";
00560
else if ( type ==
"DateTime" )
return "QDateTime";
00561
else if ( type ==
"Int64" )
return "Q_INT64";
00562
else if ( type ==
"UInt64" )
return "Q_UINT64";
00563
else if ( type ==
"IntList" )
return "QValueList<int>";
00564
else if ( type ==
"Enum" )
return "int";
00565
else if ( type ==
"Path" )
return "QString";
00566
else if ( type ==
"Password" )
return "QString";
00567
else {
00568 kdError()<<
"kconfig_compiler does not support type \""<< type <<
"\""<<
endl;
00569
return "QString";
00570 }
00571 }
00572
00573
QString defaultValue(
const QString &type )
00574 {
00575
if ( type ==
"String" )
return "\"\"";
00576
else if ( type ==
"StringList" )
return "QStringList()";
00577
else if ( type ==
"Font" )
return "KGlobalSettings::generalFont()";
00578
else if ( type ==
"Rect" )
return "QRect()";
00579
else if ( type ==
"Size" )
return "QSize()";
00580
else if ( type ==
"Color" )
return "QColor(128, 128, 128)";
00581
else if ( type ==
"Point" )
return "QPoint()";
00582
else if ( type ==
"Int" )
return "0";
00583
else if ( type ==
"UInt" )
return "0";
00584
else if ( type ==
"Bool" )
return "false";
00585
else if ( type ==
"Double" )
return "0.0";
00586
else if ( type ==
"DateTime" )
return "QDateTime()";
00587
else if ( type ==
"Int64" )
return "0";
00588
else if ( type ==
"UInt64" )
return "0";
00589
else if ( type ==
"IntList" )
return "QValueList<int>()";
00590
else if ( type ==
"Enum" )
return "0";
00591
else if ( type ==
"Path" )
return "\"\"";
00592
else if ( type ==
"Password" )
return "\"\"";
00593
else {
00594 kdWarning()<<
"Error, kconfig_compiler doesn't support the \""<< type <<
"\" type!"<<
endl;
00595
return "QString";
00596 }
00597 }
00598
00599
QString itemType(
const QString &type )
00600 {
00601
QString t;
00602
00603 t = type;
00604 t.
replace( 0, 1, t.
left( 1 ).upper() );
00605
00606
return t;
00607 }
00608
00609
static QString itemDeclaration(
const CfgEntry *e)
00610 {
00611
if (itemAccessors)
00612
return QString::null;
00613
00614
return " KConfigSkeleton::Item"+itemType( e->type() ) +
00615
" *item" + e->name() +
";\n";
00616 }
00617
00618
static QString itemVar(
const CfgEntry *e)
00619 {
00620
if (itemAccessors)
00621
return varName( e->name() ) +
"Item";
00622
00623
return "item" + e->name();
00624
00625 }
00626
00627
QString newItem(
const QString &type,
const QString &name,
const QString &key,
00628
const QString &defaultValue,
const QString ¶m = QString::null)
00629 {
00630
QString t =
"new KConfigSkeleton::Item" + itemType( type ) +
00631
"( currentGroup(), " +
key +
", " + varName( name ) + param;
00632
if ( type ==
"Enum" ) t +=
", values" +
name;
00633
if ( !defaultValue.
isEmpty() ) t +=
", " + defaultValue;
00634 t +=
" );";
00635
00636
return t;
00637 }
00638
00639
QString paramString(
const QString &s,
const CfgEntry *e,
int i)
00640 {
00641
QString result = s;
00642
QString needle =
"$("+e->param()+
")";
00643
if (result.
contains(needle))
00644 {
00645
QString tmp;
00646
if (e->paramType() ==
"Enum")
00647 {
00648 tmp = e->paramValues()[i];
00649 }
00650
else
00651 {
00652 tmp =
QString(
"%1").
arg(i);
00653 }
00654
00655 result.
replace(needle, tmp);
00656 }
00657
return result;
00658 }
00659
00660
QString paramString(
const QString &group,
const QStringList ¶meters)
00661 {
00662
QString paramString = group;
00663
QString arguments;
00664
int i = 1;
00665
for( QStringList::ConstIterator it = parameters.begin();
00666 it != parameters.end(); ++it)
00667 {
00668
if (paramString.
contains(
"$("+*it+
")"))
00669 {
00670
QString tmp;
00671 tmp.
sprintf(
"%%%d", i++);
00672 paramString.
replace(
"$("+*it+
")", tmp);
00673 arguments +=
".arg( mParam"+*it+
" )";
00674 }
00675 }
00676
if (arguments.
isEmpty())
00677
return "\""+group+
"\"";
00678
00679
return "QString(\""+paramString+
"\")"+arguments;
00680 }
00681
00682
QString userTextsFunctions( CfgEntry *e )
00683 {
00684
QString txt;
00685
if ( !e->label().isEmpty() ) {
00686 txt +=
" " + itemVar(e) +
"->setLabel( i18n(\"" +
00687 e->label() +
"\") );\n";
00688 }
00689
if ( !e->whatsThis().isEmpty() ) {
00690 txt +=
" " + itemVar(e) +
"->setWhatsThis( i18n(\"" +
00691 e->whatsThis() +
"\") );\n";
00692 }
00693
return txt;
00694 }
00695
00696
int main(
int argc,
char **argv )
00697 {
00698
KAboutData aboutData(
"kconfig_compiler", I18N_NOOP(
"KDE .kcfg compiler"),
"0.3",
00699 I18N_NOOP(
"KConfig Compiler") , KAboutData::License_LGPL );
00700 aboutData.
addAuthor(
"Cornelius Schumacher", 0,
"schumacher@kde.org" );
00701 aboutData.
addAuthor(
"Waldo Bastian", 0,
"bastian@kde.org" );
00702 aboutData.
addAuthor(
"Zack Rusin", 0,
"zack@kde.org" );
00703
00704
KCmdLineArgs::init( argc, argv, &aboutData );
00705
KCmdLineArgs::addCmdLineOptions( options );
00706
00707
KInstance app( &aboutData );
00708
00709
KCmdLineArgs *args =
KCmdLineArgs::parsedArgs();
00710
00711
if ( args->
count() < 2 ) {
00712 kdError() <<
"Too few arguments." <<
endl;
00713
return 1;
00714 }
00715
if ( args->
count() > 2 ) {
00716 kdError() <<
"Too many arguments." <<
endl;
00717
return 1;
00718 }
00719
00720
QString baseDir =
QFile::decodeName(args->
getOption(
"directory"));
00721
if (!baseDir.
endsWith(
"/"))
00722 baseDir.
append(
"/");
00723
00724
QString inputFilename = args->
url( 0 ).
path();
00725
QString codegenFilename = args->
url( 1 ).
path();
00726
00727
if (!codegenFilename.
endsWith(
".kcfgc"))
00728 {
00729 kdError() <<
"Codegen options file must have extension .kcfgc" <<
endl;
00730
return 1;
00731 }
00732
QString baseName = args->
url( 1 ).
fileName();
00733 baseName = baseName.
left(baseName.
length() - 6);
00734
00735
KSimpleConfig codegenConfig( codegenFilename,
true );
00736
00737
QString nameSpace = codegenConfig.
readEntry(
"NameSpace");
00738
QString className = codegenConfig.
readEntry(
"ClassName");
00739
QString inherits = codegenConfig.
readEntry(
"Inherits");
00740
bool singleton = codegenConfig.
readBoolEntry(
"Singleton",
false);
00741
bool staticAccessors = singleton;
00742
bool customAddons = codegenConfig.
readBoolEntry(
"CustomAdditions");
00743
QString memberVariables = codegenConfig.
readEntry(
"MemberVariables");
00744
QStringList headerIncludes = codegenConfig.
readListEntry(
"IncludeFiles");
00745
QStringList mutators = codegenConfig.
readListEntry(
"Mutators");
00746
bool allMutators =
false;
00747
if ((mutators.count() == 1) && (mutators[0].lower() ==
"true"))
00748 allMutators =
true;
00749 itemAccessors = codegenConfig.
readBoolEntry(
"ItemAccessors",
false );
00750
bool setUserTexts = codegenConfig.
readBoolEntry(
"SetUserTexts",
false );
00751
00752 globalEnums = codegenConfig.
readBoolEntry(
"GlobalEnums",
false );
00753
00754
QFile input( inputFilename );
00755
00756
QDomDocument doc;
00757
QString errorMsg;
00758
int errorRow;
00759
int errorCol;
00760
if ( !doc.
setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
00761 kdError() <<
"Unable to load document." <<
endl;
00762 kdError() <<
"Parse error in " << args->
url( 0 ).
fileName() <<
", line " << errorRow <<
", col " << errorCol <<
": " << errorMsg <<
endl;
00763
return 1;
00764 }
00765
00766
QDomElement cfgElement = doc.
documentElement();
00767
00768
if ( cfgElement.isNull() ) {
00769 kdError() <<
"No document in kcfg file" <<
endl;
00770
return 1;
00771 }
00772
00773
QString cfgFileName;
00774
bool cfgFileNameArg =
false;
00775
QStringList parameters;
00776
QStringList includes;
00777
00778
QPtrList<CfgEntry> entries;
00779 entries.
setAutoDelete(
true );
00780
00781
QDomNode n;
00782
for ( n = cfgElement.firstChild(); !n.
isNull(); n = n.
nextSibling() ) {
00783
QDomElement e = n.
toElement();
00784
00785
QString tag = e.
tagName();
00786
00787
if ( tag ==
"include" ) {
00788
QString includeFile = e.
text();
00789
if (!includeFile.
isEmpty())
00790 includes.append(includeFile);
00791
00792 }
else if ( tag ==
"kcfgfile" ) {
00793 cfgFileName = e.
attribute(
"name" );
00794 cfgFileNameArg = e.
attribute(
"arg" ).lower() ==
"true";
00795
QDomNode n2;
00796
for( n2 = e.firstChild(); !n2.
isNull(); n2 = n2.
nextSibling() ) {
00797
QDomElement e2 = n2.
toElement();
00798
if ( e2.
tagName() ==
"parameter" ) {
00799 parameters.append( e2.
attribute(
"name" ) );
00800 }
00801 }
00802
00803 }
else if ( tag ==
"group" ) {
00804
QString group = e.
attribute(
"name" );
00805
if ( group.isEmpty() ) {
00806 kdError() <<
"Group without name" <<
endl;
00807
return 1;
00808 }
00809
QDomNode n2;
00810
for( n2 = e.firstChild(); !n2.
isNull(); n2 = n2.
nextSibling() ) {
00811
QDomElement e2 = n2.
toElement();
00812
if ( e2.
tagName() !=
"entry" )
continue;
00813 CfgEntry *entry = parseEntry( group, e2 );
00814
if ( entry ) entries.
append( entry );
00815
else {
00816 kdError() <<
"Can't parse entry." <<
endl;
00817
return 1;
00818 }
00819 }
00820 }
00821 }
00822
00823
if ( inherits.
isEmpty() ) inherits =
"KConfigSkeleton";
00824
00825
if ( className.
isEmpty() ) {
00826 kdError() <<
"Class name missing" <<
endl;
00827
return 1;
00828 }
00829
00830
if ( singleton && !parameters.isEmpty() ) {
00831 kdError() <<
"Singleton class can not have parameters" <<
endl;
00832
return 1;
00833 }
00834
00835
if ( singleton && cfgFileNameArg)
00836 {
00837 kdError() <<
"Singleton class can not use filename as argument." <<
endl;
00838
return 1;
00839 }
00840
00841
if ( !cfgFileName.
isEmpty() && cfgFileNameArg)
00842 {
00843 kdError() <<
"Having both a fixed filename and a filename as argument is not possible." <<
endl;
00844
return 1;
00845 }
00846
00847
if ( entries.
isEmpty() ) {
00848 kdWarning() <<
"No entries." <<
endl;
00849 }
00850
00851
#if 0
00852
CfgEntry *cfg;
00853
for( cfg = entries.
first(); cfg; cfg = entries.
next() ) {
00854 cfg->dump();
00855 }
00856
#endif
00857
00858
QString headerFileName = baseName +
".h";
00859
QString implementationFileName = baseName +
".cpp";
00860
00861
QFile header( baseDir + headerFileName );
00862
if ( !header.
open( IO_WriteOnly ) ) {
00863 kdError() <<
"Can't open '" << headerFileName <<
"for writing." <<
endl;
00864
return 1;
00865 }
00866
00867
QTextStream h( &header );
00868
00869 h <<
"// This file is generated by kconfig_compiler from " << args->
url(0).
fileName() <<
"." <<
endl;
00870 h <<
"// All changes you do to this file will be lost." <<
endl;
00871
00872 h <<
"#ifndef " << ( !nameSpace.
isEmpty() ? nameSpace.
upper() +
"_" :
"" )
00873 << className.
upper() <<
"_H" <<
endl;
00874 h <<
"#define " << ( !nameSpace.
isEmpty() ? nameSpace.
upper() +
"_" :
"" )
00875 << className.
upper() <<
"_H" <<
endl <<
endl;
00876
00877
00878 QStringList::ConstIterator it;
00879
for( it = headerIncludes.begin(); it != headerIncludes.end(); ++it ) {
00880 h <<
"#include <" << *it <<
">" <<
endl;
00881 }
00882
00883
if ( headerIncludes.count() > 0 ) h <<
endl;
00884
00885 h <<
"#include <kconfigskeleton.h>" <<
endl <<
endl;
00886
00887
if ( !nameSpace.
isEmpty() )
00888 h <<
"namespace " << nameSpace <<
" {" <<
endl <<
endl;
00889
00890
00891 h <<
"class " << className <<
" : public " << inherits <<
endl;
00892 h <<
"{" <<
endl;
00893 h <<
" public:" <<
endl;
00894
00895
00896 CfgEntry *e;
00897
for( e = entries.
first(); e; e = entries.
next() ) {
00898
QValueList<CfgEntry::Choice> choices = e->choices();
00899
if ( !choices.
isEmpty() ) {
00900
QStringList values;
00901
QValueList<CfgEntry::Choice>::ConstIterator itChoice;
00902
for( itChoice = choices.
begin(); itChoice != choices.
end(); ++itChoice ) {
00903 values.append( (*itChoice).name );
00904 }
00905
if ( globalEnums ) {
00906 h <<
" enum { " << values.
join(
", " ) <<
" };" <<
endl;
00907 }
else {
00908 h <<
" class " << enumName(e->name()) <<
endl;
00909 h <<
" {" <<
endl;
00910 h <<
" public:" <<
endl;
00911 h <<
" enum { " << values.
join(
", " ) <<
", COUNT };" <<
endl;
00912 h <<
" };" <<
endl;
00913 }
00914 }
00915
QStringList values = e->paramValues();
00916
if ( !values.isEmpty() ) {
00917 h <<
" class " << enumName(e->param()) <<
endl;
00918 h <<
" {" <<
endl;
00919 h <<
" public:" <<
endl;
00920 h <<
" enum { " << values.
join(
", " ) <<
", COUNT };" <<
endl;
00921 h <<
" };" <<
endl;
00922 }
00923 }
00924
00925 h <<
endl;
00926
00927
00928
if ( !singleton ) {
00929 h <<
" " << className <<
"(";
00930
if (cfgFileNameArg)
00931 h <<
" KSharedConfig::Ptr config" << (parameters.isEmpty() ?
" " :
", ");
00932
for (QStringList::ConstIterator it = parameters.begin();
00933 it != parameters.end(); ++it)
00934 {
00935
if (it != parameters.begin())
00936 h <<
",";
00937 h <<
" const QString &" << *it;
00938 }
00939 h <<
" );" <<
endl;
00940 }
else {
00941 h <<
" static " << className <<
" *self();" <<
endl;
00942 }
00943
00944
00945 h <<
" ~" << className <<
"();" <<
endl <<
endl;
00946
00947
QString This;
00948
QString Const;
00949
if (staticAccessors)
00950 This =
"self()->";
00951
else
00952 Const =
" const";
00953
00954
for( e = entries.
first(); e; e = entries.
next() ) {
00955
QString n = e->name();
00956
QString t = e->type();
00957
00958
00959
if (allMutators || mutators.contains(n))
00960 {
00961 h <<
" /**" <<
endl;
00962 h <<
" Set " << e->label() <<
endl;
00963 h <<
" */" <<
endl;
00964
if (staticAccessors)
00965 h <<
" static" <<
endl;
00966 h <<
" void " << setFunction(n) <<
"( ";
00967
if (!e->param().isEmpty())
00968 h << cppType(e->paramType()) <<
" i, ";
00969 h << param( t ) <<
" v )" <<
endl;
00970 h <<
" {" <<
endl;
00971 h <<
" if (!" << This <<
"isImmutable( \"" << n <<
"\" ))" <<
endl;
00972 h <<
" " << This << varName(n);
00973
if (!e->param().isEmpty())
00974 h <<
"[i]";
00975 h <<
" = v;" <<
endl;
00976 h <<
" }" <<
endl <<
endl;
00977 }
00978
00979
00980 h <<
" /**" <<
endl;
00981 h <<
" Get " << e->label() <<
endl;
00982 h <<
" */" <<
endl;
00983
if (staticAccessors)
00984 h <<
" static" <<
endl;
00985 h <<
" " << cppType(t) <<
" " << getFunction(n) <<
"(";
00986
if (!e->param().isEmpty())
00987 h <<
" " << cppType(e->paramType()) <<
" i ";
00988 h <<
")" << Const <<
endl;
00989 h <<
" {" <<
endl;
00990 h <<
" return " << This << varName(n);
00991
if (!e->param().isEmpty())
00992 h <<
"[i]";
00993 h <<
";" <<
endl;
00994 h <<
" }" <<
endl;
00995
00996
00997
if ( itemAccessors ) {
00998 h <<
endl;
00999 h <<
" /**" <<
endl;
01000 h <<
" Get Item object corresponding to " << n <<
"()"
01001 <<
endl;
01002 h <<
" */" <<
endl;
01003 h <<
" Item" << itemType( e->type() ) <<
" *"
01004 << getFunction( n ) <<
"Item()" <<
endl;
01005 h <<
" {" <<
endl;
01006 h <<
" return " << itemVar(e) <<
";" <<
endl;
01007 h <<
" }" <<
endl;
01008 }
01009
01010 h <<
endl;
01011 }
01012
01013
01014
if ( singleton ) {
01015 h <<
" static" <<
endl;
01016 h <<
" void writeConfig()" <<
endl;
01017 h <<
" {" <<
endl;
01018 h <<
" static_cast<KConfigSkeleton*>(self())->writeConfig();" <<
endl;
01019 h <<
" }" <<
endl;
01020 }
01021
01022 h <<
" protected:" <<
endl;
01023
01024
01025
if ( singleton ) {
01026 h <<
" " << className <<
"();" <<
endl;
01027 h <<
" static " << className <<
" *mSelf;" <<
endl <<
endl;
01028 }
01029
01030
01031
if ( !memberVariables.
isEmpty() && memberVariables !=
"private" ) {
01032 h <<
" " << memberVariables <<
":" <<
endl;
01033 }
01034
01035
01036
for (QStringList::ConstIterator it = parameters.begin();
01037 it != parameters.end(); ++it)
01038 {
01039 h <<
" QString mParam" << *it <<
";" <<
endl;
01040 }
01041
01042
QString group;
01043
for( e = entries.
first(); e; e = entries.
next() ) {
01044
if ( e->group() != group ) {
01045 group = e->group();
01046 h <<
endl;
01047 h <<
" // " << group <<
endl;
01048 }
01049 h <<
" " << cppType(e->type()) <<
" " << varName(e->name());
01050
if (!e->param().isEmpty())
01051 {
01052 h <<
QString(
"[%1]").arg(e->paramMax()+1);
01053 }
01054 h <<
";" <<
endl;
01055 }
01056
01057 h <<
endl <<
" private:" <<
endl;
01058
if ( itemAccessors ) {
01059
for( e = entries.
first(); e; e = entries.
next() ) {
01060 h <<
" Item" << itemType( e->type() ) <<
" *" << itemVar( e ) <<
";" <<
endl;
01061 }
01062 }
01063
01064
if (customAddons)
01065 {
01066 h <<
" // Include custom additions" <<
endl;
01067 h <<
" #include \"" << filenameOnly(baseName) <<
"_addons.h\"" <<
endl;
01068 }
01069
01070 h <<
"};" <<
endl <<
endl;
01071
01072
if ( !nameSpace.
isEmpty() ) h <<
"}" <<
endl <<
endl;
01073
01074 h <<
"#endif" <<
endl <<
endl;
01075
01076
01077 header.
close();
01078
01079
QFile implementation( baseDir + implementationFileName );
01080
if ( !implementation.
open( IO_WriteOnly ) ) {
01081 kdError() <<
"Can't open '" << implementationFileName <<
"for writing."
01082 <<
endl;
01083
return 1;
01084 }
01085
01086
QTextStream cpp( &implementation );
01087
01088
01089 cpp <<
"// This file is generated by kconfig_compiler from " << args->
url(0).
fileName() <<
"." <<
endl;
01090 cpp <<
"// All changes you do to this file will be lost." <<
endl <<
endl;
01091
01092 cpp <<
"#include \"" << headerFileName <<
"\"" <<
endl <<
endl;
01093
01094
if ( setUserTexts ) cpp <<
"#include <klocale.h>" <<
endl <<
endl;
01095
01096
01097
for( it = includes.begin(); it != includes.end(); ++it ) {
01098 cpp <<
"#include <" << *it <<
">" <<
endl;
01099 }
01100
01101
01102
if ( singleton )
01103 cpp <<
"#include <kstaticdeleter.h>" <<
endl <<
endl;
01104
01105
if ( !nameSpace.
isEmpty() )
01106 cpp <<
"using namespace " << nameSpace <<
";" <<
endl <<
endl;
01107
01108
01109
if ( singleton ) {
01110 cpp << className <<
" *" << className <<
"::mSelf = 0;" <<
endl;
01111 cpp <<
"static KStaticDeleter<" << className <<
"> staticDeleter;" <<
endl <<
endl;
01112
01113 cpp << className <<
" *" << className <<
"::self()" <<
endl;
01114 cpp <<
"{" <<
endl;
01115 cpp <<
" if ( !mSelf ) {" <<
endl;
01116 cpp <<
" staticDeleter.setObject( mSelf, new " << className <<
"() );" <<
endl;
01117 cpp <<
" mSelf->readConfig();" <<
endl;
01118 cpp <<
" }" <<
endl <<
endl;
01119 cpp <<
" return mSelf;" <<
endl;
01120 cpp <<
"}" <<
endl <<
endl;
01121 }
01122
01123
01124 cpp << className <<
"::" << className <<
"( ";
01125
if (cfgFileNameArg)
01126 cpp <<
" KSharedConfig::Ptr config" << (parameters.isEmpty() ?
" " :
", ");
01127
for (QStringList::ConstIterator it = parameters.begin();
01128 it != parameters.end(); ++it)
01129 {
01130
if (it != parameters.begin())
01131 cpp <<
",";
01132 cpp <<
" const QString &" << *it;
01133 }
01134 cpp <<
" )" <<
endl;
01135
01136 cpp <<
" : " << inherits <<
"(";
01137
if ( !cfgFileName.
isEmpty() ) cpp <<
" \"" << cfgFileName <<
"\" ";
01138
if ( cfgFileNameArg ) cpp <<
" config ";
01139 cpp <<
")" <<
endl;
01140
01141
01142
for (QStringList::ConstIterator it = parameters.begin();
01143 it != parameters.end(); ++it)
01144 {
01145 cpp <<
" , mParam" << *it <<
"(" << *it <<
")" <<
endl;
01146 }
01147
01148 cpp <<
"{" <<
endl;
01149
01150
01151
01152
if ( singleton )
01153 cpp <<
" mSelf = this;" <<
endl;
01154
01155 group = QString::null;
01156
for( e = entries.
first(); e; e = entries.
next() ) {
01157
if ( e->group() != group ) {
01158
if ( !group.isEmpty() ) cpp <<
endl;
01159 group = e->group();
01160 cpp <<
" setCurrentGroup( " << paramString(group, parameters) <<
" );" <<
endl <<
endl;
01161 }
01162
01163
QString key = paramString(e->key(), parameters);
01164
if ( !e->code().isEmpty())
01165 {
01166 cpp << e->code() <<
endl;
01167 }
01168
if ( e->type() ==
"Enum" ) {
01169 cpp <<
" QValueList<KConfigSkeleton::ItemEnum::Choice> values"
01170 << e->name() <<
";" <<
endl;
01171
QValueList<CfgEntry::Choice> choices = e->choices();
01172
QValueList<CfgEntry::Choice>::ConstIterator it;
01173
for( it = choices.
begin(); it != choices.
end(); ++it ) {
01174 cpp <<
" {" <<
endl;
01175 cpp <<
" KConfigSkeleton::ItemEnum::Choice choice;" <<
endl;
01176 cpp <<
" choice.name = \"" << (*it).name <<
"\";" <<
endl;
01177
if ( setUserTexts ) {
01178
if ( !(*it).label.isEmpty() )
01179 cpp <<
" choice.label = i18n(\"" << (*it).label <<
"\");" <<
endl;
01180
if ( !(*it).whatsThis.isEmpty() )
01181 cpp <<
" choice.whatsThis = i18n(\"" << (*it).whatsThis <<
"\");" <<
endl;
01182 }
01183 cpp <<
" values" << e->name() <<
".append( choice );" <<
endl;
01184 cpp <<
" }" <<
endl;
01185 }
01186 }
01187 cpp << itemDeclaration(e);
01188
if (e->param().isEmpty())
01189 {
01190
01191 cpp <<
" " << itemVar(e) <<
" = "
01192 << newItem( e->type(), e->name(),
key, e->defaultValue() ) <<
endl;
01193
01194
if ( !e->minValue().isEmpty() )
01195 cpp <<
" " << itemVar(e) <<
"->setMinValue(" << e->minValue() <<
");" <<
endl;
01196
if ( !e->maxValue().isEmpty() )
01197 cpp <<
" " << itemVar(e) <<
"->setMaxValue(" << e->maxValue() <<
");" <<
endl;
01198
01199
if ( setUserTexts )
01200 cpp << userTextsFunctions( e );
01201
01202 cpp <<
" addItem( " << itemVar(e);
01203
QString quotedName = e->name();
01204 addQuotes( quotedName );
01205
if ( quotedName !=
key ) cpp <<
", \"" << e->name() <<
"\"";
01206 cpp <<
" );" <<
endl;
01207 }
01208
else
01209 {
01210
01211
01212
01213
for(
int i = 0; i <= e->paramMax(); i++)
01214 {
01215
QString defaultStr;
01216
if ( !e->paramDefaultValue(i).isEmpty() )
01217 defaultStr = e->paramDefaultValue(i);
01218
else if ( !e->defaultValue().isEmpty() )
01219 defaultStr = paramString(e->defaultValue(), e, i);
01220
else
01221 defaultStr = defaultValue( e->type() );
01222
01223 cpp <<
" " << itemVar(e) <<
" = "
01224 << newItem( e->type(), e->name(), paramString(key, e, i), defaultStr,
QString(
"[%1]").
arg(i) )
01225 <<
endl;
01226
01227
if ( setUserTexts )
01228 cpp << userTextsFunctions( e );
01229
01230 cpp <<
" addItem( " << itemVar( e ) <<
", \""
01231 << paramString(e->paramName(), e, i) <<
"\" );" <<
endl;
01232 }
01233 }
01234 }
01235
01236 cpp <<
"}" <<
endl <<
endl;
01237
01238
01239 cpp << className <<
"::~" << className <<
"()" <<
endl;
01240 cpp <<
"{" <<
endl;
01241
if ( singleton ) {
01242 cpp <<
" if ( mSelf == this )" <<
endl;
01243 cpp <<
" staticDeleter.setObject( mSelf, 0, false );" <<
endl;
01244 }
01245 cpp <<
"}" <<
endl <<
endl;
01246
01247 implementation.
close();
01248 }