26 #include <tqtextstream.h>
30 #include <kaboutdata.h>
31 #include <kapplication.h>
34 #include <kcmdlineargs.h>
37 #include <ksimpleconfig.h>
38 #include <kstandarddirs.h>
45 {
"directory <dir>",
I18N_NOOP(
"Directory to generate files in"),
"." },
46 {
"+file.kcfg",
I18N_NOOP(
"Input kcfg XML file"), 0 },
47 {
"+file.kcfgc",
I18N_NOOP(
"Code generation options file"), 0 },
55 TQStringList allNames;
56 TQRegExp *validNameRegexp;
70 CfgEntry(
const TQString &group,
const TQString &type,
const TQString &key,
71 const TQString &name,
const TQString &label,
72 const TQString &whatsThis,
const TQString &code,
73 const TQString &defaultValue,
const TQValueList<Choice> &choices,
75 : mGroup( group ), mType( type ), mKey(
key ), mName(
name ),
77 mDefaultValue( defaultValue ),
78 mChoices( choices ), mHidden( hidden )
82 void setGroup(
const TQString &group ) { mGroup = group; }
83 TQString group()
const {
return mGroup; }
85 void setType(
const TQString &type ) { mType = type; }
86 TQString type()
const {
return mType; }
88 void setKey(
const TQString &key ) { mKey =
key; }
89 TQString
key()
const {
return mKey; }
91 void setName(
const TQString &name ) { mName =
name; }
92 TQString
name()
const {
return mName; }
94 void setLabel(
const TQString &label ) { mLabel =
label; }
95 TQString
label()
const {
return mLabel; }
97 void setWhatsThis(
const TQString &whatsThis ) { mWhatsThis =
whatsThis; }
98 TQString
whatsThis()
const {
return mWhatsThis; }
100 void setDefaultValue(
const TQString &d ) { mDefaultValue = d; }
101 TQString defaultValue()
const {
return mDefaultValue; }
103 void setCode(
const TQString &d ) { mCode = d; }
104 TQString code()
const {
return mCode; }
106 void setMinValue(
const TQString &d ) { mMin = d; }
107 TQString minValue()
const {
return mMin; }
109 void setMaxValue(
const TQString &d ) { mMax = d; }
110 TQString maxValue()
const {
return mMax; }
112 void setParam(
const TQString &d ) { mParam = d; }
113 TQString param()
const {
return mParam; }
115 void setParamName(
const TQString &d ) { mParamName = d; }
116 TQString paramName()
const {
return mParamName; }
118 void setParamType(
const TQString &d ) { mParamType = d; }
119 TQString paramType()
const {
return mParamType; }
121 void setChoices(
const TQValueList<Choice> &d ) { mChoices = d; }
122 TQValueList<Choice> choices()
const {
return mChoices; }
124 void setParamValues(
const TQStringList &d ) { mParamValues = d; }
125 TQStringList paramValues()
const {
return mParamValues; }
127 void setParamDefaultValues(
const TQStringList &d ) { mParamDefaultValues = d; }
128 TQString paramDefaultValue(
int i)
const {
return mParamDefaultValues[i]; }
130 void setParamMax(
int d ) { mParamMax = d; }
131 int paramMax()
const {
return mParamMax; }
133 bool hidden()
const {
return mHidden; }
137 kdDebug() <<
"<entry>" <<
endl;
138 kdDebug() <<
" group: " << mGroup <<
endl;
139 kdDebug() <<
" type: " << mType <<
endl;
140 kdDebug() <<
" key: " << mKey <<
endl;
141 kdDebug() <<
" name: " << mName <<
endl;
142 kdDebug() <<
" label: " << mLabel <<
endl;
144 kdDebug() <<
" code: " << mCode <<
endl;
147 if (!param().isEmpty())
149 kdDebug() <<
" param name: "<< mParamName <<
endl;
150 kdDebug() <<
" param type: "<< mParamType <<
endl;
151 kdDebug() <<
" paramvalues: " << mParamValues.join(
":") <<
endl;
153 kdDebug() <<
" default: " << mDefaultValue <<
endl;
154 kdDebug() <<
" hidden: " << mHidden <<
endl;
155 kdDebug() <<
" min: " << mMin <<
endl;
156 kdDebug() <<
" max: " << mMax <<
endl;
157 kdDebug() <<
"</entry>" <<
endl;
168 TQString mDefaultValue;
172 TQValueList<Choice> mChoices;
173 TQStringList mParamValues;
174 TQStringList mParamDefaultValues;
190 static TQString varName(
const TQString &n)
195 result[1] = result[1].upper();
199 result[0] = result[0].lower();
204 static TQString varPath(
const TQString &n)
208 result =
"d->"+varName(n);
216 static TQString enumName(
const TQString &n)
218 TQString result =
"Enum"+n;
219 result[4] = result[4].upper();
223 static TQString setFunction(
const TQString &n,
const TQString &className = TQString())
225 TQString result =
"set"+n;
226 result[3] = result[3].upper();
228 if ( !className.isEmpty() )
229 result = className +
"::" + result;
234 static TQString getFunction(
const TQString &n,
const TQString &className = TQString())
237 result[0] = result[0].lower();
239 if ( !className.isEmpty() )
240 result = className +
"::" + result;
245 static void addQuotes( TQString &s )
247 if ( s.left( 1 ) !=
"\"" ) s.prepend(
"\"" );
248 if ( s.right( 1 ) !=
"\"" ) s.append(
"\"" );
251 static TQString quoteString(
const TQString &s )
254 r.replace(
"\\",
"\\\\" );
255 r.replace(
"\"",
"\\\"" );
256 r.replace(
"\r",
"" );
257 r.replace(
"\n",
"\\n\"\n\"" );
258 return "\"" + r +
"\"";
261 static TQString literalString(
const TQString &s )
264 for(
int i = s.length(); i--;)
265 if (s[i].unicode() > 127) isAscii =
false;
268 return "TQString::fromLatin1( " + quoteString(s) +
" )";
270 return "TQString::fromUtf8( " + quoteString(s) +
" )";
273 static TQString dumpNode(
const TQDomNode &node)
276 TQTextStream s(&msg, IO_WriteOnly );
279 msg = msg.simplifyWhiteSpace();
280 if (msg.length() > 40)
281 return msg.left(37)+
"...";
285 static TQString filenameOnly(TQString path)
287 int i = path.findRev(
'/');
289 return path.mid(i+1);
293 static void preProcessDefault( TQString &defaultValue,
const TQString &name,
294 const TQString &type,
295 const TQValueList<CfgEntry::Choice> &choices,
298 if ( type ==
"String" && !defaultValue.isEmpty() ) {
299 defaultValue = literalString(defaultValue);
301 }
else if ( type ==
"Path" && !defaultValue.isEmpty() ) {
302 defaultValue = literalString( defaultValue );
304 }
else if ( (type ==
"StringList" || type ==
"PathList") && !defaultValue.isEmpty() ) {
305 TQTextStream cpp( &code, IO_WriteOnly | IO_Append );
309 cpp <<
" TQStringList default" <<
name <<
";" <<
endl;
310 TQStringList defaults = TQStringList::split(
",", defaultValue );
311 TQStringList::ConstIterator it;
312 for( it = defaults.begin(); it != defaults.end(); ++it ) {
313 cpp <<
" default" <<
name <<
".append( TQString::fromUtf8( \"" << *it <<
"\" ) );"
316 defaultValue =
"default" +
name;
318 }
else if ( type ==
"Color" && !defaultValue.isEmpty() ) {
319 TQRegExp colorRe(
"\\d+,\\s*\\d+,\\s*\\d+");
320 if (colorRe.exactMatch(defaultValue))
322 defaultValue =
"TQColor( " + defaultValue +
" )";
326 defaultValue =
"TQColor( \"" + defaultValue +
"\" )";
329 }
else if ( type ==
"Enum" ) {
330 if ( !globalEnums ) {
331 TQValueList<CfgEntry::Choice>::ConstIterator it;
332 for( it = choices.begin(); it != choices.end(); ++it ) {
333 if ( (*it).name == defaultValue ) {
334 defaultValue.prepend( enumName(name) +
"::");
340 }
else if ( type ==
"IntList" ) {
341 TQTextStream cpp( &code, IO_WriteOnly | IO_Append );
345 cpp <<
" TQValueList<int> default" <<
name <<
";" <<
endl;
346 TQStringList defaults = TQStringList::split(
",", defaultValue );
347 TQStringList::ConstIterator it;
348 for( it = defaults.begin(); it != defaults.end(); ++it ) {
349 cpp <<
" default" <<
name <<
".append( " << *it <<
" );"
352 defaultValue =
"default" +
name;
357 CfgEntry *parseEntry(
const TQString &group,
const TQDomElement &element )
359 bool defaultCode =
false;
360 TQString type = element.attribute(
"type" );
361 TQString
name = element.attribute(
"name" );
362 TQString
key = element.attribute(
"key" );
363 TQString hidden = element.attribute(
"hidden" );
366 TQString defaultValue;
371 TQValueList<CfgEntry::Choice> choices;
372 TQStringList paramValues;
373 TQStringList paramDefaultValues;
379 for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
380 TQDomElement e = n.toElement();
381 TQString tag = e.tagName();
382 if ( tag ==
"label" )
label = e.text();
384 else if ( tag ==
"min" ) minValue = e.text();
385 else if ( tag ==
"max" ) maxValue = e.text();
386 else if ( tag ==
"code" ) code = e.text();
387 else if ( tag ==
"parameter" )
389 param = e.attribute(
"name" );
390 paramType = e.attribute(
"type" );
391 if ( param.isEmpty() ) {
392 kdError() <<
"Parameter must have a name: " << dumpNode(e) <<
endl;
395 if ( paramType.isEmpty() ) {
396 kdError() <<
"Parameter must have a type: " << dumpNode(e) <<
endl;
399 if ((paramType ==
"Int") || (paramType ==
"UInt"))
402 paramMax = e.attribute(
"max").toInt(&ok);
405 kdError() <<
"Integer parameter must have a maximum (e.g. max=\"0\"): " << dumpNode(e) <<
endl;
409 else if (paramType ==
"Enum")
412 for ( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
413 TQDomElement e2 = n2.toElement();
414 if (e2.tagName() ==
"values")
417 for ( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) {
418 TQDomElement e3 = n3.toElement();
419 if (e3.tagName() ==
"value")
421 paramValues.append( e3.text() );
427 if (paramValues.isEmpty())
429 kdError() <<
"No values specified for parameter '" << param <<
"'." <<
endl;
432 paramMax = paramValues.count()-1;
436 kdError() <<
"Parameter '" << param <<
"' has type " << paramType <<
" but must be of type int, uint or Enum." <<
endl;
440 else if ( tag ==
"default" )
442 if (e.attribute(
"param").isEmpty())
444 defaultValue = e.text();
445 if (e.attribute(
"code" ) ==
"true")
449 else if ( tag ==
"choices" ) {
451 for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
452 TQDomElement e2 = n2.toElement();
453 if ( e2.tagName() ==
"choice" ) {
455 CfgEntry::Choice choice;
456 choice.name = e2.attribute(
"name" );
457 if ( choice.name.isEmpty() ) {
458 kdError() <<
"Tag <choice> requires attribute 'name'." <<
endl;
460 for( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) {
461 TQDomElement e3 = n3.toElement();
462 if ( e3.tagName() ==
"label" ) choice.label = e3.text();
463 if ( e3.tagName() ==
"whatsthis" ) choice.whatsThis = e3.text();
465 choices.append( choice );
471 bool nameIsEmpty =
name.isEmpty();
472 if ( nameIsEmpty &&
key.isEmpty() ) {
473 kdError() <<
"Entry must have a name or a key: " << dumpNode(element) <<
endl;
477 if (
key.isEmpty() ) {
483 name.replace(
" ", TQString() );
484 }
else if (
name.contains(
' ' ) ) {
485 kdWarning()<<
"Entry '"<<
name<<
"' contains spaces! <name> elements can't contain speces!"<<
endl;
489 if (
name.contains(
"$("))
499 if (!param.isEmpty())
501 kdError() <<
"Name must contain '$(" << param <<
")': " <<
name <<
endl;
506 if (
label.isEmpty() ) {
510 if ( type.isEmpty() ) type =
"String";
512 if (!param.isEmpty())
516 name.replace(
"$("+param+
")", TQString());
518 for(
int i = 0; i <= paramMax; i++)
520 paramDefaultValues.append(TQString());
524 for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
525 TQDomElement e = n.toElement();
526 TQString tag = e.tagName();
527 if ( tag ==
"default" )
529 TQString index = e.attribute(
"param");
534 int i = index.toInt(&ok);
537 i = paramValues.findIndex(index);
540 kdError() <<
"Index '" << index <<
"' for default value is unknown." <<
endl;
545 if ((i < 0) || (i > paramMax))
547 kdError() <<
"Index '" << i <<
"' for default value is out of range [0, "<< paramMax<<
"]." <<
endl;
551 TQString tmpDefaultValue = e.text();
553 if (e.attribute(
"code" ) !=
"true")
554 preProcessDefault(tmpDefaultValue, name, type, choices, code);
556 paramDefaultValues[i] = tmpDefaultValue;
561 if (!validNameRegexp->exactMatch(name))
564 kdError() <<
"The key '" <<
key <<
"' can not be used as name for the entry because "
565 "it is not a valid name. You need to specify a valid name for this entry." <<
endl;
567 kdError() <<
"The name '" <<
name <<
"' is not a valid name for an entry." <<
endl;
571 if (allNames.contains(name))
574 kdError() <<
"The key '" <<
key <<
"' can not be used as name for the entry because "
575 "it does not result in a unique name. You need to specify a unique name for this entry." <<
endl;
580 allNames.append(name);
584 preProcessDefault(defaultValue, name, type, choices, code);
587 CfgEntry *result =
new CfgEntry( group, type, key, name, label, whatsThis,
588 code, defaultValue, choices,
590 if (!param.isEmpty())
592 result->setParam(param);
593 result->setParamName(paramName);
594 result->setParamType(paramType);
595 result->setParamValues(paramValues);
596 result->setParamDefaultValues(paramDefaultValues);
597 result->setParamMax(paramMax);
599 result->setMinValue(minValue);
600 result->setMaxValue(maxValue);
608 TQString param(
const TQString &type )
610 if ( type ==
"String" )
return "const TQString &";
611 else if ( type ==
"StringList" )
return "const TQStringList &";
612 else if ( type ==
"Font" )
return "const TQFont &";
613 else if ( type ==
"Rect" )
return "const TQRect &";
614 else if ( type ==
"Size" )
return "const TQSize &";
615 else if ( type ==
"Color" )
return "const TQColor &";
616 else if ( type ==
"Point" )
return "const TQPoint &";
617 else if ( type ==
"Int" )
return "int";
618 else if ( type ==
"UInt" )
return "uint";
619 else if ( type ==
"Bool" )
return "bool";
620 else if ( type ==
"Double" )
return "double";
621 else if ( type ==
"DateTime" )
return "const TQDateTime &";
622 else if ( type ==
"Int64" )
return "TQ_INT64";
623 else if ( type ==
"UInt64" )
return "TQ_UINT64";
624 else if ( type ==
"IntList" )
return "const TQValueList<int> &";
625 else if ( type ==
"Enum" )
return "int";
626 else if ( type ==
"Path" )
return "const TQString &";
627 else if ( type ==
"PathList" )
return "const TQStringList &";
628 else if ( type ==
"Password" )
return "const TQString &";
630 kdError() <<
"kconfig_compiler does not support type \""<< type <<
"\""<<
endl;
638 TQString cppType(
const TQString &type )
640 if ( type ==
"String" )
return "TQString";
641 else if ( type ==
"StringList" )
return "TQStringList";
642 else if ( type ==
"Font" )
return "TQFont";
643 else if ( type ==
"Rect" )
return "TQRect";
644 else if ( type ==
"Size" )
return "TQSize";
645 else if ( type ==
"Color" )
return "TQColor";
646 else if ( type ==
"Point" )
return "TQPoint";
647 else if ( type ==
"Int" )
return "int";
648 else if ( type ==
"UInt" )
return "uint";
649 else if ( type ==
"Bool" )
return "bool";
650 else if ( type ==
"Double" )
return "double";
651 else if ( type ==
"DateTime" )
return "TQDateTime";
652 else if ( type ==
"Int64" )
return "TQ_INT64";
653 else if ( type ==
"UInt64" )
return "TQ_UINT64";
654 else if ( type ==
"IntList" )
return "TQValueList<int>";
655 else if ( type ==
"Enum" )
return "int";
656 else if ( type ==
"Path" )
return "TQString";
657 else if ( type ==
"PathList" )
return "TQStringList";
658 else if ( type ==
"Password" )
return "TQString";
660 kdError()<<
"kconfig_compiler does not support type \""<< type <<
"\""<<
endl;
665 TQString defaultValue(
const TQString &type )
667 if ( type ==
"String" )
return "\"\"";
668 else if ( type ==
"StringList" )
return "TQStringList()";
669 else if ( type ==
"Font" )
return "KGlobalSettings::generalFont()";
670 else if ( type ==
"Rect" )
return "TQRect()";
671 else if ( type ==
"Size" )
return "TQSize()";
672 else if ( type ==
"Color" )
return "TQColor(128, 128, 128)";
673 else if ( type ==
"Point" )
return "TQPoint()";
674 else if ( type ==
"Int" )
return "0";
675 else if ( type ==
"UInt" )
return "0";
676 else if ( type ==
"Bool" )
return "false";
677 else if ( type ==
"Double" )
return "0.0";
678 else if ( type ==
"DateTime" )
return "TQDateTime()";
679 else if ( type ==
"Int64" )
return "0";
680 else if ( type ==
"UInt64" )
return "0";
681 else if ( type ==
"IntList" )
return "TQValueList<int>()";
682 else if ( type ==
"Enum" )
return "0";
683 else if ( type ==
"Path" )
return "\"\"";
684 else if ( type ==
"PathList" )
return "TQStringList()";
685 else if ( type ==
"Password" )
return "\"\"";
687 kdWarning()<<
"Error, kconfig_compiler doesn't support the \""<< type <<
"\" type!"<<
endl;
692 TQString itemType(
const TQString &type )
697 t.replace( 0, 1, t.left( 1 ).upper() );
702 static TQString itemDeclaration(
const CfgEntry *e)
707 TQString fCap = e->name();
708 fCap[0] = fCap[0].upper();
709 return " KConfigSkeleton::Item"+itemType( e->type() ) +
711 ( (!e->param().isEmpty())?(TQString(
"[%1]").arg(e->paramMax()+1)) : TQString()) +
718 static TQString itemVar(
const CfgEntry *e)
725 result =
"m" + e->name() +
"Item";
726 result[1] = result[1].upper();
730 result = e->name() +
"Item";
731 result[0] = result[0].lower();
736 result =
"item" + e->name();
737 result[4] = result[4].upper();
742 static TQString itemPath(
const CfgEntry *e)
746 result =
"d->"+itemVar(e);
754 TQString newItem(
const TQString &type,
const TQString &name,
const TQString &key,
755 const TQString &defaultValue,
const TQString ¶m = TQString())
757 TQString t =
"new KConfigSkeleton::Item" + itemType( type ) +
758 "( currentGroup(), " +
key +
", " + varPath( name ) + param;
759 if ( type ==
"Enum" ) t +=
", values" +
name;
760 if ( !defaultValue.isEmpty() ) {
762 if ( type ==
"String" ) t += defaultValue;
763 else t+= defaultValue;
770 TQString paramString(
const TQString &s,
const CfgEntry *e,
int i)
773 TQString needle =
"$("+e->param()+
")";
774 if (result.contains(needle))
777 if (e->paramType() ==
"Enum")
779 tmp = e->paramValues()[i];
783 tmp = TQString::number(i);
786 result.replace(needle, tmp);
791 TQString paramString(
const TQString &group,
const TQValueList<Param> ¶meters)
793 TQString paramString = group;
796 for (TQValueList<Param>::ConstIterator it = parameters.begin();
797 it != parameters.end(); ++it)
799 if (paramString.contains(
"$("+(*it).name+
")"))
802 tmp.sprintf(
"%%%d", i++);
803 paramString.replace(
"$("+(*it).name+
")", tmp);
804 arguments +=
".arg( mParam"+(*it).name+
" )";
807 if (arguments.isEmpty())
808 return "TQString::fromLatin1( \""+group+
"\" )";
810 return "TQString::fromLatin1( \""+paramString+
"\" )"+arguments;
814 TQString userTextsFunctions( CfgEntry *e, TQString itemVarStr=TQString(), TQString i=TQString() )
817 if (itemVarStr.isNull()) itemVarStr=itemPath(e);
818 if ( !e->label().isEmpty() ) {
819 txt +=
" " + itemVarStr +
"->setLabel( i18n(";
820 if ( !e->param().isEmpty() )
821 txt += quoteString(e->label().replace(
"$("+e->param()+
")", i));
823 txt+= quoteString(e->label());
826 if ( !e->whatsThis().isEmpty() ) {
827 txt +=
" " + itemVarStr +
"->setWhatsThis( i18n(";
828 if ( !e->param().isEmpty() )
829 txt += quoteString(e->whatsThis().replace(
"$("+e->param()+
")", i));
831 txt+= quoteString(e->whatsThis());
840 TQString memberAccessorBody( CfgEntry *e )
843 TQTextStream out(&result, IO_WriteOnly);
844 TQString n = e->name();
845 TQString t = e->type();
847 out <<
"return " << This << varPath(n);
848 if (!e->param().isEmpty()) out <<
"[i]";
857 TQString memberMutatorBody( CfgEntry *e )
860 TQTextStream out(&result, IO_WriteOnly);
861 TQString n = e->name();
862 TQString t = e->type();
864 if (!e->minValue().isEmpty())
866 out <<
"if (v < " << e->minValue() <<
")" <<
endl;
868 out <<
" kdDebug() << \"" << setFunction(n);
869 out <<
": value \" << v << \" is less than the minimum value of ";
870 out << e->minValue()<<
"\" << endl;" <<
endl;
871 out <<
" v = " << e->minValue() <<
";" <<
endl;
875 if (!e->maxValue().isEmpty())
877 out <<
endl <<
"if (v > " << e->maxValue() <<
")" <<
endl;
879 out <<
" kdDebug() << \"" << setFunction(n);
880 out <<
": value \" << v << \" is greater than the maximum value of ";
881 out << e->maxValue()<<
"\" << endl;" <<
endl;
882 out <<
" v = " << e->maxValue() <<
";" <<
endl;
886 out <<
"if (!" << This <<
"isImmutable( TQString::fromLatin1( \"";
887 if (!e->param().isEmpty())
889 out << e->paramName().replace(
"$("+e->param()+
")",
"%1") <<
"\" ).arg( ";
890 if ( e->paramType() ==
"Enum" ) {
891 out <<
"TQString::fromLatin1( ";
894 out << enumName(e->param()) <<
"ToString[i]";
896 out << enumName(e->param()) <<
"::enumToString[i]";
910 out <<
" ))" <<
endl;
911 out <<
" " << This << varPath(n);
912 if (!e->param().isEmpty())
914 out <<
" = v;" <<
endl;
922 TQString itemAccessorBody( CfgEntry *e )
925 TQTextStream out(&result, IO_WriteOnly);
927 out <<
"return " << itemPath(e);
928 if (!e->param().isEmpty()) out <<
"[i]";
935 TQString indent(TQString text,
int spaces)
938 TQTextStream out(&result, IO_WriteOnly);
939 TQTextStream in(&text, IO_ReadOnly);
941 while ( !in.atEnd() )
943 currLine = in.readLine();
944 if (!currLine.isEmpty())
945 for (
int i=0; i < spaces; i++)
947 out << currLine <<
endl;
953 int main(
int argc,
char **argv )
956 I18N_NOOP(
"KConfig Compiler") , KAboutData::License_LGPL );
957 aboutData.addAuthor(
"Cornelius Schumacher", 0,
"schumacher@kde.org" );
958 aboutData.addAuthor(
"Waldo Bastian", 0,
"bastian@kde.org" );
959 aboutData.addAuthor(
"Zack Rusin", 0,
"zack@kde.org" );
960 aboutData.addCredit(
"Reinhold Kainhofer",
"Fix for parametrized entries",
961 "reinhold@kainhofer.com",
"http://reinhold.kainhofer.com" );
962 aboutData.addCredit(
"Duncan Mac-Vicar P.",
"dpointer support",
963 "duncan@kde.org",
"http://www.mac-vicar.com/~duncan" );
972 if ( args->
count() < 2 ) {
976 if ( args->
count() > 2 ) {
981 validNameRegexp =
new TQRegExp(
"[a-zA-Z_][a-zA-Z0-9_]*");
983 TQString baseDir = TQFile::decodeName(args->
getOption(
"directory"));
984 if (!baseDir.endsWith(
"/"))
987 TQString inputFilename = args->
url( 0 ).
path();
988 TQString codegenFilename = args->
url( 1 ).
path();
990 if (!codegenFilename.endsWith(
".kcfgc"))
992 kdError() <<
"Codegen options file must have extension .kcfgc" <<
endl;
996 baseName = baseName.left(baseName.length() - 6);
1000 TQString nameSpace = codegenConfig.readEntry(
"NameSpace");
1001 TQString className = codegenConfig.readEntry(
"ClassName");
1002 TQString inherits = codegenConfig.readEntry(
"Inherits");
1003 TQString visibility = codegenConfig.readEntry(
"Visibility");
1004 if (!visibility.isEmpty()) visibility+=
" ";
1005 bool singleton = codegenConfig.readBoolEntry(
"Singleton",
false);
1006 bool staticAccessors = singleton;
1008 bool customAddons = codegenConfig.readBoolEntry(
"CustomAdditions");
1009 TQString memberVariables = codegenConfig.readEntry(
"MemberVariables");
1010 TQStringList headerIncludes = codegenConfig.readListEntry(
"IncludeFiles");
1011 TQStringList mutators = codegenConfig.readListEntry(
"Mutators");
1012 bool allMutators =
false;
1013 if ((mutators.count() == 1) && (mutators[0].lower() ==
"true"))
1015 itemAccessors = codegenConfig.readBoolEntry(
"ItemAccessors",
false );
1016 bool setUserTexts = codegenConfig.readBoolEntry(
"SetUserTexts",
false );
1018 globalEnums = codegenConfig.readBoolEntry(
"GlobalEnums",
false );
1020 dpointer = (memberVariables ==
"dpointer");
1022 TQFile input( inputFilename );
1028 if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
1030 kdError() <<
"Parse error in " << args->
url( 0 ).
fileName() <<
", line " << errorRow <<
", col " << errorCol <<
": " << errorMsg <<
endl;
1034 TQDomElement cfgElement = doc.documentElement();
1036 if ( cfgElement.isNull() ) {
1041 TQString cfgFileName;
1042 bool cfgFileNameArg =
false;
1043 TQValueList<Param> parameters;
1044 TQStringList includes;
1046 TQPtrList<CfgEntry> entries;
1047 entries.setAutoDelete(
true );
1050 for ( n = cfgElement.firstChild(); !n.isNull(); n = n.nextSibling() ) {
1051 TQDomElement e = n.toElement();
1053 TQString tag = e.tagName();
1055 if ( tag ==
"include" ) {
1056 TQString includeFile = e.text();
1057 if (!includeFile.isEmpty())
1058 includes.append(includeFile);
1060 }
else if ( tag ==
"kcfgfile" ) {
1061 cfgFileName = e.attribute(
"name" );
1062 cfgFileNameArg = e.attribute(
"arg" ).lower() ==
"true";
1064 for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
1065 TQDomElement e2 = n2.toElement();
1066 if ( e2.tagName() ==
"parameter" ) {
1068 p.name = e2.attribute(
"name" );
1069 p.type = e2.attribute(
"type" );
1070 if (p.type.isEmpty())
1072 parameters.append( p );
1076 }
else if ( tag ==
"group" ) {
1077 TQString group = e.attribute(
"name" );
1078 if ( group.isEmpty() ) {
1083 for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
1084 TQDomElement e2 = n2.toElement();
1085 if ( e2.tagName() !=
"entry" )
continue;
1086 CfgEntry *entry = parseEntry( group, e2 );
1087 if ( entry ) entries.append( entry );
1096 if ( inherits.isEmpty() ) inherits =
"KConfigSkeleton";
1098 if ( className.isEmpty() ) {
1103 if ( singleton && !parameters.isEmpty() ) {
1104 kdError() <<
"Singleton class can not have parameters" <<
endl;
1108 if ( !cfgFileName.isEmpty() && cfgFileNameArg)
1110 kdError() <<
"Having both a fixed filename and a filename as argument is not possible." <<
endl;
1114 if ( entries.isEmpty() ) {
1120 for( cfg = entries.first(); cfg; cfg = entries.next() ) {
1125 TQString headerFileName = baseName +
".h";
1126 TQString implementationFileName = baseName +
".cpp";
1127 TQString cppPreamble;
1129 TQFile header( baseDir + headerFileName );
1130 if ( !header.open( IO_WriteOnly ) ) {
1131 kdError() <<
"Can't open '" << headerFileName <<
"' for writing." <<
endl;
1135 TQTextStream h( &header );
1137 h <<
"// This file is generated by kconfig_compiler from " << args->
url(0).
fileName() <<
"." <<
endl;
1138 h <<
"// All changes you do to this file will be lost." <<
endl;
1140 h <<
"#ifndef " << ( !nameSpace.isEmpty() ? nameSpace.upper() +
"_" :
"" )
1141 << className.upper() <<
"_H" <<
endl;
1142 h <<
"#define " << ( !nameSpace.isEmpty() ? nameSpace.upper() +
"_" :
"" )
1143 << className.upper() <<
"_H" <<
endl <<
endl;
1146 TQStringList::ConstIterator it;
1147 for( it = headerIncludes.begin(); it != headerIncludes.end(); ++it ) {
1148 h <<
"#include <" << *it <<
">" <<
endl;
1151 if ( headerIncludes.count() > 0 ) h <<
endl;
1153 if ( !singleton && cfgFileNameArg && parameters.isEmpty() )
1154 h <<
"#include <kglobal.h>" <<
endl;
1156 h <<
"#include <kconfigskeleton.h>" <<
endl;
1157 h <<
"#include <kdebug.h>" <<
endl <<
endl;
1160 for( it = includes.begin(); it != includes.end(); ++it ) {
1161 h <<
"#include <" << *it <<
">" <<
endl;
1165 if ( !nameSpace.isEmpty() )
1166 h <<
"namespace " << nameSpace <<
" {" <<
endl <<
endl;
1170 h <<
"class " << className <<
"Private;" <<
endl <<
endl;
1173 h <<
"class " << visibility << className <<
" : public " << inherits <<
endl;
1175 h <<
" public:" <<
endl;
1179 for( e = entries.first(); e; e = entries.next() ) {
1180 TQValueList<CfgEntry::Choice> choices = e->choices();
1181 if ( !choices.isEmpty() ) {
1182 TQStringList values;
1183 TQValueList<CfgEntry::Choice>::ConstIterator itChoice;
1184 for( itChoice = choices.begin(); itChoice != choices.end(); ++itChoice ) {
1185 values.append( (*itChoice).name );
1187 if ( globalEnums ) {
1188 h <<
" enum { " << values.join(
", " ) <<
" };" <<
endl;
1190 h <<
" class " << enumName(e->name()) <<
endl;
1192 h <<
" public:" <<
endl;
1193 h <<
" enum type { " << values.join(
", " ) <<
", COUNT };" <<
endl;
1197 TQStringList values = e->paramValues();
1198 if ( !values.isEmpty() ) {
1199 if ( globalEnums ) {
1200 h <<
" enum { " << values.join(
", " ) <<
" };" <<
endl;
1201 h <<
" static const char* const " << enumName(e->param()) <<
"ToString[];" <<
endl;
1202 cppPreamble +=
"const char* const " + className +
"::" + enumName(e->param()) +
"ToString[] = " +
1203 "{ \"" + values.join(
"\", \"" ) +
"\" };\n";
1205 h <<
" class " << enumName(e->param()) <<
endl;
1207 h <<
" public:" <<
endl;
1208 h <<
" enum type { " << values.join(
", " ) <<
", COUNT };" <<
endl;
1209 h <<
" static const char* const enumToString[];" <<
endl;
1211 cppPreamble +=
"const char* const " + className +
"::" + enumName(e->param()) +
"::enumToString[] = " +
1212 "{ \"" + values.join(
"\", \"" ) +
"\" };\n";
1221 h <<
" " << className <<
"(";
1223 h <<
" KSharedConfig::Ptr config" << (parameters.isEmpty() ?
" = KGlobal::sharedConfig()" :
", ");
1224 for (TQValueList<Param>::ConstIterator it = parameters.begin();
1225 it != parameters.end(); ++it)
1227 if (it != parameters.begin())
1229 h <<
" " << param((*it).type) <<
" " << (*it).name;
1233 h <<
" static " << className <<
" *self();" <<
endl;
1235 h <<
" static void instance(const char * cfgfilename);" <<
endl;
1239 h <<
" ~" << className <<
"();" <<
endl <<
endl;
1242 if (staticAccessors)
1247 for( e = entries.first(); e; e = entries.next() ) {
1248 TQString n = e->name();
1249 TQString t = e->type();
1252 if (allMutators || mutators.contains(n))
1254 h <<
" /**" <<
endl;
1255 h <<
" Set " << e->label() <<
endl;
1257 if (staticAccessors)
1258 h <<
" static" <<
endl;
1259 h <<
" void " << setFunction(n) <<
"( ";
1260 if (!e->param().isEmpty())
1261 h << cppType(e->paramType()) <<
" i, ";
1262 h << param( t ) <<
" v )";
1268 h << indent(memberMutatorBody(e), 6 );
1278 h <<
" /**" <<
endl;
1279 h <<
" Get " << e->label() <<
endl;
1281 if (staticAccessors)
1282 h <<
" static" <<
endl;
1283 h <<
" " << cppType(t) <<
" " << getFunction(n) <<
"(";
1284 if (!e->param().isEmpty())
1285 h <<
" " << cppType(e->paramType()) <<
" i ";
1292 h << indent(memberAccessorBody(e), 6 );
1301 if ( itemAccessors ) {
1303 h <<
" /**" <<
endl;
1304 h <<
" Get Item object corresponding to " << n <<
"()"
1307 h <<
" Item" << itemType( e->type() ) <<
" *"
1308 << getFunction( n ) <<
"Item(";
1309 if (!e->param().isEmpty()) {
1310 h <<
" " << cppType(e->paramType()) <<
" i ";
1316 h << indent( itemAccessorBody(e), 6);
1330 h <<
" static" <<
endl;
1331 h <<
" void writeConfig()" <<
endl;
1333 h <<
" static_cast<KConfigSkeleton*>(self())->writeConfig();" <<
endl;
1337 h <<
" protected:" <<
endl;
1341 h <<
" " << className <<
"(";
1342 if ( cfgFileNameArg )
1343 h <<
"const char *arg";
1345 h <<
" static " << className <<
" *mSelf;" <<
endl <<
endl;
1349 if ( !memberVariables.isEmpty() && memberVariables !=
"private" && memberVariables !=
"dpointer") {
1350 h <<
" " << memberVariables <<
":" <<
endl;
1354 for (TQValueList<Param>::ConstIterator it = parameters.begin();
1355 it != parameters.end(); ++it)
1357 h <<
" " << cppType((*it).type) <<
" mParam" << (*it).name <<
";" <<
endl;
1360 if ( memberVariables !=
"dpointer" )
1363 for( e = entries.first(); e; e = entries.next() ) {
1364 if ( e->group() != group ) {
1367 h <<
" // " << group <<
endl;
1369 h <<
" " << cppType(e->type()) <<
" " << varName(e->name());
1370 if (!e->param().isEmpty())
1372 h << TQString(
"[%1]").arg(e->paramMax()+1);
1378 if ( itemAccessors ) {
1379 for( e = entries.first(); e; e = entries.next() ) {
1380 h <<
" Item" << itemType( e->type() ) <<
" *" << itemVar( e );
1381 if (!e->param().isEmpty() ) h << TQString(
"[%1]").arg( e->paramMax()+1 );
1390 h <<
" private:" <<
endl;
1391 h <<
" " + className +
"Private *d;" <<
endl;
1396 h <<
" // Include custom additions" <<
endl;
1397 h <<
" #include \"" << filenameOnly(baseName) <<
"_addons.h\"" <<
endl;
1402 if ( !nameSpace.isEmpty() ) h <<
"}" <<
endl <<
endl;
1409 TQFile implementation( baseDir + implementationFileName );
1410 if ( !implementation.open( IO_WriteOnly ) ) {
1411 kdError() <<
"Can't open '" << implementationFileName <<
"' for writing."
1416 TQTextStream cpp( &implementation );
1419 cpp <<
"// This file is generated by kconfig_compiler from " << args->
url(0).
fileName() <<
"." <<
endl;
1420 cpp <<
"// All changes you do to this file will be lost." <<
endl <<
endl;
1422 cpp <<
"#include \"" << headerFileName <<
"\"" <<
endl <<
endl;
1424 if ( setUserTexts ) cpp <<
"#include <klocale.h>" <<
endl <<
endl;
1428 cpp <<
"#include <kstaticdeleter.h>" <<
endl <<
endl;
1429 if ( singleton && cfgFileNameArg )
1430 cpp <<
"#include <kdebug.h>" <<
endl <<
endl;
1432 if ( !nameSpace.isEmpty() )
1433 cpp <<
"using namespace " << nameSpace <<
";" <<
endl <<
endl;
1440 cpp <<
"class " << className <<
"Private" <<
endl;
1442 cpp <<
" public:" <<
endl;
1443 for( e = entries.first(); e; e = entries.next() ) {
1444 if ( e->group() != group ) {
1447 cpp <<
" // " << group <<
endl;
1449 cpp <<
" " << cppType(e->type()) <<
" " << varName(e->name());
1450 if (!e->param().isEmpty())
1452 cpp << TQString(
"[%1]").arg(e->paramMax()+1);
1456 cpp <<
endl <<
" // items" <<
endl;
1457 for( e = entries.first(); e; e = entries.next() ) {
1458 cpp <<
" KConfigSkeleton::Item" << itemType( e->type() ) <<
" *" << itemVar( e );
1459 if (!e->param().isEmpty() ) cpp << TQString(
"[%1]").arg( e->paramMax()+1 );
1468 cpp << className <<
" *" << className <<
"::mSelf = 0;" <<
endl;
1469 cpp <<
"static KStaticDeleter<" << className <<
"> static" << className <<
"Deleter;" <<
endl <<
endl;
1471 cpp << className <<
" *" << className <<
"::self()" <<
endl;
1473 if ( cfgFileNameArg ) {
1474 cpp <<
" if (!mSelf)" <<
endl;
1475 cpp <<
" kdFatal() << \"you need to call " << className <<
"::instance before using\" << endl;" <<
endl;
1477 cpp <<
" if ( !mSelf ) {" <<
endl;
1478 cpp <<
" static" << className <<
"Deleter.setObject( mSelf, new " << className <<
"() );" <<
endl;
1479 cpp <<
" mSelf->readConfig();" <<
endl;
1482 cpp <<
" return mSelf;" <<
endl;
1485 if ( cfgFileNameArg ) {
1486 cpp <<
"void " << className <<
"::instance(const char *cfgfilename)" <<
endl;
1488 cpp <<
" if (mSelf) {" <<
endl;
1489 cpp <<
" kdError() << \"" << className <<
"::instance called after the first use - ignoring\" << endl;" <<
endl;
1490 cpp <<
" return;" <<
endl;
1491 cpp <<
" }" <<
endl;
1492 cpp <<
" static" << className <<
"Deleter.setObject( mSelf, new " << className <<
"(cfgfilename) );" <<
endl;
1493 cpp <<
" mSelf->readConfig();" <<
endl;
1498 if ( !cppPreamble.isEmpty() )
1499 cpp << cppPreamble <<
endl;
1502 cpp << className <<
"::" << className <<
"( ";
1503 if ( cfgFileNameArg ) {
1505 cpp <<
" KSharedConfig::Ptr config";
1507 cpp <<
" const char *config";
1508 cpp << (parameters.isEmpty() ?
" " :
", ");
1511 for (TQValueList<Param>::ConstIterator it = parameters.begin();
1512 it != parameters.end(); ++it)
1514 if (it != parameters.begin())
1516 cpp <<
" " << param((*it).type) <<
" " << (*it).name;
1518 cpp <<
" )" <<
endl;
1520 cpp <<
" : " << inherits <<
"(";
1521 if ( !cfgFileName.isEmpty() ) cpp <<
" TQString::fromLatin1( \"" << cfgFileName <<
"\" ";
1522 if ( cfgFileNameArg ) cpp <<
" config ";
1523 if ( !cfgFileName.isEmpty() ) cpp <<
") ";
1527 for (TQValueList<Param>::ConstIterator it = parameters.begin();
1528 it != parameters.end(); ++it)
1530 cpp <<
" , mParam" << (*it).name <<
"(" << (*it).name <<
")" <<
endl;
1536 cpp <<
" d = new " + className +
"Private;" <<
endl;
1540 cpp <<
" mSelf = this;" <<
endl;
1543 for( e = entries.first(); e; e = entries.next() ) {
1544 if ( e->group() != group ) {
1545 if ( !group.isEmpty() ) cpp <<
endl;
1547 cpp <<
" setCurrentGroup( " << paramString(group, parameters) <<
" );" <<
endl <<
endl;
1550 TQString
key = paramString(e->key(), parameters);
1551 if ( !e->code().isEmpty())
1553 cpp << e->code() <<
endl;
1555 if ( e->type() ==
"Enum" ) {
1556 cpp <<
" TQValueList<KConfigSkeleton::ItemEnum::Choice> values"
1557 << e->name() <<
";" <<
endl;
1558 TQValueList<CfgEntry::Choice> choices = e->choices();
1559 TQValueList<CfgEntry::Choice>::ConstIterator it;
1560 for( it = choices.begin(); it != choices.end(); ++it ) {
1561 cpp <<
" {" <<
endl;
1562 cpp <<
" KConfigSkeleton::ItemEnum::Choice choice;" <<
endl;
1563 cpp <<
" choice.name = TQString::fromLatin1( \"" << (*it).name <<
"\" );" <<
endl;
1564 if ( setUserTexts ) {
1565 if ( !(*it).label.isEmpty() )
1566 cpp <<
" choice.label = i18n(" << quoteString((*it).label) <<
");" <<
endl;
1567 if ( !(*it).whatsThis.isEmpty() )
1568 cpp <<
" choice.whatsThis = i18n(" << quoteString((*it).whatsThis) <<
");" <<
endl;
1570 cpp <<
" values" << e->name() <<
".append( choice );" <<
endl;
1571 cpp <<
" }" <<
endl;
1576 cpp << itemDeclaration(e);
1578 if (e->param().isEmpty())
1581 cpp <<
" " << itemPath(e) <<
" = "
1582 << newItem( e->type(), e->name(), key, e->defaultValue() ) <<
endl;
1584 if ( !e->minValue().isEmpty() )
1585 cpp <<
" " << itemPath(e) <<
"->setMinValue(" << e->minValue() <<
");" <<
endl;
1586 if ( !e->maxValue().isEmpty() )
1587 cpp <<
" " << itemPath(e) <<
"->setMaxValue(" << e->maxValue() <<
");" <<
endl;
1590 cpp << userTextsFunctions( e );
1592 cpp <<
" addItem( " << itemPath(e);
1593 TQString quotedName = e->name();
1594 addQuotes( quotedName );
1595 if ( quotedName != key ) cpp <<
", TQString::fromLatin1( \"" << e->name() <<
"\" )";
1596 cpp <<
" );" <<
endl;
1601 for(
int i = 0; i <= e->paramMax(); i++)
1603 TQString defaultStr;
1604 TQString itemVarStr(itemPath(e)+TQString(
"[%1]").arg(i));
1606 if ( !e->paramDefaultValue(i).isEmpty() )
1607 defaultStr = e->paramDefaultValue(i);
1608 else if ( !e->defaultValue().isEmpty() )
1609 defaultStr = paramString(e->defaultValue(), e, i);
1611 defaultStr = defaultValue( e->type() );
1613 cpp <<
" " << itemVarStr <<
" = "
1614 << newItem( e->type(), e->name(), paramString(key, e, i), defaultStr, TQString(
"[%1]").arg(i) )
1618 cpp << userTextsFunctions( e, itemVarStr, e->paramName() );
1624 cpp <<
" addItem( " << itemVarStr <<
", TQString::fromLatin1( \"";
1625 if ( e->paramType()==
"Enum" )
1626 cpp << e->paramName().replace(
"$("+e->param()+
")",
"%1").arg(e->paramValues()[i] );
1628 cpp << e->paramName().replace(
"$("+e->param()+
")",
"%1").arg(i);
1629 cpp <<
"\" ) );" <<
endl;
1639 for( e = entries.first(); e; e = entries.next() )
1641 TQString n = e->name();
1642 TQString t = e->type();
1645 if (allMutators || mutators.contains(n))
1647 cpp <<
"void " << setFunction(n, className) <<
"( ";
1648 if (!e->param().isEmpty())
1649 cpp << cppType(e->paramType()) <<
" i, ";
1650 cpp << param( t ) <<
" v )" <<
endl;
1654 cpp << indent(memberMutatorBody(e), 6);
1659 cpp << cppType(t) <<
" " << getFunction(n, className) <<
"(";
1660 if (!e->param().isEmpty())
1661 cpp <<
" " << cppType(e->paramType()) <<
" i ";
1662 cpp <<
")" << Const <<
endl;
1666 cpp << indent(memberAccessorBody(e), 2);
1670 if ( itemAccessors )
1673 cpp <<
"KConfigSkeleton::Item" << itemType( e->type() ) <<
" *"
1674 << getFunction( n, className ) <<
"Item(";
1675 if (!e->param().isEmpty()) {
1676 cpp <<
" " << cppType(e->paramType()) <<
" i ";
1680 cpp << indent(itemAccessorBody(e), 2);
1689 cpp << className <<
"::~" << className <<
"()" <<
endl;
1693 cpp <<
" delete d;" <<
endl;
1694 cpp <<
" if ( mSelf == this )" <<
endl;
1695 cpp <<
" static" << className <<
"Deleter.setObject( mSelf, 0, false );" <<
endl;
1699 implementation.close();
This class is used to store information about a program.
virtual TQString text() const
A class for command-line argument handling.
static void init(int _argc, char **_argv, const char *_appname, const char *programName, const char *_description, const char *_version, bool noKApp=false)
Initialize class.
static void addCmdLineOptions(const KCmdLineOptions *options, const char *name=0, const char *id=0, const char *afterId=0)
Add options to your application.
int count() const
Read the number of arguments that aren't options (but, for example, filenames).
static KCmdLineArgs * parsedArgs(const char *id=0)
Access parsed arguments.
KURL url(int n) const
Read out an argument representing a URL.
TQCString getOption(const char *option) const
Read out a string option.
Access to KDE global objects for use in shared libraries.
#define I18N_NOOP(x)
I18N_NOOP marks a string to be translated without translating it.
KDE Configuration entries.
TQString path() const
Returns the current decoded path.
TQString fileName(bool _ignore_trailing_slash_in_path=true) const
Returns the filename of the path.
kndbgstream & endl(kndbgstream &s)
Does nothing.
kdbgstream kdWarning(int area=0)
Returns a warning stream.
kdbgstream kdError(int area=0)
Returns an error stream.
kdbgstream & endl(kdbgstream &s)
Prints an "\n".
TQString label(StdAccel id)
Returns a localized label for user-visible display.
KAction * whatsThis(const TQObject *recvr, const char *slot, KActionCollection *parent, const char *name=0)
const char * name(StdAction id)
Structure that holds command line options.