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

kdecore

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

kdecore

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

kdecore

Skip menu "kdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kdecore by doxygen 1.8.11
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |