25#include <tqtextstream.h>
29#include <tdeaboutdata.h>
30#include <tdeapplication.h>
33#include <tdecmdlineargs.h>
36#include <ksimpleconfig.h>
37#include <tdestandarddirs.h>
44 {
"directory <dir>",
I18N_NOOP(
"Directory to generate files in"),
"." },
45 {
"+file.kcfg",
I18N_NOOP(
"Input kcfg XML file"), 0 },
46 {
"+file.kcfgc",
I18N_NOOP(
"Code generation options file"), 0 },
55TQRegExp *validNameRegexp;
69 CfgEntry(
const TQString &group,
const TQString &type,
const TQString &key,
70 const TQString &name,
const TQString &label,
71 const TQString &whatsThis,
const TQString &code,
72 const TQString &defaultValue,
const TQValueList<Choice> &choices,
74 : mGroup( group ), mType( type ), mKey(
key ), mName(
name ),
76 mDefaultValue( defaultValue ),
77 mChoices( choices ), mHidden( hidden )
81 void setGroup(
const TQString &group ) { mGroup = group; }
82 TQString group()
const {
return mGroup; }
84 void setType(
const TQString &type ) { mType = type; }
85 TQString type()
const {
return mType; }
87 void setKey(
const TQString &key ) { mKey =
key; }
88 TQString
key()
const {
return mKey; }
90 void setName(
const TQString &name ) { mName =
name; }
91 TQString
name()
const {
return mName; }
93 void setLabel(
const TQString &label ) { mLabel =
label; }
94 TQString
label()
const {
return mLabel; }
96 void setWhatsThis(
const TQString &whatsThis ) { mWhatsThis =
whatsThis; }
97 TQString
whatsThis()
const {
return mWhatsThis; }
99 void setDefaultValue(
const TQString &d ) { mDefaultValue = d; }
100 TQString defaultValue()
const {
return mDefaultValue; }
102 void setCode(
const TQString &d ) { mCode = d; }
103 TQString code()
const {
return mCode; }
105 void setMinValue(
const TQString &d ) { mMin = d; }
106 TQString minValue()
const {
return mMin; }
108 void setMaxValue(
const TQString &d ) { mMax = d; }
109 TQString maxValue()
const {
return mMax; }
111 void setParam(
const TQString &d ) { mParam = d; }
112 TQString param()
const {
return mParam; }
114 void setParamName(
const TQString &d ) { mParamName = d; }
115 TQString paramName()
const {
return mParamName; }
117 void setParamType(
const TQString &d ) { mParamType = d; }
118 TQString paramType()
const {
return mParamType; }
120 void setChoices(
const TQValueList<Choice> &d ) { mChoices = d; }
121 TQValueList<Choice> choices()
const {
return mChoices; }
123 void setParamValues(
const TQStringList &d ) { mParamValues = d; }
124 TQStringList paramValues()
const {
return mParamValues; }
126 void setParamDefaultValues(
const TQStringList &d ) { mParamDefaultValues = d; }
127 TQString paramDefaultValue(
int i)
const {
return mParamDefaultValues[i]; }
129 void setParamMax(
int d ) { mParamMax = d; }
130 int paramMax()
const {
return mParamMax; }
132 bool hidden()
const {
return mHidden; }
136 kdDebug() <<
"<entry>" <<
endl;
137 kdDebug() <<
" group: " << mGroup <<
endl;
138 kdDebug() <<
" type: " << mType <<
endl;
139 kdDebug() <<
" key: " << mKey <<
endl;
140 kdDebug() <<
" name: " << mName <<
endl;
141 kdDebug() <<
" label: " << mLabel <<
endl;
143 kdDebug() <<
" code: " << mCode <<
endl;
146 if (!param().isEmpty())
148 kdDebug() <<
" param name: "<< mParamName <<
endl;
149 kdDebug() <<
" param type: "<< mParamType <<
endl;
150 kdDebug() <<
" paramvalues: " << mParamValues.join(
":") <<
endl;
152 kdDebug() <<
" default: " << mDefaultValue <<
endl;
153 kdDebug() <<
" hidden: " << mHidden <<
endl;
154 kdDebug() <<
" min: " << mMin <<
endl;
155 kdDebug() <<
" max: " << mMax <<
endl;
156 kdDebug() <<
"</entry>" <<
endl;
167 TQString mDefaultValue;
171 TQValueList<Choice> mChoices;
172 TQStringList mParamValues;
173 TQStringList mParamDefaultValues;
189static TQString varName(
const TQString &n)
194 result[1] = result[1].upper();
198 result[0] = result[0].lower();
203static TQString varPath(
const TQString &n)
207 result =
"d->"+varName(n);
215static TQString enumName(
const TQString &n)
217 TQString result =
"Enum"+n;
218 result[4] = result[4].upper();
222static TQString setFunction(
const TQString &n,
const TQString &className = TQString())
224 TQString result =
"set"+n;
225 result[3] = result[3].upper();
227 if ( !className.isEmpty() )
228 result = className +
"::" + result;
233static TQString getFunction(
const TQString &n,
const TQString &className = TQString())
236 result[0] = result[0].lower();
238 if ( !className.isEmpty() )
239 result = className +
"::" + result;
244static void addQuotes( TQString &s )
246 if ( s.left( 1 ) !=
"\"" ) s.prepend(
"\"" );
247 if ( s.right( 1 ) !=
"\"" ) s.append(
"\"" );
250static TQString quoteString(
const TQString &s )
253 r.replace(
"\\",
"\\\\" );
254 r.replace(
"\"",
"\\\"" );
255 r.replace(
"\r",
"" );
256 r.replace(
"\n",
"\\n\"\n\"" );
257 return "\"" + r +
"\"";
260static TQString literalString(
const TQString &s )
263 for(
int i = s.length(); i--;)
264 if (s[i].unicode() > 127) isAscii =
false;
267 return "TQString::fromLatin1( " + quoteString(s) +
" )";
269 return "TQString::fromUtf8( " + quoteString(s) +
" )";
272static TQString dumpNode(
const TQDomNode &node)
275 TQTextStream s(&msg, IO_WriteOnly );
278 msg = msg.simplifyWhiteSpace();
279 if (msg.length() > 40)
280 return msg.left(37)+
"...";
284static TQString filenameOnly(TQString path)
286 int i = path.findRev(
'/');
288 return path.mid(i+1);
292static void preProcessDefault( TQString &defaultValue,
const TQString &name,
293 const TQString &type,
294 const TQValueList<CfgEntry::Choice> &choices,
297 if ( type ==
"String" && !defaultValue.isEmpty() ) {
298 defaultValue = literalString(defaultValue);
300 }
else if ( type ==
"Path" && !defaultValue.isEmpty() ) {
301 defaultValue = literalString( defaultValue );
303 }
else if ( (type ==
"StringList" || type ==
"PathList") && !defaultValue.isEmpty() ) {
304 TQTextStream cpp( &code, IO_WriteOnly | IO_Append );
308 cpp <<
" TQStringList default" <<
name <<
";" <<
endl;
309 TQStringList defaults = TQStringList::split(
",", defaultValue );
310 TQStringList::ConstIterator it;
311 for( it = defaults.begin(); it != defaults.end(); ++it ) {
312 cpp <<
" default" <<
name <<
".append( TQString::fromUtf8( \"" << *it <<
"\" ) );"
315 defaultValue =
"default" +
name;
317 }
else if ( type ==
"Color" && !defaultValue.isEmpty() ) {
318 TQRegExp colorRe(
"\\d+,\\s*\\d+,\\s*\\d+");
319 if (colorRe.exactMatch(defaultValue))
321 defaultValue =
"TQColor( " + defaultValue +
" )";
325 defaultValue =
"TQColor( \"" + defaultValue +
"\" )";
328 }
else if ( type ==
"Enum" ) {
329 if ( !globalEnums ) {
330 TQValueList<CfgEntry::Choice>::ConstIterator it;
331 for( it = choices.begin(); it != choices.end(); ++it ) {
332 if ( (*it).name == defaultValue ) {
333 defaultValue.prepend( enumName(name) +
"::");
339 }
else if ( type ==
"IntList" ) {
340 TQTextStream cpp( &code, IO_WriteOnly | IO_Append );
344 cpp <<
" TQValueList<int> default" <<
name <<
";" <<
endl;
345 TQStringList defaults = TQStringList::split(
",", defaultValue );
346 TQStringList::ConstIterator it;
347 for( it = defaults.begin(); it != defaults.end(); ++it ) {
348 cpp <<
" default" <<
name <<
".append( " << *it <<
" );"
351 defaultValue =
"default" +
name;
356CfgEntry *parseEntry(
const TQString &group,
const TQDomElement &element )
358 bool defaultCode =
false;
359 TQString type = element.attribute(
"type" );
360 TQString
name = element.attribute(
"name" );
361 TQString
key = element.attribute(
"key" );
362 TQString hidden = element.attribute(
"hidden" );
365 TQString defaultValue;
370 TQValueList<CfgEntry::Choice> choices;
371 TQStringList paramValues;
372 TQStringList paramDefaultValues;
378 for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
379 TQDomElement e = n.toElement();
380 TQString tag = e.tagName();
381 if ( tag ==
"label" )
label = e.text();
383 else if ( tag ==
"min" ) minValue = e.text();
384 else if ( tag ==
"max" ) maxValue = e.text();
385 else if ( tag ==
"code" ) code = e.text();
386 else if ( tag ==
"parameter" )
388 param = e.attribute(
"name" );
389 paramType = e.attribute(
"type" );
390 if ( param.isEmpty() ) {
391 kdError() <<
"Parameter must have a name: " << dumpNode(e) <<
endl;
394 if ( paramType.isEmpty() ) {
395 kdError() <<
"Parameter must have a type: " << dumpNode(e) <<
endl;
398 if ((paramType ==
"Int") || (paramType ==
"UInt"))
401 paramMax = e.attribute(
"max").toInt(&ok);
404 kdError() <<
"Integer parameter must have a maximum (e.g. max=\"0\"): " << dumpNode(e) <<
endl;
408 else if (paramType ==
"Enum")
411 for ( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
412 TQDomElement e2 = n2.toElement();
413 if (e2.tagName() ==
"values")
416 for ( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) {
417 TQDomElement e3 = n3.toElement();
418 if (e3.tagName() ==
"value")
420 paramValues.append( e3.text() );
426 if (paramValues.isEmpty())
428 kdError() <<
"No values specified for parameter '" << param <<
"'." <<
endl;
431 paramMax = paramValues.count()-1;
435 kdError() <<
"Parameter '" << param <<
"' has type " << paramType <<
" but must be of type int, uint or Enum." <<
endl;
439 else if ( tag ==
"default" )
441 if (e.attribute(
"param").isEmpty())
443 defaultValue = e.text();
444 if (e.attribute(
"code" ) ==
"true")
448 else if ( tag ==
"choices" ) {
450 for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
451 TQDomElement e2 = n2.toElement();
452 if ( e2.tagName() ==
"choice" ) {
454 CfgEntry::Choice choice;
455 choice.name = e2.attribute(
"name" );
456 if ( choice.name.isEmpty() ) {
457 kdError() <<
"Tag <choice> requires attribute 'name'." <<
endl;
459 for( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) {
460 TQDomElement e3 = n3.toElement();
461 if ( e3.tagName() ==
"label" ) choice.label = e3.text();
462 if ( e3.tagName() ==
"whatsthis" ) choice.whatsThis = e3.text();
464 choices.append( choice );
470 bool nameIsEmpty =
name.isEmpty();
471 if ( nameIsEmpty &&
key.isEmpty() ) {
472 kdError() <<
"Entry must have a name or a key: " << dumpNode(element) <<
endl;
476 if (
key.isEmpty() ) {
482 name.replace(
" ", TQString() );
483 }
else if (
name.contains(
' ' ) ) {
484 kdWarning()<<
"Entry '"<<
name<<
"' contains spaces! <name> elements can't contain speces!"<<
endl;
488 if (
name.contains(
"$("))
498 if (!param.isEmpty())
500 kdError() <<
"Name must contain '$(" << param <<
")': " <<
name <<
endl;
505 if (
label.isEmpty() ) {
509 if ( type.isEmpty() ) type =
"String";
511 if (!param.isEmpty())
515 name.replace(
"$("+param+
")", TQString());
517 for(
int i = 0; i <= paramMax; i++)
519 paramDefaultValues.append(TQString());
523 for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
524 TQDomElement e = n.toElement();
525 TQString tag = e.tagName();
526 if ( tag ==
"default" )
528 TQString index = e.attribute(
"param");
533 int i = index.toInt(&ok);
536 i = paramValues.findIndex(index);
539 kdError() <<
"Index '" << index <<
"' for default value is unknown." <<
endl;
544 if ((i < 0) || (i > paramMax))
546 kdError() <<
"Index '" << i <<
"' for default value is out of range [0, "<< paramMax<<
"]." <<
endl;
550 TQString tmpDefaultValue = e.text();
552 if (e.attribute(
"code" ) !=
"true")
553 preProcessDefault(tmpDefaultValue, name, type, choices, code);
555 paramDefaultValues[i] = tmpDefaultValue;
560 if (!validNameRegexp->exactMatch(name))
563 kdError() <<
"The key '" <<
key <<
"' can not be used as name for the entry because "
564 "it is not a valid name. You need to specify a valid name for this entry." <<
endl;
566 kdError() <<
"The name '" <<
name <<
"' is not a valid name for an entry." <<
endl;
570 if (allNames.contains(name))
573 kdError() <<
"The key '" <<
key <<
"' can not be used as name for the entry because "
574 "it does not result in a unique name. You need to specify a unique name for this entry." <<
endl;
579 allNames.append(name);
583 preProcessDefault(defaultValue, name, type, choices, code);
586 CfgEntry *result =
new CfgEntry( group, type, key, name, label, whatsThis,
587 code, defaultValue, choices,
589 if (!param.isEmpty())
591 result->setParam(param);
592 result->setParamName(paramName);
593 result->setParamType(paramType);
594 result->setParamValues(paramValues);
595 result->setParamDefaultValues(paramDefaultValues);
596 result->setParamMax(paramMax);
598 result->setMinValue(minValue);
599 result->setMaxValue(maxValue);
607TQString param(
const TQString &type )
609 if ( type ==
"String" )
return "const TQString &";
610 else if ( type ==
"StringList" )
return "const TQStringList &";
611 else if ( type ==
"Font" )
return "const TQFont &";
612 else if ( type ==
"Rect" )
return "const TQRect &";
613 else if ( type ==
"Size" )
return "const TQSize &";
614 else if ( type ==
"Color" )
return "const TQColor &";
615 else if ( type ==
"Point" )
return "const TQPoint &";
616 else if ( type ==
"Int" )
return "int";
617 else if ( type ==
"UInt" )
return "uint";
618 else if ( type ==
"Bool" )
return "bool";
619 else if ( type ==
"Double" )
return "double";
620 else if ( type ==
"DateTime" )
return "const TQDateTime &";
621 else if ( type ==
"Int64" )
return "TQ_INT64";
622 else if ( type ==
"UInt64" )
return "TQ_UINT64";
623 else if ( type ==
"IntList" )
return "const TQValueList<int> &";
624 else if ( type ==
"Enum" )
return "int";
625 else if ( type ==
"Path" )
return "const TQString &";
626 else if ( type ==
"PathList" )
return "const TQStringList &";
627 else if ( type ==
"Password" )
return "const TQString &";
629 kdError() <<
"tdeconfig_compiler does not support type \""<< type <<
"\""<<
endl;
637TQString cppType(
const TQString &type )
639 if ( type ==
"String" )
return "TQString";
640 else if ( type ==
"StringList" )
return "TQStringList";
641 else if ( type ==
"Font" )
return "TQFont";
642 else if ( type ==
"Rect" )
return "TQRect";
643 else if ( type ==
"Size" )
return "TQSize";
644 else if ( type ==
"Color" )
return "TQColor";
645 else if ( type ==
"Point" )
return "TQPoint";
646 else if ( type ==
"Int" )
return "int";
647 else if ( type ==
"UInt" )
return "uint";
648 else if ( type ==
"Bool" )
return "bool";
649 else if ( type ==
"Double" )
return "double";
650 else if ( type ==
"DateTime" )
return "TQDateTime";
651 else if ( type ==
"Int64" )
return "TQ_INT64";
652 else if ( type ==
"UInt64" )
return "TQ_UINT64";
653 else if ( type ==
"IntList" )
return "TQValueList<int>";
654 else if ( type ==
"Enum" )
return "int";
655 else if ( type ==
"Path" )
return "TQString";
656 else if ( type ==
"PathList" )
return "TQStringList";
657 else if ( type ==
"Password" )
return "TQString";
659 kdError()<<
"tdeconfig_compiler does not support type \""<< type <<
"\""<<
endl;
664TQString defaultValue(
const TQString &type )
666 if ( type ==
"String" )
return "\"\"";
667 else if ( type ==
"StringList" )
return "TQStringList()";
668 else if ( type ==
"Font" )
return "TDEGlobalSettings::generalFont()";
669 else if ( type ==
"Rect" )
return "TQRect()";
670 else if ( type ==
"Size" )
return "TQSize()";
671 else if ( type ==
"Color" )
return "TQColor(128, 128, 128)";
672 else if ( type ==
"Point" )
return "TQPoint()";
673 else if ( type ==
"Int" )
return "0";
674 else if ( type ==
"UInt" )
return "0";
675 else if ( type ==
"Bool" )
return "false";
676 else if ( type ==
"Double" )
return "0.0";
677 else if ( type ==
"DateTime" )
return "TQDateTime()";
678 else if ( type ==
"Int64" )
return "0";
679 else if ( type ==
"UInt64" )
return "0";
680 else if ( type ==
"IntList" )
return "TQValueList<int>()";
681 else if ( type ==
"Enum" )
return "0";
682 else if ( type ==
"Path" )
return "\"\"";
683 else if ( type ==
"PathList" )
return "TQStringList()";
684 else if ( type ==
"Password" )
return "\"\"";
686 kdWarning()<<
"Error, tdeconfig_compiler doesn't support the \""<< type <<
"\" type!"<<
endl;
691TQString itemType(
const TQString &type )
696 t.replace( 0, 1, t.left( 1 ).upper() );
701static TQString itemDeclaration(
const CfgEntry *e)
706 TQString fCap = e->name();
707 fCap[0] = fCap[0].upper();
708 return " TDEConfigSkeleton::Item"+itemType( e->type() ) +
710 ( (!e->param().isEmpty())?(TQString(
"[%1]").arg(e->paramMax()+1)) : TQString()) +
717static TQString itemVar(
const CfgEntry *e)
724 result =
"m" + e->name() +
"Item";
725 result[1] = result[1].upper();
729 result = e->name() +
"Item";
730 result[0] = result[0].lower();
735 result =
"item" + e->name();
736 result[4] = result[4].upper();
741static TQString itemPath(
const CfgEntry *e)
745 result =
"d->"+itemVar(e);
753TQString newItem(
const TQString &type,
const TQString &name,
const TQString &key,
754 const TQString &defaultValue,
const TQString ¶m = TQString())
756 TQString t =
"new TDEConfigSkeleton::Item" + itemType( type ) +
757 "( currentGroup(), " +
key +
", " + varPath( name ) + param;
758 if ( type ==
"Enum" ) t +=
", values" +
name;
759 if ( !defaultValue.isEmpty() ) {
761 if ( type ==
"String" ) t += defaultValue;
762 else t+= defaultValue;
769TQString paramString(
const TQString &s,
const CfgEntry *e,
int i)
772 TQString needle =
"$("+e->param()+
")";
773 if (result.contains(needle))
776 if (e->paramType() ==
"Enum")
778 tmp = e->paramValues()[i];
782 tmp = TQString::number(i);
785 result.replace(needle, tmp);
790TQString paramString(
const TQString &group,
const TQValueList<Param> ¶meters)
792 TQString paramString = group;
795 for (TQValueList<Param>::ConstIterator it = parameters.begin();
796 it != parameters.end(); ++it)
798 if (paramString.contains(
"$("+(*it).name+
")"))
801 tmp.sprintf(
"%%%d", i++);
802 paramString.replace(
"$("+(*it).name+
")", tmp);
803 arguments +=
".arg( mParam"+(*it).name+
" )";
806 if (arguments.isEmpty())
807 return "TQString::fromLatin1( \""+group+
"\" )";
809 return "TQString::fromLatin1( \""+paramString+
"\" )"+arguments;
813TQString userTextsFunctions( CfgEntry *e, TQString itemVarStr=TQString(), TQString i=TQString() )
816 if (itemVarStr.isNull()) itemVarStr=itemPath(e);
817 if ( !e->label().isEmpty() ) {
818 txt +=
" " + itemVarStr +
"->setLabel( i18n(";
819 if ( !e->param().isEmpty() )
820 txt += quoteString(e->label().replace(
"$("+e->param()+
")", i));
822 txt+= quoteString(e->label());
825 if ( !e->whatsThis().isEmpty() ) {
826 txt +=
" " + itemVarStr +
"->setWhatsThis( i18n(";
827 if ( !e->param().isEmpty() )
828 txt += quoteString(e->whatsThis().replace(
"$("+e->param()+
")", i));
830 txt+= quoteString(e->whatsThis());
839TQString memberAccessorBody( CfgEntry *e )
842 TQTextStream out(&result, IO_WriteOnly);
843 TQString n = e->name();
844 TQString t = e->type();
846 out <<
"return " << This << varPath(n);
847 if (!e->param().isEmpty()) out <<
"[i]";
856TQString memberMutatorBody( CfgEntry *e )
859 TQTextStream out(&result, IO_WriteOnly);
860 TQString n = e->name();
861 TQString t = e->type();
863 if (!e->minValue().isEmpty())
865 out <<
"if (v < " << e->minValue() <<
")" <<
endl;
867 out <<
" kdDebug() << \"" << setFunction(n);
868 out <<
": value \" << v << \" is less than the minimum value of ";
869 out << e->minValue()<<
"\" << endl;" <<
endl;
870 out <<
" v = " << e->minValue() <<
";" <<
endl;
874 if (!e->maxValue().isEmpty())
876 out <<
endl <<
"if (v > " << e->maxValue() <<
")" <<
endl;
878 out <<
" kdDebug() << \"" << setFunction(n);
879 out <<
": value \" << v << \" is greater than the maximum value of ";
880 out << e->maxValue()<<
"\" << endl;" <<
endl;
881 out <<
" v = " << e->maxValue() <<
";" <<
endl;
885 out <<
"if (!" << This <<
"isImmutable( TQString::fromLatin1( \"";
886 if (!e->param().isEmpty())
888 out << e->paramName().replace(
"$("+e->param()+
")",
"%1") <<
"\" ).arg( ";
889 if ( e->paramType() ==
"Enum" ) {
890 out <<
"TQString::fromLatin1( ";
893 out << enumName(e->param()) <<
"ToString[i]";
895 out << enumName(e->param()) <<
"::enumToString[i]";
909 out <<
" ))" <<
endl;
910 out <<
" " << This << varPath(n);
911 if (!e->param().isEmpty())
913 out <<
" = v;" <<
endl;
921TQString itemAccessorBody( CfgEntry *e )
924 TQTextStream out(&result, IO_WriteOnly);
926 out <<
"return " << itemPath(e);
927 if (!e->param().isEmpty()) out <<
"[i]";
934TQString indent(TQString text,
int spaces)
937 TQTextStream out(&result, IO_WriteOnly);
938 TQTextStream in(&text, IO_ReadOnly);
940 while ( !in.atEnd() )
942 currLine = in.readLine();
943 if (!currLine.isEmpty())
944 for (
int i=0; i < spaces; i++)
946 out << currLine <<
endl;
952int main(
int argc,
char **argv )
955 I18N_NOOP(
"TDEConfig Compiler") , TDEAboutData::License_LGPL );
956 aboutData.addAuthor(
"Cornelius Schumacher", 0,
"schumacher@kde.org" );
957 aboutData.addAuthor(
"Waldo Bastian", 0,
"bastian@kde.org" );
958 aboutData.addAuthor(
"Zack Rusin", 0,
"zack@kde.org" );
959 aboutData.addCredit(
"Reinhold Kainhofer",
"Fix for parametrized entries",
960 "reinhold@kainhofer.com",
"http://reinhold.kainhofer.com" );
961 aboutData.addCredit(
"Duncan Mac-Vicar P.",
"dpointer support",
962 "duncan@kde.org",
"http://www.mac-vicar.com/~duncan" );
971 if ( args->
count() < 2 ) {
975 if ( args->
count() > 2 ) {
980 validNameRegexp =
new TQRegExp(
"[a-zA-Z_][a-zA-Z0-9_]*");
982 TQString baseDir = TQFile::decodeName(args->
getOption(
"directory"));
983 if (!baseDir.endsWith(
"/"))
986 TQString inputFilename = args->
url( 0 ).
path();
987 TQString codegenFilename = args->
url( 1 ).
path();
989 if (!codegenFilename.endsWith(
".kcfgc"))
991 kdError() <<
"Codegen options file must have extension .kcfgc" <<
endl;
995 baseName = baseName.left(baseName.length() - 6);
999 TQString nameSpace = codegenConfig.readEntry(
"NameSpace");
1000 TQString className = codegenConfig.readEntry(
"ClassName");
1001 TQString inherits = codegenConfig.readEntry(
"Inherits");
1002 TQString visibility = codegenConfig.readEntry(
"Visibility");
1003 if (!visibility.isEmpty()) visibility+=
" ";
1004 bool singleton = codegenConfig.readBoolEntry(
"Singleton",
false);
1005 bool staticAccessors = singleton;
1007 bool customAddons = codegenConfig.readBoolEntry(
"CustomAdditions");
1008 TQString memberVariables = codegenConfig.readEntry(
"MemberVariables");
1009 TQStringList headerIncludes = codegenConfig.readListEntry(
"IncludeFiles");
1010 TQStringList mutators = codegenConfig.readListEntry(
"Mutators");
1011 bool allMutators =
false;
1012 if ((mutators.count() == 1) && (mutators[0].lower() ==
"true"))
1014 itemAccessors = codegenConfig.readBoolEntry(
"ItemAccessors",
false );
1015 bool setUserTexts = codegenConfig.readBoolEntry(
"SetUserTexts",
false );
1017 globalEnums = codegenConfig.readBoolEntry(
"GlobalEnums",
false );
1019 dpointer = (memberVariables ==
"dpointer");
1021 TQFile input( inputFilename );
1027 if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
1029 kdError() <<
"Parse error in " << args->
url( 0 ).
fileName() <<
", line " << errorRow <<
", col " << errorCol <<
": " << errorMsg <<
endl;
1033 TQDomElement cfgElement = doc.documentElement();
1035 if ( cfgElement.isNull() ) {
1040 TQString cfgFileName;
1041 bool cfgFileNameArg =
false;
1042 TQValueList<Param> parameters;
1043 TQStringList includes;
1045 TQPtrList<CfgEntry> entries;
1046 entries.setAutoDelete(
true );
1049 for ( n = cfgElement.firstChild(); !n.isNull(); n = n.nextSibling() ) {
1050 TQDomElement e = n.toElement();
1052 TQString tag = e.tagName();
1054 if ( tag ==
"include" ) {
1055 TQString includeFile = e.text();
1056 if (!includeFile.isEmpty())
1057 includes.append(includeFile);
1059 }
else if ( tag ==
"kcfgfile" ) {
1060 cfgFileName = e.attribute(
"name" );
1061 cfgFileNameArg = e.attribute(
"arg" ).lower() ==
"true";
1063 for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
1064 TQDomElement e2 = n2.toElement();
1065 if ( e2.tagName() ==
"parameter" ) {
1067 p.name = e2.attribute(
"name" );
1068 p.type = e2.attribute(
"type" );
1069 if (p.type.isEmpty())
1071 parameters.append( p );
1075 }
else if ( tag ==
"group" ) {
1076 TQString group = e.attribute(
"name" );
1077 if ( group.isEmpty() ) {
1082 for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
1083 TQDomElement e2 = n2.toElement();
1084 if ( e2.tagName() !=
"entry" )
continue;
1085 CfgEntry *entry = parseEntry( group, e2 );
1086 if ( entry ) entries.append( entry );
1095 if ( inherits.isEmpty() ) inherits =
"TDEConfigSkeleton";
1097 if ( className.isEmpty() ) {
1102 if ( singleton && !parameters.isEmpty() ) {
1103 kdError() <<
"Singleton class can not have parameters" <<
endl;
1107 if ( !cfgFileName.isEmpty() && cfgFileNameArg)
1109 kdError() <<
"Having both a fixed filename and a filename as argument is not possible." <<
endl;
1113 if ( entries.isEmpty() ) {
1119 for( cfg = entries.first(); cfg; cfg = entries.next() ) {
1124 TQString headerFileName = baseName +
".h";
1125 TQString implementationFileName = baseName +
".cpp";
1126 TQString cppPreamble;
1128 TQFile header( baseDir + headerFileName );
1129 if ( !header.open( IO_WriteOnly ) ) {
1130 kdError() <<
"Can't open '" << headerFileName <<
"' for writing." <<
endl;
1134 TQTextStream h( &header );
1136 h <<
"// This file is generated by tdeconfig_compiler from " << args->
url(0).
fileName() <<
"." <<
endl;
1137 h <<
"// All changes you do to this file will be lost." <<
endl;
1139 h <<
"#ifndef " << ( !nameSpace.isEmpty() ? nameSpace.upper() +
"_" :
"" )
1140 << className.upper() <<
"_H" <<
endl;
1141 h <<
"#define " << ( !nameSpace.isEmpty() ? nameSpace.upper() +
"_" :
"" )
1142 << className.upper() <<
"_H" <<
endl <<
endl;
1145 TQStringList::ConstIterator it;
1146 for( it = headerIncludes.begin(); it != headerIncludes.end(); ++it ) {
1147 h <<
"#include <" << *it <<
">" <<
endl;
1150 if ( headerIncludes.count() > 0 ) h <<
endl;
1152 if ( !singleton && cfgFileNameArg && parameters.isEmpty() )
1153 h <<
"#include <tdeglobal.h>" <<
endl;
1155 h <<
"#include <tdeconfigskeleton.h>" <<
endl;
1156 h <<
"#include <kdebug.h>" <<
endl <<
endl;
1159 for( it = includes.begin(); it != includes.end(); ++it ) {
1160 h <<
"#include <" << *it <<
">" <<
endl;
1164 if ( !nameSpace.isEmpty() )
1165 h <<
"namespace " << nameSpace <<
" {" <<
endl <<
endl;
1169 h <<
"class " << className <<
"Private;" <<
endl <<
endl;
1172 h <<
"class " << visibility << className <<
" : public " << inherits <<
endl;
1174 h <<
" public:" <<
endl;
1178 for( e = entries.first(); e; e = entries.next() ) {
1179 TQValueList<CfgEntry::Choice> choices = e->choices();
1180 if ( !choices.isEmpty() ) {
1181 TQStringList values;
1182 TQValueList<CfgEntry::Choice>::ConstIterator itChoice;
1183 for( itChoice = choices.begin(); itChoice != choices.end(); ++itChoice ) {
1184 values.append( (*itChoice).name );
1186 if ( globalEnums ) {
1187 h <<
" enum { " << values.join(
", " ) <<
" };" <<
endl;
1189 h <<
" class " << enumName(e->name()) <<
endl;
1191 h <<
" public:" <<
endl;
1192 h <<
" enum type { " << values.join(
", " ) <<
", COUNT };" <<
endl;
1196 TQStringList values = e->paramValues();
1197 if ( !values.isEmpty() ) {
1198 if ( globalEnums ) {
1199 h <<
" enum { " << values.join(
", " ) <<
" };" <<
endl;
1200 h <<
" static const char* const " << enumName(e->param()) <<
"ToString[];" <<
endl;
1201 cppPreamble +=
"const char* const " + className +
"::" + enumName(e->param()) +
"ToString[] = " +
1202 "{ \"" + values.join(
"\", \"" ) +
"\" };\n";
1204 h <<
" class " << enumName(e->param()) <<
endl;
1206 h <<
" public:" <<
endl;
1207 h <<
" enum type { " << values.join(
", " ) <<
", COUNT };" <<
endl;
1208 h <<
" static const char* const enumToString[];" <<
endl;
1210 cppPreamble +=
"const char* const " + className +
"::" + enumName(e->param()) +
"::enumToString[] = " +
1211 "{ \"" + values.join(
"\", \"" ) +
"\" };\n";
1220 h <<
" " << className <<
"(";
1222 h <<
" TDESharedConfig::Ptr config" << (parameters.isEmpty() ?
" = TDEGlobal::sharedConfig()" :
", ");
1223 for (TQValueList<Param>::ConstIterator it = parameters.begin();
1224 it != parameters.end(); ++it)
1226 if (it != parameters.begin())
1228 h <<
" " << param((*it).type) <<
" " << (*it).name;
1232 h <<
" static " << className <<
" *self();" <<
endl;
1234 h <<
" static void instance(const char * cfgfilename);" <<
endl;
1238 h <<
" ~" << className <<
"();" <<
endl <<
endl;
1241 if (staticAccessors)
1246 for( e = entries.first(); e; e = entries.next() ) {
1247 TQString n = e->name();
1248 TQString t = e->type();
1251 if (allMutators || mutators.contains(n))
1253 h <<
" /**" <<
endl;
1254 h <<
" Set " << e->label() <<
endl;
1256 if (staticAccessors)
1257 h <<
" static" <<
endl;
1258 h <<
" void " << setFunction(n) <<
"( ";
1259 if (!e->param().isEmpty())
1260 h << cppType(e->paramType()) <<
" i, ";
1261 h << param( t ) <<
" v )";
1267 h << indent(memberMutatorBody(e), 6 );
1277 h <<
" /**" <<
endl;
1278 h <<
" Get " << e->label() <<
endl;
1280 if (staticAccessors)
1281 h <<
" static" <<
endl;
1282 h <<
" " << cppType(t) <<
" " << getFunction(n) <<
"(";
1283 if (!e->param().isEmpty())
1284 h <<
" " << cppType(e->paramType()) <<
" i ";
1291 h << indent(memberAccessorBody(e), 6 );
1300 if ( itemAccessors ) {
1302 h <<
" /**" <<
endl;
1303 h <<
" Get Item object corresponding to " << n <<
"()"
1306 h <<
" Item" << itemType( e->type() ) <<
" *"
1307 << getFunction( n ) <<
"Item(";
1308 if (!e->param().isEmpty()) {
1309 h <<
" " << cppType(e->paramType()) <<
" i ";
1315 h << indent( itemAccessorBody(e), 6);
1329 h <<
" static" <<
endl;
1330 h <<
" void writeConfig()" <<
endl;
1332 h <<
" static_cast<TDEConfigSkeleton*>(self())->writeConfig();" <<
endl;
1336 h <<
" protected:" <<
endl;
1340 h <<
" " << className <<
"(";
1341 if ( cfgFileNameArg )
1342 h <<
"const char *arg";
1344 h <<
" static " << className <<
" *mSelf;" <<
endl <<
endl;
1348 if ( !memberVariables.isEmpty() && memberVariables !=
"private" && memberVariables !=
"dpointer") {
1349 h <<
" " << memberVariables <<
":" <<
endl;
1353 for (TQValueList<Param>::ConstIterator it = parameters.begin();
1354 it != parameters.end(); ++it)
1356 h <<
" " << cppType((*it).type) <<
" mParam" << (*it).name <<
";" <<
endl;
1359 if ( memberVariables !=
"dpointer" )
1362 for( e = entries.first(); e; e = entries.next() ) {
1363 if ( e->group() != group ) {
1366 h <<
" // " << group <<
endl;
1368 h <<
" " << cppType(e->type()) <<
" " << varName(e->name());
1369 if (!e->param().isEmpty())
1371 h << TQString(
"[%1]").arg(e->paramMax()+1);
1377 if ( itemAccessors ) {
1378 for( e = entries.first(); e; e = entries.next() ) {
1379 h <<
" Item" << itemType( e->type() ) <<
" *" << itemVar( e );
1380 if (!e->param().isEmpty() ) h << TQString(
"[%1]").arg( e->paramMax()+1 );
1389 h <<
" private:" <<
endl;
1390 h <<
" " + className +
"Private *d;" <<
endl;
1395 h <<
" // Include custom additions" <<
endl;
1396 h <<
" #include \"" << filenameOnly(baseName) <<
"_addons.h\"" <<
endl;
1401 if ( !nameSpace.isEmpty() ) h <<
"}" <<
endl <<
endl;
1408 TQFile implementation( baseDir + implementationFileName );
1409 if ( !implementation.open( IO_WriteOnly ) ) {
1410 kdError() <<
"Can't open '" << implementationFileName <<
"' for writing."
1415 TQTextStream cpp( &implementation );
1418 cpp <<
"// This file is generated by tdeconfig_compiler from " << args->
url(0).
fileName() <<
"." <<
endl;
1419 cpp <<
"// All changes you do to this file will be lost." <<
endl <<
endl;
1421 cpp <<
"#include \"" << headerFileName <<
"\"" <<
endl <<
endl;
1423 if ( setUserTexts ) cpp <<
"#include <tdelocale.h>" <<
endl <<
endl;
1427 cpp <<
"#include <kstaticdeleter.h>" <<
endl <<
endl;
1428 if ( singleton && cfgFileNameArg )
1429 cpp <<
"#include <kdebug.h>" <<
endl <<
endl;
1431 if ( !nameSpace.isEmpty() )
1432 cpp <<
"using namespace " << nameSpace <<
";" <<
endl <<
endl;
1439 cpp <<
"class " << className <<
"Private" <<
endl;
1441 cpp <<
" public:" <<
endl;
1442 for( e = entries.first(); e; e = entries.next() ) {
1443 if ( e->group() != group ) {
1446 cpp <<
" // " << group <<
endl;
1448 cpp <<
" " << cppType(e->type()) <<
" " << varName(e->name());
1449 if (!e->param().isEmpty())
1451 cpp << TQString(
"[%1]").arg(e->paramMax()+1);
1455 cpp <<
endl <<
" // items" <<
endl;
1456 for( e = entries.first(); e; e = entries.next() ) {
1457 cpp <<
" TDEConfigSkeleton::Item" << itemType( e->type() ) <<
" *" << itemVar( e );
1458 if (!e->param().isEmpty() ) cpp << TQString(
"[%1]").arg( e->paramMax()+1 );
1467 cpp << className <<
" *" << className <<
"::mSelf = 0;" <<
endl;
1468 cpp <<
"static KStaticDeleter<" << className <<
"> static" << className <<
"Deleter;" <<
endl <<
endl;
1470 cpp << className <<
" *" << className <<
"::self()" <<
endl;
1472 if ( cfgFileNameArg ) {
1473 cpp <<
" if (!mSelf)" <<
endl;
1474 cpp <<
" kdFatal() << \"you need to call " << className <<
"::instance before using\" << endl;" <<
endl;
1476 cpp <<
" if ( !mSelf ) {" <<
endl;
1477 cpp <<
" static" << className <<
"Deleter.setObject( mSelf, new " << className <<
"() );" <<
endl;
1478 cpp <<
" mSelf->readConfig();" <<
endl;
1481 cpp <<
" return mSelf;" <<
endl;
1484 if ( cfgFileNameArg ) {
1485 cpp <<
"void " << className <<
"::instance(const char *cfgfilename)" <<
endl;
1487 cpp <<
" if (mSelf) {" <<
endl;
1488 cpp <<
" kdError() << \"" << className <<
"::instance called after the first use - ignoring\" << endl;" <<
endl;
1489 cpp <<
" return;" <<
endl;
1490 cpp <<
" }" <<
endl;
1491 cpp <<
" static" << className <<
"Deleter.setObject( mSelf, new " << className <<
"(cfgfilename) );" <<
endl;
1492 cpp <<
" mSelf->readConfig();" <<
endl;
1497 if ( !cppPreamble.isEmpty() )
1498 cpp << cppPreamble <<
endl;
1501 cpp << className <<
"::" << className <<
"( ";
1502 if ( cfgFileNameArg ) {
1504 cpp <<
" TDESharedConfig::Ptr config";
1506 cpp <<
" const char *config";
1507 cpp << (parameters.isEmpty() ?
" " :
", ");
1510 for (TQValueList<Param>::ConstIterator it = parameters.begin();
1511 it != parameters.end(); ++it)
1513 if (it != parameters.begin())
1515 cpp <<
" " << param((*it).type) <<
" " << (*it).name;
1517 cpp <<
" )" <<
endl;
1519 cpp <<
" : " << inherits <<
"(";
1520 if ( !cfgFileName.isEmpty() ) cpp <<
" TQString::fromLatin1( \"" << cfgFileName <<
"\" ";
1521 if ( cfgFileNameArg ) cpp <<
" config ";
1522 if ( !cfgFileName.isEmpty() ) cpp <<
") ";
1526 for (TQValueList<Param>::ConstIterator it = parameters.begin();
1527 it != parameters.end(); ++it)
1529 cpp <<
" , mParam" << (*it).name <<
"(" << (*it).name <<
")" <<
endl;
1535 cpp <<
" d = new " + className +
"Private;" <<
endl;
1539 cpp <<
" mSelf = this;" <<
endl;
1542 for( e = entries.first(); e; e = entries.next() ) {
1543 if ( e->group() != group ) {
1544 if ( !group.isEmpty() ) cpp <<
endl;
1546 cpp <<
" setCurrentGroup( " << paramString(group, parameters) <<
" );" <<
endl <<
endl;
1549 TQString
key = paramString(e->key(), parameters);
1550 if ( !e->code().isEmpty())
1552 cpp << e->code() <<
endl;
1554 if ( e->type() ==
"Enum" ) {
1555 cpp <<
" TQValueList<TDEConfigSkeleton::ItemEnum::Choice> values"
1556 << e->name() <<
";" <<
endl;
1557 TQValueList<CfgEntry::Choice> choices = e->choices();
1558 TQValueList<CfgEntry::Choice>::ConstIterator it;
1559 for( it = choices.begin(); it != choices.end(); ++it ) {
1560 cpp <<
" {" <<
endl;
1561 cpp <<
" TDEConfigSkeleton::ItemEnum::Choice choice;" <<
endl;
1562 cpp <<
" choice.name = TQString::fromLatin1( \"" << (*it).name <<
"\" );" <<
endl;
1563 if ( setUserTexts ) {
1564 if ( !(*it).label.isEmpty() )
1565 cpp <<
" choice.label = i18n(" << quoteString((*it).label) <<
");" <<
endl;
1566 if ( !(*it).whatsThis.isEmpty() )
1567 cpp <<
" choice.whatsThis = i18n(" << quoteString((*it).whatsThis) <<
");" <<
endl;
1569 cpp <<
" values" << e->name() <<
".append( choice );" <<
endl;
1570 cpp <<
" }" <<
endl;
1575 cpp << itemDeclaration(e);
1577 if (e->param().isEmpty())
1580 cpp <<
" " << itemPath(e) <<
" = "
1581 << newItem( e->type(), e->name(), key, e->defaultValue() ) <<
endl;
1583 if ( !e->minValue().isEmpty() )
1584 cpp <<
" " << itemPath(e) <<
"->setMinValue(" << e->minValue() <<
");" <<
endl;
1585 if ( !e->maxValue().isEmpty() )
1586 cpp <<
" " << itemPath(e) <<
"->setMaxValue(" << e->maxValue() <<
");" <<
endl;
1589 cpp << userTextsFunctions( e );
1591 cpp <<
" addItem( " << itemPath(e);
1592 TQString quotedName = e->name();
1593 addQuotes( quotedName );
1594 if ( quotedName != key ) cpp <<
", TQString::fromLatin1( \"" << e->name() <<
"\" )";
1595 cpp <<
" );" <<
endl;
1600 for(
int i = 0; i <= e->paramMax(); i++)
1602 TQString defaultStr;
1603 TQString itemVarStr(itemPath(e)+TQString(
"[%1]").arg(i));
1605 if ( !e->paramDefaultValue(i).isEmpty() )
1606 defaultStr = e->paramDefaultValue(i);
1607 else if ( !e->defaultValue().isEmpty() )
1608 defaultStr = paramString(e->defaultValue(), e, i);
1610 defaultStr = defaultValue( e->type() );
1612 cpp <<
" " << itemVarStr <<
" = "
1613 << newItem( e->type(), e->name(), paramString(key, e, i), defaultStr, TQString(
"[%1]").arg(i) )
1617 cpp << userTextsFunctions( e, itemVarStr, e->paramName() );
1623 cpp <<
" addItem( " << itemVarStr <<
", TQString::fromLatin1( \"";
1624 if ( e->paramType()==
"Enum" )
1625 cpp << e->paramName().replace(
"$("+e->param()+
")",
"%1").arg(e->paramValues()[i] );
1627 cpp << e->paramName().replace(
"$("+e->param()+
")",
"%1").arg(i);
1628 cpp <<
"\" ) );" <<
endl;
1638 for( e = entries.first(); e; e = entries.next() )
1640 TQString n = e->name();
1641 TQString t = e->type();
1644 if (allMutators || mutators.contains(n))
1646 cpp <<
"void " << setFunction(n, className) <<
"( ";
1647 if (!e->param().isEmpty())
1648 cpp << cppType(e->paramType()) <<
" i, ";
1649 cpp << param( t ) <<
" v )" <<
endl;
1653 cpp << indent(memberMutatorBody(e), 6);
1658 cpp << cppType(t) <<
" " << getFunction(n, className) <<
"(";
1659 if (!e->param().isEmpty())
1660 cpp <<
" " << cppType(e->paramType()) <<
" i ";
1661 cpp <<
")" << Const <<
endl;
1665 cpp << indent(memberAccessorBody(e), 2);
1669 if ( itemAccessors )
1672 cpp <<
"TDEConfigSkeleton::Item" << itemType( e->type() ) <<
" *"
1673 << getFunction( n, className ) <<
"Item(";
1674 if (!e->param().isEmpty()) {
1675 cpp <<
" " << cppType(e->paramType()) <<
" i ";
1679 cpp << indent(itemAccessorBody(e), 2);
1688 cpp << className <<
"::~" << className <<
"()" <<
endl;
1692 cpp <<
" delete d;" <<
endl;
1693 cpp <<
" if ( mSelf == this )" <<
endl;
1694 cpp <<
" static" << className <<
"Deleter.setObject( mSelf, 0, false );" <<
endl;
1698 implementation.close();
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.
This class is used to store information about a program.
virtual TQString text() const
A class for command-line argument handling.
static TDECmdLineArgs * parsedArgs(const char *id=0)
Access parsed arguments.
static void addCmdLineOptions(const TDECmdLineOptions *options, const char *name=0, const char *id=0, const char *afterId=0)
Add options to your application.
KURL url(int n) const
Read out an argument representing a URL.
TQCString getOption(const char *option) const
Read out a string option.
static void init(int _argc, char **_argv, const char *_appname, const char *programName, const char *_description, const char *_version, bool noTDEApp=false)
Initialize class.
int count() const
Read the number of arguments that aren't options (but, for example, filenames).
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.
kdbgstream kdWarning(int area=0)
Returns a warning stream.
kdbgstream kdError(int area=0)
Returns an error stream.
kndbgstream & endl(kndbgstream &s)
Does nothing.
kdbgstream & endl(kdbgstream &s)
Prints an "\n".
TDEAction * whatsThis(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
const char * name(StdAction id)
TQString label(StdAccel id)
Returns a localized label for user-visible display.
Structure that holds command line options.