• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
  • tdeconfig_compiler
tdeconfig_compiler.cpp
1 /*
2  This file is part of KDE.
3 
4  Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
6  Copyright (c) 2003 Zack Rusin <zack@kde.org>
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Library General Public
10  License as published by the Free Software Foundation; either
11  version 2 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Library General Public License for more details.
17 
18  You should have received a copy of the GNU Library General Public License
19  along with this library; see the file COPYING.LIB. If not, write to
20  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  Boston, MA 02110-1301, USA.
22 */
23 
24 #include <tqfile.h>
25 #include <tqtextstream.h>
26 #include <tqdom.h>
27 #include <tqregexp.h>
28 
29 #include <tdeaboutdata.h>
30 #include <tdeapplication.h>
31 #include <kdebug.h>
32 #include <tdelocale.h>
33 #include <tdecmdlineargs.h>
34 #include <tdeglobal.h>
35 #include <tdeconfig.h>
36 #include <ksimpleconfig.h>
37 #include <kstandarddirs.h>
38 
39 #include <iostream>
40 
41 static const TDECmdLineOptions options[] =
42 {
43  { "d", 0, 0 },
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 },
47  TDECmdLineLastOption
48 };
49 
50 
51 bool globalEnums;
52 bool itemAccessors;
53 bool dpointer;
54 TQStringList allNames;
55 TQRegExp *validNameRegexp;
56 TQString This;
57 TQString Const;
58 
59 class CfgEntry
60 {
61  public:
62  struct Choice
63  {
64  TQString name;
65  TQString label;
66  TQString whatsThis;
67  };
68 
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,
73  bool hidden )
74  : mGroup( group ), mType( type ), mKey( key ), mName( name ),
75  mLabel( label ), mWhatsThis( whatsThis ), mCode( code ),
76  mDefaultValue( defaultValue ),
77  mChoices( choices ), mHidden( hidden )
78  {
79  }
80 
81  void setGroup( const TQString &group ) { mGroup = group; }
82  TQString group() const { return mGroup; }
83 
84  void setType( const TQString &type ) { mType = type; }
85  TQString type() const { return mType; }
86 
87  void setKey( const TQString &key ) { mKey = key; }
88  TQString key() const { return mKey; }
89 
90  void setName( const TQString &name ) { mName = name; }
91  TQString name() const { return mName; }
92 
93  void setLabel( const TQString &label ) { mLabel = label; }
94  TQString label() const { return mLabel; }
95 
96  void setWhatsThis( const TQString &whatsThis ) { mWhatsThis = whatsThis; }
97  TQString whatsThis() const { return mWhatsThis; }
98 
99  void setDefaultValue( const TQString &d ) { mDefaultValue = d; }
100  TQString defaultValue() const { return mDefaultValue; }
101 
102  void setCode( const TQString &d ) { mCode = d; }
103  TQString code() const { return mCode; }
104 
105  void setMinValue( const TQString &d ) { mMin = d; }
106  TQString minValue() const { return mMin; }
107 
108  void setMaxValue( const TQString &d ) { mMax = d; }
109  TQString maxValue() const { return mMax; }
110 
111  void setParam( const TQString &d ) { mParam = d; }
112  TQString param() const { return mParam; }
113 
114  void setParamName( const TQString &d ) { mParamName = d; }
115  TQString paramName() const { return mParamName; }
116 
117  void setParamType( const TQString &d ) { mParamType = d; }
118  TQString paramType() const { return mParamType; }
119 
120  void setChoices( const TQValueList<Choice> &d ) { mChoices = d; }
121  TQValueList<Choice> choices() const { return mChoices; }
122 
123  void setParamValues( const TQStringList &d ) { mParamValues = d; }
124  TQStringList paramValues() const { return mParamValues; }
125 
126  void setParamDefaultValues( const TQStringList &d ) { mParamDefaultValues = d; }
127  TQString paramDefaultValue(int i) const { return mParamDefaultValues[i]; }
128 
129  void setParamMax( int d ) { mParamMax = d; }
130  int paramMax() const { return mParamMax; }
131 
132  bool hidden() const { return mHidden; }
133 
134  void dump() const
135  {
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;
142 // whatsthis
143  kdDebug() << " code: " << mCode << endl;
144 // kdDebug() << " values: " << mValues.join(":") << endl;
145 
146  if (!param().isEmpty())
147  {
148  kdDebug() << " param name: "<< mParamName << endl;
149  kdDebug() << " param type: "<< mParamType << endl;
150  kdDebug() << " paramvalues: " << mParamValues.join(":") << endl;
151  }
152  kdDebug() << " default: " << mDefaultValue << endl;
153  kdDebug() << " hidden: " << mHidden << endl;
154  kdDebug() << " min: " << mMin << endl;
155  kdDebug() << " max: " << mMax << endl;
156  kdDebug() << "</entry>" << endl;
157  }
158 
159  private:
160  TQString mGroup;
161  TQString mType;
162  TQString mKey;
163  TQString mName;
164  TQString mLabel;
165  TQString mWhatsThis;
166  TQString mCode;
167  TQString mDefaultValue;
168  TQString mParam;
169  TQString mParamName;
170  TQString mParamType;
171  TQValueList<Choice> mChoices;
172  TQStringList mParamValues;
173  TQStringList mParamDefaultValues;
174  int mParamMax;
175  bool mHidden;
176  TQString mMin;
177  TQString mMax;
178 };
179 
180 class Param {
181 public:
182  TQString name;
183  TQString type;
184 };
185 
186 // returns the name of an member variable
187 // use itemPath to know the full path
188 // like using d-> in case of dpointer
189 static TQString varName(const TQString &n)
190 {
191  TQString result;
192  if ( !dpointer ) {
193  result = "m"+n;
194  result[1] = result[1].upper();
195  }
196  else {
197  result = n;
198  result[0] = result[0].lower();
199  }
200  return result;
201 }
202 
203 static TQString varPath(const TQString &n)
204 {
205  TQString result;
206  if ( dpointer ) {
207  result = "d->"+varName(n);
208  }
209  else {
210  result = varName(n);
211  }
212  return result;
213 }
214 
215 static TQString enumName(const TQString &n)
216 {
217  TQString result = "Enum"+n;
218  result[4] = result[4].upper();
219  return result;
220 }
221 
222 static TQString setFunction(const TQString &n, const TQString &className = TQString())
223 {
224  TQString result = "set"+n;
225  result[3] = result[3].upper();
226 
227  if ( !className.isEmpty() )
228  result = className + "::" + result;
229  return result;
230 }
231 
232 
233 static TQString getFunction(const TQString &n, const TQString &className = TQString())
234 {
235  TQString result = n;
236  result[0] = result[0].lower();
237 
238  if ( !className.isEmpty() )
239  result = className + "::" + result;
240  return result;
241 }
242 
243 
244 static void addQuotes( TQString &s )
245 {
246  if ( s.left( 1 ) != "\"" ) s.prepend( "\"" );
247  if ( s.right( 1 ) != "\"" ) s.append( "\"" );
248 }
249 
250 static TQString quoteString( const TQString &s )
251 {
252  TQString r = s;
253  r.replace( "\\", "\\\\" );
254  r.replace( "\"", "\\\"" );
255  r.replace( "\r", "" );
256  r.replace( "\n", "\\n\"\n\"" );
257  return "\"" + r + "\"";
258 }
259 
260 static TQString literalString( const TQString &s )
261 {
262  bool isAscii = true;
263  for(int i = s.length(); i--;)
264  if (s[i].unicode() > 127) isAscii = false;
265 
266  if (isAscii)
267  return "TQString::fromLatin1( " + quoteString(s) + " )";
268  else
269  return "TQString::fromUtf8( " + quoteString(s) + " )";
270 }
271 
272 static TQString dumpNode(const TQDomNode &node)
273 {
274  TQString msg;
275  TQTextStream s(&msg, IO_WriteOnly );
276  node.save(s, 0);
277 
278  msg = msg.simplifyWhiteSpace();
279  if (msg.length() > 40)
280  return msg.left(37)+"...";
281  return msg;
282 }
283 
284 static TQString filenameOnly(TQString path)
285 {
286  int i = path.findRev('/');
287  if (i >= 0)
288  return path.mid(i+1);
289  return path;
290 }
291 
292 static void preProcessDefault( TQString &defaultValue, const TQString &name,
293  const TQString &type,
294  const TQValueList<CfgEntry::Choice> &choices,
295  TQString &code )
296 {
297  if ( type == "String" && !defaultValue.isEmpty() ) {
298  defaultValue = literalString(defaultValue);
299 
300  } else if ( type == "Path" && !defaultValue.isEmpty() ) {
301  defaultValue = literalString( defaultValue );
302 
303  } else if ( (type == "StringList" || type == "PathList") && !defaultValue.isEmpty() ) {
304  TQTextStream cpp( &code, IO_WriteOnly | IO_Append );
305  if (!code.isEmpty())
306  cpp << endl;
307 
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 << "\" ) );"
313  << endl;
314  }
315  defaultValue = "default" + name;
316 
317  } else if ( type == "Color" && !defaultValue.isEmpty() ) {
318  TQRegExp colorRe("\\d+,\\s*\\d+,\\s*\\d+");
319  if (colorRe.exactMatch(defaultValue))
320  {
321  defaultValue = "TQColor( " + defaultValue + " )";
322  }
323  else
324  {
325  defaultValue = "TQColor( \"" + defaultValue + "\" )";
326  }
327 
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) + "::");
334  break;
335  }
336  }
337  }
338 
339  } else if ( type == "IntList" ) {
340  TQTextStream cpp( &code, IO_WriteOnly | IO_Append );
341  if (!code.isEmpty())
342  cpp << endl;
343 
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 << " );"
349  << endl;
350  }
351  defaultValue = "default" + name;
352  }
353 }
354 
355 
356 CfgEntry *parseEntry( const TQString &group, const TQDomElement &element )
357 {
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" );
363  TQString label;
364  TQString whatsThis;
365  TQString defaultValue;
366  TQString code;
367  TQString param;
368  TQString paramName;
369  TQString paramType;
370  TQValueList<CfgEntry::Choice> choices;
371  TQStringList paramValues;
372  TQStringList paramDefaultValues;
373  TQString minValue;
374  TQString maxValue;
375  int paramMax = 0;
376 
377  TQDomNode n;
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" )
387  {
388  param = e.attribute( "name" );
389  paramType = e.attribute( "type" );
390  if ( param.isEmpty() ) {
391  kdError() << "Parameter must have a name: " << dumpNode(e) << endl;
392  return 0;
393  }
394  if ( paramType.isEmpty() ) {
395  kdError() << "Parameter must have a type: " << dumpNode(e) << endl;
396  return 0;
397  }
398  if ((paramType == "Int") || (paramType == "UInt"))
399  {
400  bool ok;
401  paramMax = e.attribute("max").toInt(&ok);
402  if (!ok)
403  {
404  kdError() << "Integer parameter must have a maximum (e.g. max=\"0\"): " << dumpNode(e) << endl;
405  return 0;
406  }
407  }
408  else if (paramType == "Enum")
409  {
410  TQDomNode n2;
411  for ( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
412  TQDomElement e2 = n2.toElement();
413  if (e2.tagName() == "values")
414  {
415  TQDomNode n3;
416  for ( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) {
417  TQDomElement e3 = n3.toElement();
418  if (e3.tagName() == "value")
419  {
420  paramValues.append( e3.text() );
421  }
422  }
423  break;
424  }
425  }
426  if (paramValues.isEmpty())
427  {
428  kdError() << "No values specified for parameter '" << param << "'." << endl;
429  return 0;
430  }
431  paramMax = paramValues.count()-1;
432  }
433  else
434  {
435  kdError() << "Parameter '" << param << "' has type " << paramType << " but must be of type int, uint or Enum." << endl;
436  return 0;
437  }
438  }
439  else if ( tag == "default" )
440  {
441  if (e.attribute("param").isEmpty())
442  {
443  defaultValue = e.text();
444  if (e.attribute( "code" ) == "true")
445  defaultCode = true;
446  }
447  }
448  else if ( tag == "choices" ) {
449  TQDomNode n2;
450  for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
451  TQDomElement e2 = n2.toElement();
452  if ( e2.tagName() == "choice" ) {
453  TQDomNode n3;
454  CfgEntry::Choice choice;
455  choice.name = e2.attribute( "name" );
456  if ( choice.name.isEmpty() ) {
457  kdError() << "Tag <choice> requires attribute 'name'." << endl;
458  }
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();
463  }
464  choices.append( choice );
465  }
466  }
467  }
468  }
469 
470  bool nameIsEmpty = name.isEmpty();
471  if ( nameIsEmpty && key.isEmpty() ) {
472  kdError() << "Entry must have a name or a key: " << dumpNode(element) << endl;
473  return 0;
474  }
475 
476  if ( key.isEmpty() ) {
477  key = name;
478  }
479 
480  if ( nameIsEmpty ) {
481  name = key;
482  name.replace( " ", TQString() );
483  } else if ( name.contains( ' ' ) ) {
484  kdWarning()<<"Entry '"<<name<<"' contains spaces! <name> elements can't contain speces!"<<endl;
485  name.remove( ' ' );
486  }
487 
488  if (name.contains("$("))
489  {
490  if (param.isEmpty())
491  {
492  kdError() << "Name may not be parameterized: " << name << endl;
493  return 0;
494  }
495  }
496  else
497  {
498  if (!param.isEmpty())
499  {
500  kdError() << "Name must contain '$(" << param << ")': " << name << endl;
501  return 0;
502  }
503  }
504 
505  if ( label.isEmpty() ) {
506  label = key;
507  }
508 
509  if ( type.isEmpty() ) type = "String"; // XXX : implicit type might be bad
510 
511  if (!param.isEmpty())
512  {
513  // Adjust name
514  paramName = name;
515  name.replace("$("+param+")", TQString());
516  // Lookup defaults for indexed entries
517  for(int i = 0; i <= paramMax; i++)
518  {
519  paramDefaultValues.append(TQString());
520  }
521 
522  TQDomNode n;
523  for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
524  TQDomElement e = n.toElement();
525  TQString tag = e.tagName();
526  if ( tag == "default" )
527  {
528  TQString index = e.attribute("param");
529  if (index.isEmpty())
530  continue;
531 
532  bool ok;
533  int i = index.toInt(&ok);
534  if (!ok)
535  {
536  i = paramValues.findIndex(index);
537  if (i == -1)
538  {
539  kdError() << "Index '" << index << "' for default value is unknown." << endl;
540  return 0;
541  }
542  }
543 
544  if ((i < 0) || (i > paramMax))
545  {
546  kdError() << "Index '" << i << "' for default value is out of range [0, "<< paramMax<<"]." << endl;
547  return 0;
548  }
549 
550  TQString tmpDefaultValue = e.text();
551 
552  if (e.attribute( "code" ) != "true")
553  preProcessDefault(tmpDefaultValue, name, type, choices, code);
554 
555  paramDefaultValues[i] = tmpDefaultValue;
556  }
557  }
558  }
559 
560  if (!validNameRegexp->exactMatch(name))
561  {
562  if (nameIsEmpty)
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;
565  else
566  kdError() << "The name '" << name << "' is not a valid name for an entry." << endl;
567  return 0;
568  }
569 
570  if (allNames.contains(name))
571  {
572  if (nameIsEmpty)
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;
575  else
576  kdError() << "The name '" << name << "' is not unique." << endl;
577  return 0;
578  }
579  allNames.append(name);
580 
581  if (!defaultCode)
582  {
583  preProcessDefault(defaultValue, name, type, choices, code);
584  }
585 
586  CfgEntry *result = new CfgEntry( group, type, key, name, label, whatsThis,
587  code, defaultValue, choices,
588  hidden == "true" );
589  if (!param.isEmpty())
590  {
591  result->setParam(param);
592  result->setParamName(paramName);
593  result->setParamType(paramType);
594  result->setParamValues(paramValues);
595  result->setParamDefaultValues(paramDefaultValues);
596  result->setParamMax(paramMax);
597  }
598  result->setMinValue(minValue);
599  result->setMaxValue(maxValue);
600 
601  return result;
602 }
603 
607 TQString param( const TQString &type )
608 {
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 &";
628  else {
629  kdError() <<"tdeconfig_compiler does not support type \""<< type <<"\""<<endl;
630  return "TQString"; //For now, but an assert would be better
631  }
632 }
633 
637 TQString cppType( const TQString &type )
638 {
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";
658  else {
659  kdError()<<"tdeconfig_compiler does not support type \""<< type <<"\""<<endl;
660  return "TQString"; //For now, but an assert would be better
661  }
662 }
663 
664 TQString defaultValue( const TQString &type )
665 {
666  if ( type == "String" ) return "\"\""; // Use empty string, not null string!
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 "\"\""; // Use empty string, not null string!
683  else if ( type == "PathList" ) return "TQStringList()";
684  else if ( type == "Password" ) return "\"\""; // Use empty string, not null string!
685  else {
686  kdWarning()<<"Error, tdeconfig_compiler doesn't support the \""<< type <<"\" type!"<<endl;
687  return "TQString"; //For now, but an assert would be better
688  }
689 }
690 
691 TQString itemType( const TQString &type )
692 {
693  TQString t;
694 
695  t = type;
696  t.replace( 0, 1, t.left( 1 ).upper() );
697 
698  return t;
699 }
700 
701 static TQString itemDeclaration(const CfgEntry *e)
702 {
703  if (itemAccessors)
704  return TQString();
705 
706  TQString fCap = e->name();
707  fCap[0] = fCap[0].upper();
708  return " TDEConfigSkeleton::Item"+itemType( e->type() ) +
709  " *item" + fCap +
710  ( (!e->param().isEmpty())?(TQString("[%1]").arg(e->paramMax()+1)) : TQString()) +
711  ";\n";
712 }
713 
714 // returns the name of an item variable
715 // use itemPath to know the full path
716 // like using d-> in case of dpointer
717 static TQString itemVar(const CfgEntry *e)
718 {
719  TQString result;
720  if (itemAccessors)
721  {
722  if ( !dpointer )
723  {
724  result = "m" + e->name() + "Item";
725  result[1] = result[1].upper();
726  }
727  else
728  {
729  result = e->name() + "Item";
730  result[0] = result[0].lower();
731  }
732  }
733  else
734  {
735  result = "item" + e->name();
736  result[4] = result[4].upper();
737  }
738  return result;
739 }
740 
741 static TQString itemPath(const CfgEntry *e)
742 {
743  TQString result;
744  if ( dpointer ) {
745  result = "d->"+itemVar(e);
746  }
747  else {
748  result = itemVar(e);
749  }
750  return result;
751 }
752 
753 TQString newItem( const TQString &type, const TQString &name, const TQString &key,
754  const TQString &defaultValue, const TQString &param = TQString())
755 {
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() ) {
760  t += ", ";
761  if ( type == "String" ) t += defaultValue;
762  else t+= defaultValue;
763  }
764  t += " );";
765 
766  return t;
767 }
768 
769 TQString paramString(const TQString &s, const CfgEntry *e, int i)
770 {
771  TQString result = s;
772  TQString needle = "$("+e->param()+")";
773  if (result.contains(needle))
774  {
775  TQString tmp;
776  if (e->paramType() == "Enum")
777  {
778  tmp = e->paramValues()[i];
779  }
780  else
781  {
782  tmp = TQString::number(i);
783  }
784 
785  result.replace(needle, tmp);
786  }
787  return result;
788 }
789 
790 TQString paramString(const TQString &group, const TQValueList<Param> &parameters)
791 {
792  TQString paramString = group;
793  TQString arguments;
794  int i = 1;
795  for (TQValueList<Param>::ConstIterator it = parameters.begin();
796  it != parameters.end(); ++it)
797  {
798  if (paramString.contains("$("+(*it).name+")"))
799  {
800  TQString tmp;
801  tmp.sprintf("%%%d", i++);
802  paramString.replace("$("+(*it).name+")", tmp);
803  arguments += ".arg( mParam"+(*it).name+" )";
804  }
805  }
806  if (arguments.isEmpty())
807  return "TQString::fromLatin1( \""+group+"\" )";
808 
809  return "TQString::fromLatin1( \""+paramString+"\" )"+arguments;
810 }
811 
812 /* int i is the value of the parameter */
813 TQString userTextsFunctions( CfgEntry *e, TQString itemVarStr=TQString(), TQString i=TQString() )
814 {
815  TQString txt;
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));
821  else
822  txt+= quoteString(e->label());
823  txt+= ") );\n";
824  }
825  if ( !e->whatsThis().isEmpty() ) {
826  txt += " " + itemVarStr + "->setWhatsThis( i18n(";
827  if ( !e->param().isEmpty() )
828  txt += quoteString(e->whatsThis().replace("$("+e->param()+")", i));
829  else
830  txt+= quoteString(e->whatsThis());
831  txt+=") );\n";
832  }
833  return txt;
834 }
835 
836 // returns the member accesor implementation
837 // which should go in the h file if inline
838 // or the cpp file if not inline
839 TQString memberAccessorBody( CfgEntry *e )
840 {
841  TQString result;
842  TQTextStream out(&result, IO_WriteOnly);
843  TQString n = e->name();
844  TQString t = e->type();
845 
846  out << "return " << This << varPath(n);
847  if (!e->param().isEmpty()) out << "[i]";
848  out << ";" << endl;
849 
850  return result;
851 }
852 
853 // returns the member mutator implementation
854 // which should go in the h file if inline
855 // or the cpp file if not inline
856 TQString memberMutatorBody( CfgEntry *e )
857 {
858  TQString result;
859  TQTextStream out(&result, IO_WriteOnly);
860  TQString n = e->name();
861  TQString t = e->type();
862 
863  if (!e->minValue().isEmpty())
864  {
865  out << "if (v < " << e->minValue() << ")" << endl;
866  out << "{" << 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;
871  out << "}" << endl;
872  }
873 
874  if (!e->maxValue().isEmpty())
875  {
876  out << endl << "if (v > " << e->maxValue() << ")" << endl;
877  out << "{" << 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;
883  }
884 
885  out << "if (!" << This << "isImmutable( TQString::fromLatin1( \"";
886  if (!e->param().isEmpty())
887  {
888  out << e->paramName().replace("$("+e->param()+")", "%1") << "\" ).arg( ";
889  if ( e->paramType() == "Enum" ) {
890  out << "TQString::fromLatin1( ";
891 
892  if (globalEnums)
893  out << enumName(e->param()) << "ToString[i]";
894  else
895  out << enumName(e->param()) << "::enumToString[i]";
896 
897  out << " )";
898  }
899  else
900  {
901  out << "i";
902  }
903  out << " )";
904  }
905  else
906  {
907  out << n << "\" )";
908  }
909  out << " ))" << endl;
910  out << " " << This << varPath(n);
911  if (!e->param().isEmpty())
912  out << "[i]";
913  out << " = v;" << endl;
914 
915  return result;
916 }
917 
918 // returns the item accesor implementation
919 // which should go in the h file if inline
920 // or the cpp file if not inline
921 TQString itemAccessorBody( CfgEntry *e )
922 {
923  TQString result;
924  TQTextStream out(&result, IO_WriteOnly);
925 
926  out << "return " << itemPath(e);
927  if (!e->param().isEmpty()) out << "[i]";
928  out << ";" << endl;
929 
930  return result;
931 }
932 
933 //indents text adding X spaces per line
934 TQString indent(TQString text, int spaces)
935 {
936  TQString result;
937  TQTextStream out(&result, IO_WriteOnly);
938  TQTextStream in(&text, IO_ReadOnly);
939  TQString currLine;
940  while ( !in.atEnd() )
941  {
942  currLine = in.readLine();
943  if (!currLine.isEmpty())
944  for (int i=0; i < spaces; i++)
945  out << " ";
946  out << currLine << endl;
947  }
948  return result;
949 }
950 
951 
952 int main( int argc, char **argv )
953 {
954  TDEAboutData aboutData( "tdeconfig_compiler", I18N_NOOP("TDE .kcfg compiler"), "0.3",
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" );
963 
964  TDECmdLineArgs::init( argc, argv, &aboutData );
965  TDECmdLineArgs::addCmdLineOptions( options );
966 
967  TDEInstance app( &aboutData );
968 
969  TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
970 
971  if ( args->count() < 2 ) {
972  kdError() << "Too few arguments." << endl;
973  return 1;
974  }
975  if ( args->count() > 2 ) {
976  kdError() << "Too many arguments." << endl;
977  return 1;
978  }
979 
980  validNameRegexp = new TQRegExp("[a-zA-Z_][a-zA-Z0-9_]*");
981 
982  TQString baseDir = TQFile::decodeName(args->getOption("directory"));
983  if (!baseDir.endsWith("/"))
984  baseDir.append("/");
985 
986  TQString inputFilename = args->url( 0 ).path();
987  TQString codegenFilename = args->url( 1 ).path();
988 
989  if (!codegenFilename.endsWith(".kcfgc"))
990  {
991  kdError() << "Codegen options file must have extension .kcfgc" << endl;
992  return 1;
993  }
994  TQString baseName = args->url( 1 ).fileName();
995  baseName = baseName.left(baseName.length() - 6);
996 
997  KSimpleConfig codegenConfig( codegenFilename, true );
998 
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;
1006  //bool useDPointer = codegenConfig.readBoolEntry("DPointer", false);
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"))
1013  allMutators = true;
1014  itemAccessors = codegenConfig.readBoolEntry( "ItemAccessors", false );
1015  bool setUserTexts = codegenConfig.readBoolEntry( "SetUserTexts", false );
1016 
1017  globalEnums = codegenConfig.readBoolEntry( "GlobalEnums", false );
1018 
1019  dpointer = (memberVariables == "dpointer");
1020 
1021  TQFile input( inputFilename );
1022 
1023  TQDomDocument doc;
1024  TQString errorMsg;
1025  int errorRow;
1026  int errorCol;
1027  if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
1028  kdError() << "Unable to load document." << endl;
1029  kdError() << "Parse error in " << args->url( 0 ).fileName() << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl;
1030  return 1;
1031  }
1032 
1033  TQDomElement cfgElement = doc.documentElement();
1034 
1035  if ( cfgElement.isNull() ) {
1036  kdError() << "No document in kcfg file" << endl;
1037  return 1;
1038  }
1039 
1040  TQString cfgFileName;
1041  bool cfgFileNameArg = false;
1042  TQValueList<Param> parameters;
1043  TQStringList includes;
1044 
1045  TQPtrList<CfgEntry> entries;
1046  entries.setAutoDelete( true );
1047 
1048  TQDomNode n;
1049  for ( n = cfgElement.firstChild(); !n.isNull(); n = n.nextSibling() ) {
1050  TQDomElement e = n.toElement();
1051 
1052  TQString tag = e.tagName();
1053 
1054  if ( tag == "include" ) {
1055  TQString includeFile = e.text();
1056  if (!includeFile.isEmpty())
1057  includes.append(includeFile);
1058 
1059  } else if ( tag == "kcfgfile" ) {
1060  cfgFileName = e.attribute( "name" );
1061  cfgFileNameArg = e.attribute( "arg" ).lower() == "true";
1062  TQDomNode n2;
1063  for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
1064  TQDomElement e2 = n2.toElement();
1065  if ( e2.tagName() == "parameter" ) {
1066  Param p;
1067  p.name = e2.attribute( "name" );
1068  p.type = e2.attribute( "type" );
1069  if (p.type.isEmpty())
1070  p.type = "String";
1071  parameters.append( p );
1072  }
1073  }
1074 
1075  } else if ( tag == "group" ) {
1076  TQString group = e.attribute( "name" );
1077  if ( group.isEmpty() ) {
1078  kdError() << "Group without name" << endl;
1079  return 1;
1080  }
1081  TQDomNode n2;
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 );
1087  else {
1088  kdError() << "Can't parse entry." << endl;
1089  return 1;
1090  }
1091  }
1092  }
1093  }
1094 
1095  if ( inherits.isEmpty() ) inherits = "TDEConfigSkeleton";
1096 
1097  if ( className.isEmpty() ) {
1098  kdError() << "Class name missing" << endl;
1099  return 1;
1100  }
1101 
1102  if ( singleton && !parameters.isEmpty() ) {
1103  kdError() << "Singleton class can not have parameters" << endl;
1104  return 1;
1105  }
1106 
1107  if ( !cfgFileName.isEmpty() && cfgFileNameArg)
1108  {
1109  kdError() << "Having both a fixed filename and a filename as argument is not possible." << endl;
1110  return 1;
1111  }
1112 
1113  if ( entries.isEmpty() ) {
1114  kdWarning() << "No entries." << endl;
1115  }
1116 
1117 #if 0
1118  CfgEntry *cfg;
1119  for( cfg = entries.first(); cfg; cfg = entries.next() ) {
1120  cfg->dump();
1121  }
1122 #endif
1123 
1124  TQString headerFileName = baseName + ".h";
1125  TQString implementationFileName = baseName + ".cpp";
1126  TQString cppPreamble; // code to be inserted at the beginnin of the cpp file, e.g. initialization of static values
1127 
1128  TQFile header( baseDir + headerFileName );
1129  if ( !header.open( IO_WriteOnly ) ) {
1130  kdError() << "Can't open '" << headerFileName << "' for writing." << endl;
1131  return 1;
1132  }
1133 
1134  TQTextStream h( &header );
1135 
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;
1138 
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;
1143 
1144  // Includes
1145  TQStringList::ConstIterator it;
1146  for( it = headerIncludes.begin(); it != headerIncludes.end(); ++it ) {
1147  h << "#include <" << *it << ">" << endl;
1148  }
1149 
1150  if ( headerIncludes.count() > 0 ) h << endl;
1151 
1152  if ( !singleton && cfgFileNameArg && parameters.isEmpty() )
1153  h << "#include <tdeglobal.h>" << endl;
1154 
1155  h << "#include <tdeconfigskeleton.h>" << endl;
1156  h << "#include <kdebug.h>" << endl << endl;
1157 
1158  // Includes
1159  for( it = includes.begin(); it != includes.end(); ++it ) {
1160  h << "#include <" << *it << ">" << endl;
1161  }
1162 
1163 
1164  if ( !nameSpace.isEmpty() )
1165  h << "namespace " << nameSpace << " {" << endl << endl;
1166 
1167  // Private class declaration
1168  if ( dpointer )
1169  h << "class " << className << "Private;" << endl << endl;
1170 
1171  // Class declaration header
1172  h << "class " << visibility << className << " : public " << inherits << endl;
1173  h << "{" << endl;
1174  h << " public:" << endl;
1175 
1176  // enums
1177  CfgEntry *e;
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 );
1185  }
1186  if ( globalEnums ) {
1187  h << " enum { " << values.join( ", " ) << " };" << endl;
1188  } else {
1189  h << " class " << enumName(e->name()) << endl;
1190  h << " {" << endl;
1191  h << " public:" << endl;
1192  h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl;
1193  h << " };" << endl;
1194  }
1195  }
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";
1203  } else {
1204  h << " class " << enumName(e->param()) << endl;
1205  h << " {" << endl;
1206  h << " public:" << endl;
1207  h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl;
1208  h << " static const char* const enumToString[];" << endl;
1209  h << " };" << endl;
1210  cppPreamble += "const char* const " + className + "::" + enumName(e->param()) + "::enumToString[] = " +
1211  "{ \"" + values.join( "\", \"" ) + "\" };\n";
1212  }
1213  }
1214  }
1215 
1216  h << endl;
1217 
1218  // Constructor or singleton accessor
1219  if ( !singleton ) {
1220  h << " " << className << "(";
1221  if (cfgFileNameArg)
1222  h << " TDESharedConfig::Ptr config" << (parameters.isEmpty() ? " = TDEGlobal::sharedConfig()" : ", ");
1223  for (TQValueList<Param>::ConstIterator it = parameters.begin();
1224  it != parameters.end(); ++it)
1225  {
1226  if (it != parameters.begin())
1227  h << ",";
1228  h << " " << param((*it).type) << " " << (*it).name;
1229  }
1230  h << " );" << endl;
1231  } else {
1232  h << " static " << className << " *self();" << endl;
1233  if (cfgFileNameArg)
1234  h << " static void instance(const char * cfgfilename);" << endl;
1235  }
1236 
1237  // Destructor
1238  h << " ~" << className << "();" << endl << endl;
1239 
1240  // global variables
1241  if (staticAccessors)
1242  This = "self()->";
1243  else
1244  Const = " const";
1245 
1246  for( e = entries.first(); e; e = entries.next() ) {
1247  TQString n = e->name();
1248  TQString t = e->type();
1249 
1250  // Manipulator
1251  if (allMutators || mutators.contains(n))
1252  {
1253  h << " /**" << endl;
1254  h << " Set " << e->label() << endl;
1255  h << " */" << 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 )";
1262  // function body inline only if not using dpointer
1263  // for BC mode
1264  if ( !dpointer )
1265  {
1266  h << endl << " {" << endl;
1267  h << indent(memberMutatorBody(e), 6 );
1268  h << " }" << endl;
1269  }
1270  else
1271  {
1272  h << ";" << endl;
1273  }
1274  }
1275  h << endl;
1276  // Accessor
1277  h << " /**" << endl;
1278  h << " Get " << e->label() << endl;
1279  h << " */" << 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 ";
1285  h << ")" << Const;
1286  // function body inline only if not using dpointer
1287  // for BC mode
1288  if ( !dpointer )
1289  {
1290  h << endl << " {" << endl;
1291  h << indent(memberAccessorBody(e), 6 );
1292  h << " }" << endl;
1293  }
1294  else
1295  {
1296  h << ";" << endl;
1297  }
1298 
1299  // Item accessor
1300  if ( itemAccessors ) {
1301  h << endl;
1302  h << " /**" << endl;
1303  h << " Get Item object corresponding to " << n << "()"
1304  << endl;
1305  h << " */" << endl;
1306  h << " Item" << itemType( e->type() ) << " *"
1307  << getFunction( n ) << "Item(";
1308  if (!e->param().isEmpty()) {
1309  h << " " << cppType(e->paramType()) << " i ";
1310  }
1311  h << ")";
1312  if (! dpointer )
1313  {
1314  h << endl << " {" << endl;
1315  h << indent( itemAccessorBody(e), 6);
1316  h << " }" << endl;
1317  }
1318  else
1319  {
1320  h << ";" << endl;
1321  }
1322  }
1323 
1324  h << endl;
1325  }
1326 
1327  // Static writeConfig method for singleton
1328  if ( singleton ) {
1329  h << " static" << endl;
1330  h << " void writeConfig()" << endl;
1331  h << " {" << endl;
1332  h << " static_cast<TDEConfigSkeleton*>(self())->writeConfig();" << endl;
1333  h << " }" << endl;
1334  }
1335 
1336  h << " protected:" << endl;
1337 
1338  // Private constructor for singleton
1339  if ( singleton ) {
1340  h << " " << className << "(";
1341  if ( cfgFileNameArg )
1342  h << "const char *arg";
1343  h << ");" << endl;
1344  h << " static " << className << " *mSelf;" << endl << endl;
1345  }
1346 
1347  // Member variables
1348  if ( !memberVariables.isEmpty() && memberVariables != "private" && memberVariables != "dpointer") {
1349  h << " " << memberVariables << ":" << endl;
1350  }
1351 
1352  // Class Parameters
1353  for (TQValueList<Param>::ConstIterator it = parameters.begin();
1354  it != parameters.end(); ++it)
1355  {
1356  h << " " << cppType((*it).type) << " mParam" << (*it).name << ";" << endl;
1357  }
1358 
1359  if ( memberVariables != "dpointer" )
1360  {
1361  TQString group;
1362  for( e = entries.first(); e; e = entries.next() ) {
1363  if ( e->group() != group ) {
1364  group = e->group();
1365  h << endl;
1366  h << " // " << group << endl;
1367  }
1368  h << " " << cppType(e->type()) << " " << varName(e->name());
1369  if (!e->param().isEmpty())
1370  {
1371  h << TQString("[%1]").arg(e->paramMax()+1);
1372  }
1373  h << ";" << endl;
1374  }
1375 
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 );
1381  h << ";" << endl;
1382  }
1383  }
1384 
1385  }
1386  else
1387  {
1388  // use a private class for both member variables and items
1389  h << " private:" << endl;
1390  h << " " + className + "Private *d;" << endl;
1391  }
1392 
1393  if (customAddons)
1394  {
1395  h << " // Include custom additions" << endl;
1396  h << " #include \"" << filenameOnly(baseName) << "_addons.h\"" <<endl;
1397  }
1398 
1399  h << "};" << endl << endl;
1400 
1401  if ( !nameSpace.isEmpty() ) h << "}" << endl << endl;
1402 
1403  h << "#endif" << endl << endl;
1404 
1405 
1406  header.close();
1407 
1408  TQFile implementation( baseDir + implementationFileName );
1409  if ( !implementation.open( IO_WriteOnly ) ) {
1410  kdError() << "Can't open '" << implementationFileName << "' for writing."
1411  << endl;
1412  return 1;
1413  }
1414 
1415  TQTextStream cpp( &implementation );
1416 
1417 
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;
1420 
1421  cpp << "#include \"" << headerFileName << "\"" << endl << endl;
1422 
1423  if ( setUserTexts ) cpp << "#include <tdelocale.h>" << endl << endl;
1424 
1425  // Header required by singleton implementation
1426  if ( singleton )
1427  cpp << "#include <kstaticdeleter.h>" << endl << endl;
1428  if ( singleton && cfgFileNameArg )
1429  cpp << "#include <kdebug.h>" << endl << endl;
1430 
1431  if ( !nameSpace.isEmpty() )
1432  cpp << "using namespace " << nameSpace << ";" << endl << endl;
1433 
1434  TQString group;
1435 
1436  // private class implementation
1437  if ( dpointer )
1438  {
1439  cpp << "class " << className << "Private" << endl;
1440  cpp << "{" << endl;
1441  cpp << " public:" << endl;
1442  for( e = entries.first(); e; e = entries.next() ) {
1443  if ( e->group() != group ) {
1444  group = e->group();
1445  cpp << endl;
1446  cpp << " // " << group << endl;
1447  }
1448  cpp << " " << cppType(e->type()) << " " << varName(e->name());
1449  if (!e->param().isEmpty())
1450  {
1451  cpp << TQString("[%1]").arg(e->paramMax()+1);
1452  }
1453  cpp << ";" << endl;
1454  }
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 );
1459  cpp << ";" << endl;
1460  }
1461 
1462  cpp << "};" << endl << endl;
1463  }
1464 
1465  // Singleton implementation
1466  if ( singleton ) {
1467  cpp << className << " *" << className << "::mSelf = 0;" << endl;
1468  cpp << "static KStaticDeleter<" << className << "> static" << className << "Deleter;" << endl << endl;
1469 
1470  cpp << className << " *" << className << "::self()" << endl;
1471  cpp << "{" << endl;
1472  if ( cfgFileNameArg ) {
1473  cpp << " if (!mSelf)" << endl;
1474  cpp << " kdFatal() << \"you need to call " << className << "::instance before using\" << endl;" << endl;
1475  } else {
1476  cpp << " if ( !mSelf ) {" << endl;
1477  cpp << " static" << className << "Deleter.setObject( mSelf, new " << className << "() );" << endl;
1478  cpp << " mSelf->readConfig();" << endl;
1479  cpp << " }" << endl << endl;
1480  }
1481  cpp << " return mSelf;" << endl;
1482  cpp << "}" << endl << endl;
1483 
1484  if ( cfgFileNameArg ) {
1485  cpp << "void " << className << "::instance(const char *cfgfilename)" << endl;
1486  cpp << "{" << 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;
1494  }
1495  }
1496 
1497  if ( !cppPreamble.isEmpty() )
1498  cpp << cppPreamble << endl;
1499 
1500  // Constructor
1501  cpp << className << "::" << className << "( ";
1502  if ( cfgFileNameArg ) {
1503  if ( !singleton )
1504  cpp << " TDESharedConfig::Ptr config";
1505  else
1506  cpp << " const char *config";
1507  cpp << (parameters.isEmpty() ? " " : ", ");
1508  }
1509 
1510  for (TQValueList<Param>::ConstIterator it = parameters.begin();
1511  it != parameters.end(); ++it)
1512  {
1513  if (it != parameters.begin())
1514  cpp << ",";
1515  cpp << " " << param((*it).type) << " " << (*it).name;
1516  }
1517  cpp << " )" << endl;
1518 
1519  cpp << " : " << inherits << "(";
1520  if ( !cfgFileName.isEmpty() ) cpp << " TQString::fromLatin1( \"" << cfgFileName << "\" ";
1521  if ( cfgFileNameArg ) cpp << " config ";
1522  if ( !cfgFileName.isEmpty() ) cpp << ") ";
1523  cpp << ")" << endl;
1524 
1525  // Store parameters
1526  for (TQValueList<Param>::ConstIterator it = parameters.begin();
1527  it != parameters.end(); ++it)
1528  {
1529  cpp << " , mParam" << (*it).name << "(" << (*it).name << ")" << endl;
1530  }
1531 
1532  cpp << "{" << endl;
1533 
1534  if (dpointer)
1535  cpp << " d = new " + className + "Private;" << endl;
1536  // Needed in case the singleton class is used as baseclass for
1537  // another singleton.
1538  if ( singleton )
1539  cpp << " mSelf = this;" << endl;
1540 
1541  group = TQString();
1542  for( e = entries.first(); e; e = entries.next() ) {
1543  if ( e->group() != group ) {
1544  if ( !group.isEmpty() ) cpp << endl;
1545  group = e->group();
1546  cpp << " setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl;
1547  }
1548 
1549  TQString key = paramString(e->key(), parameters);
1550  if ( !e->code().isEmpty())
1551  {
1552  cpp << e->code() << endl;
1553  }
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;
1568  }
1569  cpp << " values" << e->name() << ".append( choice );" << endl;
1570  cpp << " }" << endl;
1571  }
1572  }
1573 
1574  if (!dpointer)
1575  cpp << itemDeclaration(e);
1576 
1577  if (e->param().isEmpty())
1578  {
1579  // Normal case
1580  cpp << " " << itemPath(e) << " = "
1581  << newItem( e->type(), e->name(), key, e->defaultValue() ) << endl;
1582 
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;
1587 
1588  if ( setUserTexts )
1589  cpp << userTextsFunctions( e );
1590 
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;
1596  }
1597  else
1598  {
1599  // Indexed
1600  for(int i = 0; i <= e->paramMax(); i++)
1601  {
1602  TQString defaultStr;
1603  TQString itemVarStr(itemPath(e)+TQString("[%1]").arg(i));
1604 
1605  if ( !e->paramDefaultValue(i).isEmpty() )
1606  defaultStr = e->paramDefaultValue(i);
1607  else if ( !e->defaultValue().isEmpty() )
1608  defaultStr = paramString(e->defaultValue(), e, i);
1609  else
1610  defaultStr = defaultValue( e->type() );
1611 
1612  cpp << " " << itemVarStr << " = "
1613  << newItem( e->type(), e->name(), paramString(key, e, i), defaultStr, TQString("[%1]").arg(i) )
1614  << endl;
1615 
1616  if ( setUserTexts )
1617  cpp << userTextsFunctions( e, itemVarStr, e->paramName() );
1618 
1619  // Make mutators for enum parameters work by adding them with $(..) replaced by the
1620  // param name. The check for isImmutable in the set* functions doesn't have the param
1621  // name available, just the corresponding enum value (int), so we need to store the
1622  // param names in a separate static list!.
1623  cpp << " addItem( " << itemVarStr << ", TQString::fromLatin1( \"";
1624  if ( e->paramType()=="Enum" )
1625  cpp << e->paramName().replace( "$("+e->param()+")", "%1").arg(e->paramValues()[i] );
1626  else
1627  cpp << e->paramName().replace( "$("+e->param()+")", "%1").arg(i);
1628  cpp << "\" ) );" << endl;
1629  }
1630  }
1631  }
1632 
1633  cpp << "}" << endl << endl;
1634 
1635  if (dpointer)
1636  {
1637  // setters and getters go in Cpp if in dpointer mode
1638  for( e = entries.first(); e; e = entries.next() )
1639  {
1640  TQString n = e->name();
1641  TQString t = e->type();
1642 
1643  // Manipulator
1644  if (allMutators || mutators.contains(n))
1645  {
1646  cpp << "void " << setFunction(n, className) << "( ";
1647  if (!e->param().isEmpty())
1648  cpp << cppType(e->paramType()) << " i, ";
1649  cpp << param( t ) << " v )" << endl;
1650  // function body inline only if not using dpointer
1651  // for BC mode
1652  cpp << "{" << endl;
1653  cpp << indent(memberMutatorBody(e), 6);
1654  cpp << "}" << endl << endl;
1655  }
1656 
1657  // Accessor
1658  cpp << cppType(t) << " " << getFunction(n, className) << "(";
1659  if (!e->param().isEmpty())
1660  cpp << " " << cppType(e->paramType()) <<" i ";
1661  cpp << ")" << Const << endl;
1662  // function body inline only if not using dpointer
1663  // for BC mode
1664  cpp << "{" << endl;
1665  cpp << indent(memberAccessorBody(e), 2);
1666  cpp << "}" << endl << endl;
1667 
1668  // Item accessor
1669  if ( itemAccessors )
1670  {
1671  cpp << endl;
1672  cpp << "TDEConfigSkeleton::Item" << itemType( e->type() ) << " *"
1673  << getFunction( n, className ) << "Item(";
1674  if (!e->param().isEmpty()) {
1675  cpp << " " << cppType(e->paramType()) << " i ";
1676  }
1677  cpp << ")" << endl;
1678  cpp << "{" << endl;
1679  cpp << indent(itemAccessorBody(e), 2);
1680  cpp << "}" << endl;
1681  }
1682 
1683  cpp << endl;
1684  }
1685  }
1686 
1687  // Destructor
1688  cpp << className << "::~" << className << "()" << endl;
1689  cpp << "{" << endl;
1690  if ( singleton ) {
1691  if ( dpointer )
1692  cpp << " delete d;" << endl;
1693  cpp << " if ( mSelf == this )" << endl;
1694  cpp << " static" << className << "Deleter.setObject( mSelf, 0, false );" << endl;
1695  }
1696  cpp << "}" << endl << endl;
1697 
1698  implementation.close();
1699 }
KSimpleConfig
KDE Configuration entries.
Definition: ksimpleconfig.h:42
KURL::path
TQString path() const
Returns the current decoded path.
Definition: kurl.h:532
KURL::fileName
TQString fileName(bool _ignore_trailing_slash_in_path=true) const
Returns the filename of the path.
Definition: kurl.cpp:1709
TDEAboutData
This class is used to store information about a program.
Definition: tdeaboutdata.h:183
TDEAction::text
virtual TQString text() const
TDECmdLineArgs
A class for command-line argument handling.
Definition: tdecmdlineargs.h:223
TDECmdLineArgs::parsedArgs
static TDECmdLineArgs * parsedArgs(const char *id=0)
Access parsed arguments.
Definition: tdecmdlineargs.cpp:310
TDECmdLineArgs::addCmdLineOptions
static void addCmdLineOptions(const TDECmdLineOptions *options, const char *name=0, const char *id=0, const char *afterId=0)
Add options to your application.
Definition: tdecmdlineargs.cpp:206
TDECmdLineArgs::url
KURL url(int n) const
Read out an argument representing a URL.
Definition: tdecmdlineargs.cpp:1248
TDECmdLineArgs::getOption
TQCString getOption(const char *option) const
Read out a string option.
Definition: tdecmdlineargs.cpp:1119
TDECmdLineArgs::count
int count() const
Read the number of arguments that aren't options (but, for example, filenames).
Definition: tdecmdlineargs.cpp:1224
TDECmdLineArgs::init
static void init(int _argc, char **_argv, const char *_appname, const char *programName, const char *_description, const char *_version, bool noKApp=false)
Initialize class.
Definition: tdecmdlineargs.cpp:127
TDEInstance
Access to KDE global objects for use in shared libraries.
Definition: kinstance.h:48
TDELocale::I18N_NOOP
#define I18N_NOOP(x)
I18N_NOOP marks a string to be translated without translating it.
Definition: tdelocale.h:51
endl
kndbgstream & endl(kndbgstream &s)
Does nothing.
Definition: kdebug.h:583
TDEGlobal::kdWarning
kdbgstream kdWarning(int area=0)
Returns a warning stream.
Definition: kdebug.cpp:376
TDEGlobal::kdError
kdbgstream kdError(int area=0)
Returns an error stream.
Definition: kdebug.cpp:374
TDEGlobal::endl
kdbgstream & endl(kdbgstream &s)
Prints an "\n".
Definition: kdebug.h:430
KStdAction::whatsThis
TDEAction * whatsThis(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
KStdAction::name
const char * name(StdAction id)
TDEStdAccel::key
int key(StdAccel id)
Definition: tdestdaccel.cpp:383
TDEStdAccel::label
TQString label(StdAccel id)
Returns a localized label for user-visible display.
Definition: tdestdaccel.cpp:156
TDECmdLineOptions
Structure that holds command line options.
Definition: tdecmdlineargs.h:41
tdelocale.h

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.1
This website is maintained by Timothy Pearson.