25 #include <tqtextstream.h>
29 #include <tdeaboutdata.h>
30 #include <tdeapplication.h>
33 #include <tdecmdlineargs.h>
34 #include <tdeglobal.h>
35 #include <tdeconfig.h>
36 #include <ksimpleconfig.h>
37 #include <kstandarddirs.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 },
54 TQStringList allNames;
55 TQRegExp *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 ),
75 mLabel( label ), mWhatsThis( whatsThis ), mCode( code ),
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;
189 static TQString varName(
const TQString &n)
194 result[1] = result[1].upper();
198 result[0] = result[0].lower();
203 static TQString varPath(
const TQString &n)
207 result =
"d->"+varName(n);
215 static TQString enumName(
const TQString &n)
217 TQString result =
"Enum"+n;
218 result[4] = result[4].upper();
222 static 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;
233 static TQString getFunction(
const TQString &n,
const TQString &className = TQString())
236 result[0] = result[0].lower();
238 if ( !className.isEmpty() )
239 result = className +
"::" + result;
244 static void addQuotes( TQString &s )
246 if ( s.left( 1 ) !=
"\"" ) s.prepend(
"\"" );
247 if ( s.right( 1 ) !=
"\"" ) s.append(
"\"" );
250 static TQString quoteString(
const TQString &s )
253 r.replace(
"\\",
"\\\\" );
254 r.replace(
"\"",
"\\\"" );
255 r.replace(
"\r",
"" );
256 r.replace(
"\n",
"\\n\"\n\"" );
257 return "\"" + r +
"\"";
260 static 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) +
" )";
272 static 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)+
"...";
284 static TQString filenameOnly(TQString path)
286 int i = path.findRev(
'/');
288 return path.mid(i+1);
292 static 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;
356 CfgEntry *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();
382 else if ( tag ==
"whatsthis" ) whatsThis = 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(
"$("))
492 kdError() <<
"Name may not be parameterized: " << name <<
endl;
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;
576 kdError() <<
"The name '" << name <<
"' is not unique." <<
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);
607 TQString 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;
637 TQString 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;
664 TQString 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;
691 TQString itemType(
const TQString &type )
696 t.replace( 0, 1, t.left( 1 ).upper() );
701 static 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()) +
717 static 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();
741 static TQString itemPath(
const CfgEntry *e)
745 result =
"d->"+itemVar(e);
753 TQString 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;
769 TQString 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);
790 TQString 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;
813 TQString 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());
839 TQString 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]";
856 TQString 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;
882 out <<
"}" << endl <<
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;
921 TQString itemAccessorBody( CfgEntry *e )
924 TQTextStream out(&result, IO_WriteOnly);
926 out <<
"return " << itemPath(e);
927 if (!e->param().isEmpty()) out <<
"[i]";
934 TQString 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;
952 int 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 )";
1266 h << endl <<
" {" <<
endl;
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 ";
1290 h << endl <<
" {" <<
endl;
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 ";
1314 h << endl <<
" {" <<
endl;
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);
1376 h << endl <<
" private:" <<
endl;
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;
1399 h <<
"};" << endl <<
endl;
1401 if ( !nameSpace.isEmpty() ) h <<
"}" << endl << endl;
1403 h <<
"#endif" << 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 );
1462 cpp <<
"};" << endl <<
endl;
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;
1479 cpp <<
" }" << endl <<
endl;
1481 cpp <<
" return mSelf;" <<
endl;
1482 cpp <<
"}" << endl <<
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;
1493 cpp <<
"}" << endl <<
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;
1633 cpp <<
"}" << endl <<
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);
1654 cpp <<
"}" << endl <<
endl;
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);
1666 cpp <<
"}" << endl <<
endl;
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;
1696 cpp <<
"}" << endl <<
endl;
1698 implementation.close();
A class for command-line argument handling.
kdbgstream kdError(int area=0)
This class is used to store information about a program.
static void addCmdLineOptions(const TDECmdLineOptions *options, const char *name=0, const char *id=0, const char *afterId=0)
Add options to your application.
TQString fileName(bool _ignore_trailing_slash_in_path=true) const
Returns the filename of the path.
KURL url(int n) const
Read out an argument representing a URL.
TQCString getOption(const char *option) const
Read out a string option.
static TDECmdLineArgs * parsedArgs(const char *id=0)
Access parsed arguments.
kdbgstream kdWarning(int area=0)
static void init(int _argc, char **_argv, const char *_appname, const char *programName, const char *_description, const char *_version, bool noKApp=false)
Initialize class.
const char * name(StdAction id)
TDEAction * whatsThis(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
int count() const
Read the number of arguments that aren't options (but, for example, filenames).
TQString path() const
Returns the current decoded path.
kndbgstream & endl(kndbgstream &s)
Does nothing.
KDE Configuration entries.
TQString label(StdAccel id)
Returns a localized label for user-visible display.
kdbgstream & endl(kdbgstream &s)
Access to KDE global objects for use in shared libraries.
Structure that holds command line options.