• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • sources
  • kde-4.12
  • kdelibs
  • kdecore
  • kconfig_compiler
kconfig_compiler.cpp
Go to the documentation of this file.
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  Copyright (c) 2006 MichaĆ«l Larouche <michael.larouche@kdemail.net>
9  Copyright (c) 2008 Allen Winter <winter@kde.org>
10 
11  This library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU Library General Public
13  License as published by the Free Software Foundation; either
14  version 2 of the License, or (at your option) any later version.
15 
16  This library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  Library General Public License for more details.
20 
21  You should have received a copy of the GNU Library General Public License
22  along with this library; see the file COPYING.LIB. If not, write to
23  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  Boston, MA 02110-1301, USA.
25 */
26 
27 // Compiling this file with this flag is just crazy
28 #undef QT_NO_CAST_FROM_ASCII
29 
30 #include <QtCore/QCoreApplication>
31 #include <QtCore/QFile>
32 #include <QtCore/QFileInfo>
33 #include <QtCore/QSettings>
34 #include <QtCore/QTextStream>
35 #include <QtXml/QDomAttr>
36 #include <QtCore/QRegExp>
37 #include <QtCore/QStringList>
38 
39 #include <ostream>
40 #include <iostream>
41 #include <stdlib.h>
42 
43 namespace
44 {
45  QTextStream cout(stdout);
46  QTextStream cerr(stderr);
47 }
48 
49 static void parseArgs(const QStringList &args, QString &directory, QString &file1, QString &file2)
50 {
51  int fileCount = 0;
52  directory = QChar::fromLatin1('.');
53 
54  for (int i = 1; i < args.count(); ++i) {
55  if (args.at(i) == QLatin1String("-d") || args.at(i) == QLatin1String("--directory")) {
56  if (i + 1 > args.count()) {
57  cerr << args.at(i) << " needs an argument" << endl;
58  exit(1);
59  }
60  directory = args.at(++i);
61  } else if (args.at(i).startsWith(QLatin1String("-d"))) {
62  directory = args.at(i).mid(2);
63  } else if (args.at(i) == QLatin1String("--help") || args.at(i) == QLatin1String("-h")) {
64  cout << "Options:" << endl;
65  cout << " -L --license Display software license" << endl;
66  cout << " -d, --directory <dir> Directory to generate files in [.]" << endl;
67  cout << " -h, --help Display this help" << endl;
68  cout << endl;
69  cout << "Arguments:" << endl;
70  cout << " file.kcfg Input kcfg XML file" << endl;
71  cout << " file.kcfgc Code generation options file" << endl;
72  exit(0);
73  } else if (args.at(i) == QLatin1String("--license") || args.at(i) == QLatin1String("-L")) {
74  cout << "Copyright 2003 Cornelius Schumacher, Waldo Bastian, Zack Rusin," << endl;
75  cout << " Reinhold Kainhofer, Duncan Mac-Vicar P., Harald Fernengel" << endl;
76  cout << "This program comes with ABSOLUTELY NO WARRANTY." << endl;
77  cout << "You may redistribute copies of this program" << endl;
78  cout << "under the terms of the GNU Library Public License." << endl;
79  cout << "For more information about these matters, see the file named COPYING." << endl;
80  exit(0);
81  } else if (args.at(i).startsWith(QLatin1Char('-'))) {
82  cerr << "Unknown option: " << args.at(i) << endl;
83  exit(1);
84  } else if (fileCount == 0) {
85  file1 = args.at(i);
86  ++fileCount;
87  } else if (fileCount == 1) {
88  file2 = args.at(i);
89  ++fileCount;
90  } else {
91  cerr << "Too many arguments" << endl;
92  exit(1);
93  }
94  }
95  if (fileCount < 2) {
96  cerr << "Too few arguments" << endl;
97  exit(1);
98  }
99 }
100 
101 QStringList allNames;
102 QRegExp *validNameRegexp;
103 QString This;
104 QString Const;
105 
109 class CfgConfig
110 {
111 public:
112  CfgConfig( const QString &codegenFilename )
113  {
114  // Configure the compiler with some settings
115  QSettings codegenConfig(codegenFilename, QSettings::IniFormat);
116 
117  nameSpace = codegenConfig.value("NameSpace").toString();
118  className = codegenConfig.value("ClassName").toString();
119  if ( className.isEmpty() ) {
120  cerr << "Class name missing" << endl;
121  exit(1);
122  }
123  inherits = codegenConfig.value("Inherits").toString();
124  if ( inherits.isEmpty() ) inherits = "KConfigSkeleton";
125  visibility = codegenConfig.value("Visibility").toString();
126  if ( !visibility.isEmpty() ) visibility += ' ';
127  forceStringFilename = codegenConfig.value("ForceStringFilename", false).toBool();
128  singleton = codegenConfig.value("Singleton", false).toBool();
129  staticAccessors = singleton;
130  customAddons = codegenConfig.value("CustomAdditions", false).toBool();
131  memberVariables = codegenConfig.value("MemberVariables").toString();
132  dpointer = (memberVariables == "dpointer");
133  headerIncludes = codegenConfig.value("IncludeFiles", QStringList()).toStringList();
134  sourceIncludes = codegenConfig.value("SourceIncludeFiles", QStringList()).toStringList();
135  mutators = codegenConfig.value("Mutators", QStringList()).toStringList();
136  allMutators = ((mutators.count() == 1) && (mutators.at(0).toLower() == "true"));
137  itemAccessors = codegenConfig.value("ItemAccessors", false).toBool();
138  setUserTexts = codegenConfig.value("SetUserTexts", false).toBool();
139  defaultGetters = codegenConfig.value("DefaultValueGetters", QStringList()).toStringList();
140  allDefaultGetters = (defaultGetters.count() == 1) && (defaultGetters.at(0).toLower() == "true");
141  globalEnums = codegenConfig.value("GlobalEnums", false).toBool();
142  useEnumTypes = codegenConfig.value("UseEnumTypes", false).toBool();
143  }
144 
145 public:
146  // These are read from the .kcfgc configuration file
147  QString nameSpace; // The namespace for the class to be generated
148  QString className; // The class name to be generated
149  QString inherits; // The class the generated class inherits (if empty, from KConfigSkeleton)
150  QString visibility;
151  bool forceStringFilename;
152  bool singleton; // The class will be a singleton
153  bool staticAccessors; // provide or not static accessors
154  bool customAddons;
155  QString memberVariables;
156  QStringList headerIncludes;
157  QStringList sourceIncludes;
158  QStringList mutators;
159  QStringList defaultGetters;
160  bool allMutators;
161  bool setUserTexts;
162  bool allDefaultGetters;
163  bool dpointer;
164  bool globalEnums;
165  bool useEnumTypes;
166  bool itemAccessors;
167 };
168 
169 
170 struct SignalArguments
171 {
172  QString type;
173  QString variableName;
174 };
175 
176 class Signal {
177 public:
178  QString name;
179  QString label;
180  QList<SignalArguments> arguments;
181 };
182 
183 
184 
185 
186 class CfgEntry
187 {
188  public:
189  struct Choice
190  {
191  QString name;
192  QString context;
193  QString label;
194  QString toolTip;
195  QString whatsThis;
196  };
197  class Choices
198  {
199  public:
200  Choices() {}
201  Choices( const QList<Choice> &d, const QString &n, const QString &p )
202  : prefix(p), choices(d), mName(n)
203  {
204  int i = n.indexOf(QLatin1String("::"));
205  if (i >= 0)
206  mExternalQual = n.left(i + 2);
207  }
208  QString prefix;
209  QList<Choice> choices;
210  const QString& name() const { return mName; }
211  const QString& externalQualifier() const { return mExternalQual; }
212  bool external() const { return !mExternalQual.isEmpty(); }
213  private:
214  QString mName;
215  QString mExternalQual;
216  };
217 
218  CfgEntry( const QString &group, const QString &type, const QString &key,
219  const QString &name, const QString &labelContext, const QString &label,
220  const QString &toolTipContext, const QString &toolTip, const QString &whatsThisContext, const QString &whatsThis, const QString &code,
221  const QString &defaultValue, const Choices &choices, const QList<Signal> signalList,
222  bool hidden )
223  : mGroup( group ), mType( type ), mKey( key ), mName( name ),
224  mLabelContext( labelContext ), mLabel( label ), mToolTipContext( toolTipContext ), mToolTip( toolTip ),
225  mWhatsThisContext( whatsThisContext ), mWhatsThis( whatsThis ),
226  mCode( code ), mDefaultValue( defaultValue ), mChoices( choices ),
227  mSignalList(signalList), mHidden( hidden )
228  {
229  }
230 
231  void setGroup( const QString &group ) { mGroup = group; }
232  QString group() const { return mGroup; }
233 
234  void setType( const QString &type ) { mType = type; }
235  QString type() const { return mType; }
236 
237  void setKey( const QString &key ) { mKey = key; }
238  QString key() const { return mKey; }
239 
240  void setName( const QString &name ) { mName = name; }
241  QString name() const { return mName; }
242 
243  void setLabelContext( const QString &labelContext ) { mLabelContext = labelContext; }
244  QString labelContext() const { return mLabelContext; }
245 
246  void setLabel( const QString &label ) { mLabel = label; }
247  QString label() const { return mLabel; }
248 
249  void setToolTipContext( const QString &toolTipContext ) { mToolTipContext = toolTipContext; }
250  QString toolTipContext() const { return mToolTipContext; }
251 
252  void setToolTip( const QString &toolTip ) { mToolTip = toolTip; }
253  QString toolTip() const { return mToolTip; }
254 
255  void setWhatsThisContext( const QString &whatsThisContext ) { mWhatsThisContext = whatsThisContext; }
256  QString whatsThisContext() const { return mWhatsThisContext; }
257 
258  void setWhatsThis( const QString &whatsThis ) { mWhatsThis = whatsThis; }
259  QString whatsThis() const { return mWhatsThis; }
260 
261  void setDefaultValue( const QString &d ) { mDefaultValue = d; }
262  QString defaultValue() const { return mDefaultValue; }
263 
264  void setCode( const QString &d ) { mCode = d; }
265  QString code() const { return mCode; }
266 
267  void setMinValue( const QString &d ) { mMin = d; }
268  QString minValue() const { return mMin; }
269 
270  void setMaxValue( const QString &d ) { mMax = d; }
271  QString maxValue() const { return mMax; }
272 
273  void setParam( const QString &d ) { mParam = d; }
274  QString param() const { return mParam; }
275 
276  void setParamName( const QString &d ) { mParamName = d; }
277  QString paramName() const { return mParamName; }
278 
279  void setParamType( const QString &d ) { mParamType = d; }
280  QString paramType() const { return mParamType; }
281 
282  void setChoices( const QList<Choice> &d, const QString &n, const QString &p ) { mChoices = Choices( d, n, p ); }
283  Choices choices() const { return mChoices; }
284 
285  void setParamValues( const QStringList &d ) { mParamValues = d; }
286  QStringList paramValues() const { return mParamValues; }
287 
288  void setParamDefaultValues( const QStringList &d ) { mParamDefaultValues = d; }
289  QString paramDefaultValue(int i) const { return mParamDefaultValues[i]; }
290 
291  void setParamMax( int d ) { mParamMax = d; }
292  int paramMax() const { return mParamMax; }
293 
294  void setSignalList( const QList<Signal> &value ) { mSignalList = value; }
295  QList<Signal> signalList() const { return mSignalList; }
296 
297  bool hidden() const { return mHidden; }
298 
299  void dump() const
300  {
301  cerr << "<entry>" << endl;
302  cerr << " group: " << mGroup << endl;
303  cerr << " type: " << mType << endl;
304  cerr << " key: " << mKey << endl;
305  cerr << " name: " << mName << endl;
306  cerr << " label context: " << mLabelContext << endl;
307  cerr << " label: " << mLabel << endl;
308 // whatsthis
309  cerr << " code: " << mCode << endl;
310 // cerr << " values: " << mValues.join(":") << endl;
311 
312  if (!param().isEmpty())
313  {
314  cerr << " param name: "<< mParamName << endl;
315  cerr << " param type: "<< mParamType << endl;
316  cerr << " paramvalues: " << mParamValues.join(QChar::fromLatin1(':')) << endl;
317  }
318  cerr << " default: " << mDefaultValue << endl;
319  cerr << " hidden: " << mHidden << endl;
320  cerr << " min: " << mMin << endl;
321  cerr << " max: " << mMax << endl;
322  cerr << "</entry>" << endl;
323  }
324 
325  private:
326  QString mGroup;
327  QString mType;
328  QString mKey;
329  QString mName;
330  QString mLabelContext;
331  QString mLabel;
332  QString mToolTipContext;
333  QString mToolTip;
334  QString mWhatsThisContext;
335  QString mWhatsThis;
336  QString mCode;
337  QString mDefaultValue;
338  QString mParam;
339  QString mParamName;
340  QString mParamType;
341  Choices mChoices;
342  QList<Signal> mSignalList;
343  QStringList mParamValues;
344  QStringList mParamDefaultValues;
345  int mParamMax;
346  bool mHidden;
347  QString mMin;
348  QString mMax;
349 };
350 
351 class Param {
352 public:
353  QString name;
354  QString type;
355 };
356 
357 // returns the name of an member variable
358 // use itemPath to know the full path
359 // like using d-> in case of dpointer
360 static QString varName(const QString &n, const CfgConfig &cfg)
361 {
362  QString result;
363  if ( !cfg.dpointer ) {
364  result = QChar::fromLatin1('m') + n;
365  result[1] = result[1].toUpper();
366  }
367  else {
368  result = n;
369  result[0] = result[0].toLower();
370  }
371  return result;
372 }
373 
374 static QString varPath(const QString &n, const CfgConfig &cfg)
375 {
376  QString result;
377  if ( cfg.dpointer ) {
378  result = "d->"+varName(n, cfg);
379  }
380  else {
381  result = varName(n, cfg);
382  }
383  return result;
384 }
385 
386 static QString enumName(const QString &n)
387 {
388  QString result = QString::fromLatin1("Enum") + n;
389  result[4] = result[4].toUpper();
390  return result;
391 }
392 
393 static QString enumName(const QString &n, const CfgEntry::Choices &c)
394 {
395  QString result = c.name();
396  if ( result.isEmpty() )
397  {
398  result = QString::fromLatin1("Enum") + n;
399  result[4] = result[4].toUpper();
400  }
401  return result;
402 }
403 
404 static QString enumType(const CfgEntry *e, bool globalEnums)
405 {
406  QString result = e->choices().name();
407  if ( result.isEmpty() )
408  {
409  result = QString::fromLatin1("Enum") + e->name();
410  if( !globalEnums )
411  result += QString::fromLatin1("::type");
412  result[4] = result[4].toUpper();
413  }
414  return result;
415 }
416 
417 static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
418 {
419  QString result = c.name();
420  if ( result.isEmpty() )
421  {
422  result = QString::fromLatin1("Enum") + n + QString::fromLatin1("::");
423  result[4] = result[4].toUpper();
424  }
425  else if ( c.external() )
426  result = c.externalQualifier();
427  else
428  result.clear();
429  return result;
430 }
431 
432 static QString setFunction(const QString &n, const QString &className = QString())
433 {
434  QString result = QString::fromLatin1("set") + n;
435  result[3] = result[3].toUpper();
436 
437  if ( !className.isEmpty() )
438  result = className + QString::fromLatin1("::") + result;
439  return result;
440 }
441 
442 static QString getDefaultFunction(const QString &n, const QString &className = QString())
443 {
444  QString result = QString::fromLatin1("default") + n + QString::fromLatin1("Value");
445  result[7] = result[7].toUpper();
446 
447  if ( !className.isEmpty() )
448  result = className + QString::fromLatin1("::") + result;
449  return result;
450 }
451 
452 static QString getFunction(const QString &n, const QString &className = QString())
453 {
454  QString result = n;
455  result[0] = result[0].toLower();
456 
457  if ( !className.isEmpty() )
458  result = className + QString::fromLatin1("::") + result;
459  return result;
460 }
461 
462 
463 static void addQuotes( QString &s )
464 {
465  if ( !s.startsWith( QLatin1Char('"') ) )
466  s.prepend( QLatin1Char('"') );
467  if ( !s.endsWith( QLatin1Char('"') ) )
468  s.append( QLatin1Char('"') );
469 }
470 
471 static QString quoteString( const QString &s )
472 {
473  QString r = s;
474  r.replace( QLatin1Char('\\'), QLatin1String("\\\\") );
475  r.replace( QLatin1Char('\"'), QLatin1String("\\\"") );
476  r.remove( QLatin1Char('\r') );
477  r.replace( QLatin1Char('\n'), QLatin1String("\\n\"\n\"") );
478  return QLatin1Char('\"') + r + QLatin1Char('\"');
479 }
480 
481 static QString literalString( const QString &s )
482 {
483  bool isAscii = true;
484  for(int i = s.length(); i--;)
485  if (s[i].unicode() > 127) isAscii = false;
486 
487  if (isAscii)
488  return QString::fromLatin1("QLatin1String( ") + quoteString(s) + QString::fromLatin1(" )");
489  else
490  return QString::fromLatin1("QString::fromUtf8( ") + quoteString(s) + QString::fromLatin1(" )");
491 }
492 
493 static QString dumpNode(const QDomNode &node)
494 {
495  QString msg;
496  QTextStream s(&msg, QIODevice::WriteOnly );
497  node.save(s, 0);
498 
499  msg = msg.simplified();
500  if (msg.length() > 40)
501  return msg.left(37) + QString::fromLatin1("...");
502  return msg;
503 }
504 
505 static QString filenameOnly(const QString& path)
506 {
507  int i = path.lastIndexOf(QRegExp(QLatin1String("[/\\]")));
508  if (i >= 0)
509  return path.mid(i+1);
510  return path;
511 }
512 
513 static QString signalEnumName(const QString &signalName)
514 {
515  QString result;
516  result = QString::fromLatin1("signal") + signalName;
517  result[6] = result[6].toUpper();
518 
519  return result;
520 }
521 
522 static void preProcessDefault( QString &defaultValue, const QString &name,
523  const QString &type,
524  const CfgEntry::Choices &choices,
525  QString &code, const CfgConfig &cfg )
526 {
527  if ( type == QLatin1String("String") && !defaultValue.isEmpty() ) {
528  defaultValue = literalString(defaultValue);
529 
530  } else if ( type == QLatin1String("Path") && !defaultValue.isEmpty() ) {
531  defaultValue = literalString( defaultValue );
532  } else if ( type == QLatin1String("Url") && !defaultValue.isEmpty() ) {
533  defaultValue = QString::fromLatin1("KUrl( ") + literalString(defaultValue) + QLatin1Char(')');
534  } else if ( ( type == QLatin1String("UrlList") || type == QLatin1String("StringList") || type == QLatin1String("PathList")) && !defaultValue.isEmpty() ) {
535  QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
536  if (!code.isEmpty())
537  cpp << endl;
538 
539  if( type == "UrlList" ) {
540  cpp << " KUrl::List default" << name << ";" << endl;
541  } else {
542  cpp << " QStringList default" << name << ";" << endl;
543  }
544  const QStringList defaults = defaultValue.split(QLatin1Char(','));
545  QStringList::ConstIterator it;
546  for( it = defaults.constBegin(); it != defaults.constEnd(); ++it ) {
547  cpp << " default" << name << ".append( ";
548  if( type == "UrlList" ) {
549  cpp << "KUrl(";
550  }
551  cpp << "QString::fromUtf8( \"" << *it << "\" ) ";
552  if( type == QLatin1String("UrlList") ) {
553  cpp << ") ";
554  }
555  cpp << ");" << endl;
556  }
557  defaultValue = QString::fromLatin1("default") + name;
558 
559  } else if ( type == QLatin1String("Color") && !defaultValue.isEmpty() ) {
560  QRegExp colorRe(QLatin1String("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?"));
561  if (colorRe.exactMatch(defaultValue))
562  {
563  defaultValue = QLatin1String("QColor( ") + defaultValue + QLatin1String(" )");
564  }
565  else
566  {
567  defaultValue = QLatin1String("QColor( \"") + defaultValue + QLatin1String("\" )");
568  }
569 
570  } else if ( type == QLatin1String("Enum") ) {
571  QList<CfgEntry::Choice>::ConstIterator it;
572  for( it = choices.choices.constBegin(); it != choices.choices.constEnd(); ++it ) {
573  if ( (*it).name == defaultValue ) {
574  if ( cfg.globalEnums && choices.name().isEmpty() )
575  defaultValue.prepend( choices.prefix );
576  else
577  defaultValue.prepend( enumTypeQualifier(name, choices) + choices.prefix );
578  break;
579  }
580  }
581 
582  } else if ( type == QLatin1String("IntList") ) {
583  QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
584  if (!code.isEmpty())
585  cpp << endl;
586 
587  cpp << " QList<int> default" << name << ";" << endl;
588  if (!defaultValue.isEmpty())
589  {
590  const QStringList defaults = defaultValue.split( QLatin1Char(',') );
591  QStringList::ConstIterator it;
592  for( it = defaults.constBegin(); it != defaults.constEnd(); ++it ) {
593  cpp << " default" << name << ".append( " << *it << " );"
594  << endl;
595  }
596  }
597  defaultValue = QString::fromLatin1("default") + name;
598  }
599 }
600 
601 
602 CfgEntry *parseEntry( const QString &group, const QDomElement &element, const CfgConfig &cfg )
603 {
604  bool defaultCode = false;
605  QString type = element.attribute( "type" );
606  QString name = element.attribute( "name" );
607  QString key = element.attribute( "key" );
608  QString hidden = element.attribute( "hidden" );
609  QString labelContext;
610  QString label;
611  QString toolTipContext;
612  QString toolTip;
613  QString whatsThisContext;
614  QString whatsThis;
615  QString defaultValue;
616  QString code;
617  QString param;
618  QString paramName;
619  QString paramType;
620  CfgEntry::Choices choices;
621  QList<Signal> signalList;
622  QStringList paramValues;
623  QStringList paramDefaultValues;
624  QString minValue;
625  QString maxValue;
626  int paramMax = 0;
627 
628  for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
629  QString tag = e.tagName();
630  if ( tag == "label" ) {
631  label = e.text();
632  labelContext = e.attribute( "context" );
633  }
634  else if ( tag == "tooltip" ) {
635  toolTip = e.text();
636  toolTipContext = e.attribute( "context" );
637  }
638  else if ( tag == "whatsthis" ) {
639  whatsThis = e.text();
640  whatsThisContext = e.attribute( "context" );
641  }
642  else if ( tag == "min" ) minValue = e.text();
643  else if ( tag == "max" ) maxValue = e.text();
644  else if ( tag == "code" ) code = e.text();
645  else if ( tag == "parameter" )
646  {
647  param = e.attribute( "name" );
648  paramType = e.attribute( "type" );
649  if ( param.isEmpty() ) {
650  cerr << "Parameter must have a name: " << dumpNode(e) << endl;
651  return 0;
652  }
653  if ( paramType.isEmpty() ) {
654  cerr << "Parameter must have a type: " << dumpNode(e) << endl;
655  return 0;
656  }
657  if ((paramType == "Int") || (paramType == "UInt"))
658  {
659  bool ok;
660  paramMax = e.attribute("max").toInt(&ok);
661  if (!ok)
662  {
663  cerr << "Integer parameter must have a maximum (e.g. max=\"0\"): "
664  << dumpNode(e) << endl;
665  return 0;
666  }
667  }
668  else if (paramType == "Enum")
669  {
670  for ( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
671  if (e2.tagName() == "values")
672  {
673  for ( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) {
674  if (e3.tagName() == "value")
675  {
676  paramValues.append( e3.text() );
677  }
678  }
679  break;
680  }
681  }
682  if (paramValues.isEmpty())
683  {
684  cerr << "No values specified for parameter '" << param
685  << "'." << endl;
686  return 0;
687  }
688  paramMax = paramValues.count()-1;
689  }
690  else
691  {
692  cerr << "Parameter '" << param << "' has type " << paramType
693  << " but must be of type int, uint or Enum." << endl;
694  return 0;
695  }
696  }
697  else if ( tag == "default" )
698  {
699  if (e.attribute("param").isEmpty())
700  {
701  defaultValue = e.text();
702  if (e.attribute( "code" ) == "true")
703  defaultCode = true;
704  }
705  }
706  else if ( tag == "choices" ) {
707  QString name = e.attribute( "name" );
708  QString prefix = e.attribute( "prefix" );
709  QList<CfgEntry::Choice> chlist;
710  for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
711  if ( e2.tagName() == "choice" ) {
712  CfgEntry::Choice choice;
713  choice.name = e2.attribute( "name" );
714  if ( choice.name.isEmpty() ) {
715  cerr << "Tag <choice> requires attribute 'name'." << endl;
716  }
717  for( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) {
718  if ( e3.tagName() == "label" ) {
719  choice.label = e3.text();
720  choice.context = e3.attribute( "context" );
721  }
722  if ( e3.tagName() == "tooltip" ) {
723  choice.toolTip = e3.text();
724  choice.context = e3.attribute( "context" );
725  }
726  if ( e3.tagName() == "whatsthis" ) {
727  choice.whatsThis = e3.text();
728  choice.context = e3.attribute( "context" );
729  }
730  }
731  chlist.append( choice );
732  }
733  }
734  choices = CfgEntry::Choices( chlist, name, prefix );
735  }
736  else if ( tag == "emit" ) {
737  QDomNode signalNode;
738  Signal signal;
739  signal.name = e.attribute( "signal" );
740  signalList.append( signal);
741  }
742  }
743 
744 
745  bool nameIsEmpty = name.isEmpty();
746  if ( nameIsEmpty && key.isEmpty() ) {
747  cerr << "Entry must have a name or a key: " << dumpNode(element) << endl;
748  return 0;
749  }
750 
751  if ( key.isEmpty() ) {
752  key = name;
753  }
754 
755  if ( nameIsEmpty ) {
756  name = key;
757  name.remove( ' ' );
758  } else if ( name.contains( ' ' ) ) {
759  cout<<"Entry '"<<name<<"' contains spaces! <name> elements can not contain spaces!"<<endl;
760  name.remove( ' ' );
761  }
762 
763  if (name.contains("$("))
764  {
765  if (param.isEmpty())
766  {
767  cerr << "Name may not be parameterized: " << name << endl;
768  return 0;
769  }
770  }
771  else
772  {
773  if (!param.isEmpty())
774  {
775  cerr << "Name must contain '$(" << param << ")': " << name << endl;
776  return 0;
777  }
778  }
779 
780  if ( label.isEmpty() ) {
781  label = key;
782  }
783 
784  if ( type.isEmpty() ) type = "String"; // XXX : implicit type might be bad
785 
786  if (!param.isEmpty())
787  {
788  // Adjust name
789  paramName = name;
790  name.remove("$("+param+')');
791  // Lookup defaults for indexed entries
792  for(int i = 0; i <= paramMax; i++)
793  {
794  paramDefaultValues.append(QString());
795  }
796 
797  for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
798  QString tag = e.tagName();
799  if ( tag == "default" )
800  {
801  QString index = e.attribute("param");
802  if (index.isEmpty())
803  continue;
804 
805  bool ok;
806  int i = index.toInt(&ok);
807  if (!ok)
808  {
809  i = paramValues.indexOf(index);
810  if (i == -1)
811  {
812  cerr << "Index '" << index << "' for default value is unknown." << endl;
813  return 0;
814  }
815  }
816 
817  if ((i < 0) || (i > paramMax))
818  {
819  cerr << "Index '" << i << "' for default value is out of range [0, "<< paramMax<<"]." << endl;
820  return 0;
821  }
822 
823  QString tmpDefaultValue = e.text();
824 
825  if (e.attribute( "code" ) != "true")
826  preProcessDefault(tmpDefaultValue, name, type, choices, code, cfg);
827 
828  paramDefaultValues[i] = tmpDefaultValue;
829  }
830  }
831  }
832 
833  if (!validNameRegexp->exactMatch(name))
834  {
835  if (nameIsEmpty)
836  cerr << "The key '" << key << "' can not be used as name for the entry because "
837  "it is not a valid name. You need to specify a valid name for this entry." << endl;
838  else
839  cerr << "The name '" << name << "' is not a valid name for an entry." << endl;
840  return 0;
841  }
842 
843  if (allNames.contains(name))
844  {
845  if (nameIsEmpty)
846  cerr << "The key '" << key << "' can not be used as name for the entry because "
847  "it does not result in a unique name. You need to specify a unique name for this entry." << endl;
848  else
849  cerr << "The name '" << name << "' is not unique." << endl;
850  return 0;
851  }
852  allNames.append(name);
853 
854  if (!defaultCode)
855  {
856  preProcessDefault(defaultValue, name, type, choices, code, cfg);
857  }
858 
859  CfgEntry *result = new CfgEntry( group, type, key, name, labelContext, label, toolTipContext, toolTip, whatsThisContext, whatsThis,
860  code, defaultValue, choices, signalList,
861  hidden == "true" );
862  if (!param.isEmpty())
863  {
864  result->setParam(param);
865  result->setParamName(paramName);
866  result->setParamType(paramType);
867  result->setParamValues(paramValues);
868  result->setParamDefaultValues(paramDefaultValues);
869  result->setParamMax(paramMax);
870  }
871  result->setMinValue(minValue);
872  result->setMaxValue(maxValue);
873 
874  return result;
875 }
876 
877 static bool isUnsigned(const QString& type)
878 {
879  if ( type == "UInt" ) return true;
880  if ( type == "ULongLong" ) return true;
881  return false;
882 }
883 
887 QString param( const QString &t )
888 {
889  const QString type = t.toLower();
890  if ( type == "string" ) return "const QString &";
891  else if ( type == "stringlist" ) return "const QStringList &";
892  else if ( type == "font" ) return "const QFont &";
893  else if ( type == "rect" ) return "const QRect &";
894  else if ( type == "size" ) return "const QSize &";
895  else if ( type == "color" ) return "const QColor &";
896  else if ( type == "point" ) return "const QPoint &";
897  else if ( type == "int" ) return "int";
898  else if ( type == "uint" ) return "uint";
899  else if ( type == "bool" ) return "bool";
900  else if ( type == "double" ) return "double";
901  else if ( type == "datetime" ) return "const QDateTime &";
902  else if ( type == "longlong" ) return "qint64";
903  else if ( type == "ulonglong" ) return "quint64";
904  else if ( type == "intlist" ) return "const QList<int> &";
905  else if ( type == "enum" ) return "int";
906  else if ( type == "path" ) return "const QString &";
907  else if ( type == "pathlist" ) return "const QStringList &";
908  else if ( type == "password" ) return "const QString &";
909  else if ( type == "url" ) return "const KUrl &";
910  else if ( type == "urllist" ) return "const KUrl::List &";
911  else {
912  cerr <<"kconfig_compiler does not support type \""<< type <<"\""<<endl;
913  return "QString"; //For now, but an assert would be better
914  }
915 }
916 
920 QString cppType( const QString &t )
921 {
922  const QString type = t.toLower();
923  if ( type == "string" ) return "QString";
924  else if ( type == "stringlist" ) return "QStringList";
925  else if ( type == "font" ) return "QFont";
926  else if ( type == "rect" ) return "QRect";
927  else if ( type == "size" ) return "QSize";
928  else if ( type == "color" ) return "QColor";
929  else if ( type == "point" ) return "QPoint";
930  else if ( type == "int" ) return "int";
931  else if ( type == "uint" ) return "uint";
932  else if ( type == "bool" ) return "bool";
933  else if ( type == "double" ) return "double";
934  else if ( type == "datetime" ) return "QDateTime";
935  else if ( type == "longlong" ) return "qint64";
936  else if ( type == "ulonglong" ) return "quint64";
937  else if ( type == "intlist" ) return "QList<int>";
938  else if ( type == "enum" ) return "int";
939  else if ( type == "path" ) return "QString";
940  else if ( type == "pathlist" ) return "QStringList";
941  else if ( type == "password" ) return "QString";
942  else if ( type == "url" ) return "KUrl";
943  else if ( type == "urllist" ) return "KUrl::List";
944  else {
945  cerr<<"kconfig_compiler does not support type \""<< type <<"\""<<endl;
946  return "QString"; //For now, but an assert would be better
947  }
948 }
949 
950 QString defaultValue( const QString &t )
951 {
952  const QString type = t.toLower();
953  if ( type == "string" ) return "\"\""; // Use empty string, not null string!
954  else if ( type == "stringlist" ) return "QStringList()";
955  else if ( type == "font" ) return "QFont()";
956  else if ( type == "rect" ) return "QRect()";
957  else if ( type == "size" ) return "QSize()";
958  else if ( type == "color" ) return "QColor(128, 128, 128)";
959  else if ( type == "point" ) return "QPoint()";
960  else if ( type == "int" ) return "0";
961  else if ( type == "uint" ) return "0";
962  else if ( type == "bool" ) return "false";
963  else if ( type == "double" ) return "0.0";
964  else if ( type == "datetime" ) return "QDateTime()";
965  else if ( type == "longlong" ) return "0";
966  else if ( type == "ulonglong" ) return "0";
967  else if ( type == "intlist" ) return "QList<int>()";
968  else if ( type == "enum" ) return "0";
969  else if ( type == "path" ) return "\"\""; // Use empty string, not null string!
970  else if ( type == "pathlist" ) return "QStringList()";
971  else if ( type == "password" ) return "\"\""; // Use empty string, not null string!
972  else if ( type == "url" ) return "KUrl()";
973  else if ( type == "urllist" ) return "KUrl::List()";
974  else {
975  cerr<<"Error, kconfig_compiler does not support the \""<< type <<"\" type!"<<endl;
976  return "QString"; //For now, but an assert would be better
977  }
978 }
979 
980 QString itemType( const QString &type )
981 {
982  QString t;
983 
984  t = type;
985  t.replace( 0, 1, t.left( 1 ).toUpper() );
986 
987  return t;
988 }
989 
990 static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg)
991 {
992  if (cfg.itemAccessors)
993  return QString();
994 
995  QString fCap = e->name();
996  fCap[0] = fCap[0].toUpper();
997  return " "+cfg.inherits+"::Item"+itemType( e->type() ) +
998  " *item" + fCap +
999  ( (!e->param().isEmpty())?(QString("[%1]").arg(e->paramMax()+1)) : QString()) +
1000  ";\n";
1001 }
1002 
1003 // returns the name of an item variable
1004 // use itemPath to know the full path
1005 // like using d-> in case of dpointer
1006 static QString itemVar(const CfgEntry *e, const CfgConfig &cfg)
1007 {
1008  QString result;
1009  if (cfg.itemAccessors)
1010  {
1011  if ( !cfg.dpointer )
1012  {
1013  result = 'm' + e->name() + "Item";
1014  result[1] = result[1].toUpper();
1015  }
1016  else
1017  {
1018  result = e->name() + "Item";
1019  result[0] = result[0].toLower();
1020  }
1021  }
1022  else
1023  {
1024  result = "item" + e->name();
1025  result[4] = result[4].toUpper();
1026  }
1027  return result;
1028 }
1029 
1030 static QString itemPath(const CfgEntry *e, const CfgConfig &cfg)
1031 {
1032  QString result;
1033  if ( cfg.dpointer ) {
1034  result = "d->"+itemVar(e, cfg);
1035  }
1036  else {
1037  result = itemVar(e, cfg);
1038  }
1039  return result;
1040 }
1041 
1042 QString newItem( const QString &type, const QString &name, const QString &key,
1043  const QString &defaultValue, const CfgConfig &cfg, const QString &param = QString())
1044 {
1045  QString t = "new "+cfg.inherits+"::Item" + itemType( type ) +
1046  "( currentGroup(), " + key + ", " + varPath( name, cfg ) + param;
1047  if ( type == "Enum" ) t += ", values" + name;
1048  if ( !defaultValue.isEmpty() ) {
1049  t += ", ";
1050  if ( type == "String" ) t += defaultValue;
1051  else t+= defaultValue;
1052  }
1053  t += " );";
1054 
1055  return t;
1056 }
1057 
1058 QString paramString(const QString &s, const CfgEntry *e, int i)
1059 {
1060  QString result = s;
1061  QString needle = "$("+e->param()+')';
1062  if (result.contains(needle))
1063  {
1064  QString tmp;
1065  if (e->paramType() == "Enum")
1066  {
1067  tmp = e->paramValues()[i];
1068  }
1069  else
1070  {
1071  tmp = QString::number(i);
1072  }
1073 
1074  result.replace(needle, tmp);
1075  }
1076  return result;
1077 }
1078 
1079 QString paramString(const QString &group, const QList<Param> &parameters)
1080 {
1081  QString paramString = group;
1082  QString arguments;
1083  int i = 1;
1084  for (QList<Param>::ConstIterator it = parameters.constBegin();
1085  it != parameters.constEnd(); ++it)
1086  {
1087  if (paramString.contains("$("+(*it).name+')'))
1088  {
1089  QString tmp;
1090  tmp.sprintf("%%%d", i++);
1091  paramString.replace("$("+(*it).name+')', tmp);
1092  arguments += ".arg( mParam"+(*it).name+" )";
1093  }
1094  }
1095  if (arguments.isEmpty())
1096  return "QLatin1String( \""+group+"\" )";
1097 
1098  return "QString( QLatin1String( \""+paramString+"\" ) )"+arguments;
1099 }
1100 
1101 /* int i is the value of the parameter */
1102 QString userTextsFunctions( CfgEntry *e, const CfgConfig &cfg, QString itemVarStr=QString(), QString i=QString() )
1103 {
1104  QString txt;
1105  if (itemVarStr.isNull()) itemVarStr=itemPath(e, cfg);
1106  if ( !e->label().isEmpty() ) {
1107  txt += " " + itemVarStr + "->setLabel( ";
1108  if ( !e->labelContext().isEmpty() )
1109  txt += "i18nc(" + quoteString(e->labelContext()) + ", ";
1110  else
1111  txt += "i18n(";
1112  if ( !e->param().isEmpty() )
1113  txt += quoteString(e->label().replace("$("+e->param()+')', i));
1114  else
1115  txt+= quoteString(e->label());
1116  txt+= ") );\n";
1117  }
1118  if ( !e->toolTip().isEmpty() ) {
1119  txt += " " + itemVarStr + "->setToolTip( ";
1120  if ( !e->toolTipContext().isEmpty() )
1121  txt += "i18nc(" + quoteString(e->toolTipContext()) + ", ";
1122  else
1123  txt += "i18n(";
1124  if ( !e->param().isEmpty() )
1125  txt += quoteString(e->toolTip().replace("$("+e->param()+')', i));
1126  else
1127  txt+= quoteString(e->toolTip());
1128  txt+=") );\n";
1129  }
1130  if ( !e->whatsThis().isEmpty() ) {
1131  txt += " " + itemVarStr + "->setWhatsThis( ";
1132  if ( !e->whatsThisContext().isEmpty() )
1133  txt += "i18nc(" + quoteString(e->whatsThisContext()) + ", ";
1134  else
1135  txt += "i18n(";
1136  if ( !e->param().isEmpty() )
1137  txt += quoteString(e->whatsThis().replace("$("+e->param()+')', i));
1138  else
1139  txt+= quoteString(e->whatsThis());
1140  txt+=") );\n";
1141  }
1142  return txt;
1143 }
1144 
1145 // returns the member accesor implementation
1146 // which should go in the h file if inline
1147 // or the cpp file if not inline
1148 QString memberAccessorBody( CfgEntry *e, bool globalEnums, const CfgConfig &cfg )
1149 {
1150  QString result;
1151  QTextStream out(&result, QIODevice::WriteOnly);
1152  QString n = e->name();
1153  QString t = e->type();
1154  bool useEnumType = cfg.useEnumTypes && t == "Enum";
1155 
1156  out << "return ";
1157  if (useEnumType)
1158  out << "static_cast<" << enumType(e, globalEnums) << ">(";
1159  out << This << varPath(n, cfg);
1160  if (!e->param().isEmpty())
1161  out << "[i]";
1162  if (useEnumType)
1163  out << ")";
1164  out << ";" << endl;
1165 
1166  return result;
1167 }
1168 
1169 // returns the member mutator implementation
1170 // which should go in the h file if inline
1171 // or the cpp file if not inline
1172 QString memberMutatorBody( CfgEntry *e, const CfgConfig &cfg )
1173 {
1174  QString result;
1175  QTextStream out(&result, QIODevice::WriteOnly);
1176  QString n = e->name();
1177  QString t = e->type();
1178 
1179  if (!e->minValue().isEmpty())
1180  {
1181  if (e->minValue() != "0" || !isUnsigned(t)) { // skip writing "if uint<0" (#187579)
1182  out << "if (v < " << e->minValue() << ")" << endl;
1183  out << "{" << endl;
1184  out << " kDebug() << \"" << setFunction(n);
1185  out << ": value \" << v << \" is less than the minimum value of ";
1186  out << e->minValue()<< "\";" << endl;
1187  out << " v = " << e->minValue() << ";" << endl;
1188  out << "}" << endl;
1189  }
1190  }
1191 
1192  if (!e->maxValue().isEmpty())
1193  {
1194  out << endl << "if (v > " << e->maxValue() << ")" << endl;
1195  out << "{" << endl;
1196  out << " kDebug() << \"" << setFunction(n);
1197  out << ": value \" << v << \" is greater than the maximum value of ";
1198  out << e->maxValue()<< "\";" << endl;
1199  out << " v = " << e->maxValue() << ";" << endl;
1200  out << "}" << endl << endl;
1201  }
1202 
1203  out << "if (!" << This << "isImmutable( QString::fromLatin1( \"";
1204  if (!e->param().isEmpty())
1205  {
1206  out << e->paramName().replace("$("+e->param()+")", "%1") << "\" ).arg( ";
1207  if ( e->paramType() == "Enum" ) {
1208  out << "QLatin1String( ";
1209 
1210  if (cfg.globalEnums)
1211  out << enumName(e->param()) << "ToString[i]";
1212  else
1213  out << enumName(e->param()) << "::enumToString[i]";
1214 
1215  out << " )";
1216  }
1217  else
1218  {
1219  out << "i";
1220  }
1221  out << " )";
1222  }
1223  else
1224  {
1225  out << n << "\" )";
1226  }
1227  out << " ))" << (!e->signalList().empty() ? " {" : "") << endl;
1228  out << " " << This << varPath(n, cfg);
1229  if (!e->param().isEmpty())
1230  out << "[i]";
1231  out << " = v;" << endl;
1232 
1233  if ( !e->signalList().empty() ) {
1234  foreach(const Signal &signal, e->signalList()) {
1235  out << " " << This << varPath("settingsChanged", cfg) << " |= " << signalEnumName(signal.name) << ";" << endl;
1236  }
1237  out << "}" << endl;
1238  }
1239 
1240  return result;
1241 }
1242 
1243 // returns the member get default implementation
1244 // which should go in the h file if inline
1245 // or the cpp file if not inline
1246 QString memberGetDefaultBody( CfgEntry *e )
1247 {
1248  QString result = e->code();
1249  QTextStream out(&result, QIODevice::WriteOnly);
1250  out << endl;
1251 
1252  if (!e->param().isEmpty()) {
1253  out << " switch (i) {" << endl;
1254  for (int i = 0; i <= e->paramMax(); ++i) {
1255  if (!e->paramDefaultValue(i).isEmpty()) {
1256  out << " case " << i << ": return " << e->paramDefaultValue(i) << ';' << endl;
1257  }
1258  }
1259  out << " default:" << endl;
1260  out << " return " << e->defaultValue().replace("$("+e->param()+')', "i") << ';' << endl;
1261  out << " }" << endl;
1262  } else {
1263  out << " return " << e->defaultValue() << ';';
1264  }
1265 
1266  return result;
1267 }
1268 
1269 // returns the item accesor implementation
1270 // which should go in the h file if inline
1271 // or the cpp file if not inline
1272 QString itemAccessorBody( CfgEntry *e, const CfgConfig &cfg )
1273 {
1274  QString result;
1275  QTextStream out(&result, QIODevice::WriteOnly);
1276 
1277  out << "return " << itemPath(e, cfg);
1278  if (!e->param().isEmpty()) out << "[i]";
1279  out << ";" << endl;
1280 
1281  return result;
1282 }
1283 
1284 //indents text adding X spaces per line
1285 QString indent(QString text, int spaces)
1286 {
1287  QString result;
1288  QTextStream out(&result, QIODevice::WriteOnly);
1289  QTextStream in(&text, QIODevice::ReadOnly);
1290  QString currLine;
1291  while ( !in.atEnd() )
1292  {
1293  currLine = in.readLine();
1294  if (!currLine.isEmpty())
1295  for (int i=0; i < spaces; i++)
1296  out << " ";
1297  out << currLine << endl;
1298  }
1299  return result;
1300 }
1301 
1302 // adds as many 'namespace foo {' lines to p_out as
1303 // there are namespaces in p_ns
1304 void beginNamespaces(const QString &p_ns, QTextStream &p_out)
1305 {
1306  if ( !p_ns.isEmpty() ) {
1307  const QStringList nameSpaces = p_ns.split( "::" );
1308  foreach (const QString &ns, nameSpaces )
1309  p_out << "namespace " << ns << " {" << endl;
1310  p_out << endl;
1311  }
1312 }
1313 
1314 // adds as many '}' lines to p_out as
1315 // there are namespaces in p_ns
1316 void endNamespaces(const QString &p_ns, QTextStream &p_out)
1317 {
1318  if ( !p_ns.isEmpty() ) {
1319  const int namespaceCount = p_ns.count( "::" ) + 1;
1320  for ( int i = 0; i < namespaceCount; ++i )
1321  p_out << "}" << endl;
1322  p_out << endl;
1323  }
1324 }
1325 
1326 
1327 int main( int argc, char **argv )
1328 {
1329  QCoreApplication app(argc, argv);
1330 
1331  validNameRegexp = new QRegExp("[a-zA-Z_][a-zA-Z0-9_]*");
1332 
1333  QString directoryName, inputFilename, codegenFilename;
1334  parseArgs(app.arguments(), directoryName, inputFilename, codegenFilename);
1335 
1336  QString baseDir = directoryName;
1337 #ifdef Q_OS_WIN
1338  if (!baseDir.endsWith('/') && !baseDir.endsWith('\\'))
1339 #else
1340  if (!baseDir.endsWith('/'))
1341 #endif
1342  baseDir.append("/");
1343 
1344  if (!codegenFilename.endsWith(QLatin1String(".kcfgc")))
1345  {
1346  cerr << "Codegen options file must have extension .kcfgc" << endl;
1347  return 1;
1348  }
1349  QString baseName = QFileInfo(codegenFilename).fileName();
1350  baseName = baseName.left(baseName.length() - 6);
1351 
1352  CfgConfig cfg = CfgConfig( codegenFilename );
1353 
1354  QFile input( inputFilename );
1355 
1356  QDomDocument doc;
1357  QString errorMsg;
1358  int errorRow;
1359  int errorCol;
1360  if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
1361  cerr << "Unable to load document." << endl;
1362  cerr << "Parse error in " << inputFilename << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl;
1363  return 1;
1364  }
1365 
1366  QDomElement cfgElement = doc.documentElement();
1367 
1368  if ( cfgElement.isNull() ) {
1369  cerr << "No document in kcfg file" << endl;
1370  return 1;
1371  }
1372 
1373  QString cfgFileName;
1374  bool cfgFileNameArg = false;
1375  QList<Param> parameters;
1376  QList<Signal> signalList;
1377  QStringList includes;
1378  bool hasSignals = false;
1379 
1380  QList<CfgEntry*> entries;
1381 
1382  for ( QDomElement e = cfgElement.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
1383  QString tag = e.tagName();
1384 
1385  if ( tag == "include" ) {
1386  QString includeFile = e.text();
1387  if (!includeFile.isEmpty())
1388  includes.append(includeFile);
1389 
1390  } else if ( tag == "kcfgfile" ) {
1391  cfgFileName = e.attribute( "name" );
1392  cfgFileNameArg = e.attribute( "arg" ).toLower() == "true";
1393  for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
1394  if ( e2.tagName() == "parameter" ) {
1395  Param p;
1396  p.name = e2.attribute( "name" );
1397  p.type = e2.attribute( "type" );
1398  if (p.type.isEmpty())
1399  p.type = "String";
1400  parameters.append( p );
1401  }
1402  }
1403 
1404  } else if ( tag == "group" ) {
1405  QString group = e.attribute( "name" );
1406  if ( group.isEmpty() ) {
1407  cerr << "Group without name" << endl;
1408  return 1;
1409  }
1410  for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
1411  if ( e2.tagName() != "entry" ) continue;
1412  CfgEntry *entry = parseEntry( group, e2, cfg );
1413  if ( entry ) entries.append( entry );
1414  else {
1415  cerr << "Can not parse entry." << endl;
1416  return 1;
1417  }
1418  }
1419  }
1420  else if ( tag == "signal" ) {
1421  QString signalName = e.attribute( "name" );
1422  if ( signalName.isEmpty() ) {
1423  cerr << "Signal without name." << endl;
1424  return 1;
1425  }
1426  Signal theSignal;
1427  theSignal.name = signalName;
1428 
1429  for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
1430  if ( e2.tagName() == "argument") {
1431  SignalArguments argument;
1432  argument.type = e2.attribute("type");
1433  if ( argument.type.isEmpty() ) {
1434  cerr << "Signal argument without type." << endl;
1435  return 1;
1436  }
1437  argument.variableName = e2.text();
1438  theSignal.arguments.append(argument);
1439  }
1440  else if( e2.tagName() == "label") {
1441  theSignal.label = e2.text();
1442  }
1443  }
1444  signalList.append(theSignal);
1445  }
1446  }
1447 
1448  if ( cfg.className.isEmpty() ) {
1449  cerr << "Class name missing" << endl;
1450  return 1;
1451  }
1452 
1453  if ( cfg.singleton && !parameters.isEmpty() ) {
1454  cerr << "Singleton class can not have parameters" << endl;
1455  return 1;
1456  }
1457 
1458  if ( !cfgFileName.isEmpty() && cfgFileNameArg)
1459  {
1460  cerr << "Having both a fixed filename and a filename as argument is not possible." << endl;
1461  return 1;
1462  }
1463 
1464  if ( entries.isEmpty() ) {
1465  cerr << "No entries." << endl;
1466  }
1467 
1468 #if 0
1469  CfgEntry *cfg;
1470  for( cfg = entries.first(); cfg; cfg = entries.next() ) {
1471  cfg->dump();
1472  }
1473 #endif
1474 
1475  hasSignals = !signalList.empty();
1476  QString headerFileName = baseName + ".h";
1477  QString implementationFileName = baseName + ".cpp";
1478  QString mocFileName = baseName + ".moc";
1479  QString cppPreamble; // code to be inserted at the beginnin of the cpp file, e.g. initialization of static values
1480 
1481  QFile header( baseDir + headerFileName );
1482  if ( !header.open( QIODevice::WriteOnly ) ) {
1483  cerr << "Can not open '" << baseDir << headerFileName << "for writing." << endl;
1484  return 1;
1485  }
1486 
1487  QTextStream h( &header );
1488 
1489  h << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
1490  h << "// All changes you do to this file will be lost." << endl;
1491 
1492  h << "#ifndef " << ( !cfg.nameSpace.isEmpty() ? QString (QString(cfg.nameSpace).replace( "::", "_" ).toUpper() + '_') : "" )
1493  << cfg.className.toUpper() << "_H" << endl;
1494  h << "#define " << ( !cfg.nameSpace.isEmpty() ? QString (QString(cfg.nameSpace).replace( "::", "_" ).toUpper() + '_') : "" )
1495  << cfg.className.toUpper() << "_H" << endl << endl;
1496 
1497  // Includes
1498  QStringList::ConstIterator it;
1499  for( it = cfg.headerIncludes.constBegin(); it != cfg.headerIncludes.constEnd(); ++it ) {
1500  if ( (*it).startsWith('"') )
1501  h << "#include " << *it << endl;
1502  else
1503  h << "#include <" << *it << ">" << endl;
1504  }
1505 
1506  if ( cfg.headerIncludes.count() > 0 ) h << endl;
1507 
1508  if ( !cfg.singleton && parameters.isEmpty() )
1509  h << "#include <kglobal.h>" << endl;
1510 
1511  if ( cfg.inherits=="KCoreConfigSkeleton" ) {
1512  h << "#include <kcoreconfigskeleton.h>" << endl;
1513  } else {
1514  h << "#include <kconfigskeleton.h>" << endl;
1515  }
1516 
1517  h << "#include <kdebug.h>" << endl << endl;
1518 
1519  // Includes
1520  for( it = includes.constBegin(); it != includes.constEnd(); ++it ) {
1521  if ( (*it).startsWith('"') )
1522  h << "#include " << *it << endl;
1523  else
1524  h << "#include <" << *it << ">" << endl;
1525  }
1526 
1527  beginNamespaces(cfg.nameSpace, h);
1528 
1529  // Private class declaration
1530  if ( cfg.dpointer )
1531  h << "class " << cfg.className << "Private;" << endl << endl;
1532 
1533  // Class declaration header
1534  h << "class " << cfg.visibility << cfg.className << " : public " << cfg.inherits << endl;
1535 
1536  h << "{" << endl;
1537  // Add Q_OBJECT macro if the config need signals.
1538  if( hasSignals )
1539  h << " Q_OBJECT" << endl;
1540  h << " public:" << endl;
1541 
1542  // enums
1543  QList<CfgEntry*>::ConstIterator itEntry;
1544  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1545  const CfgEntry::Choices &choices = (*itEntry)->choices();
1546  const QList<CfgEntry::Choice> chlist = choices.choices;
1547  if ( !chlist.isEmpty() ) {
1548  QStringList values;
1549  QList<CfgEntry::Choice>::ConstIterator itChoice;
1550  for( itChoice = chlist.constBegin(); itChoice != chlist.constEnd(); ++itChoice ) {
1551  values.append( choices.prefix + (*itChoice).name );
1552  }
1553  if ( choices.name().isEmpty() ) {
1554  if ( cfg.globalEnums ) {
1555  h << " enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << " { " << values.join( ", " ) << " };" << endl;
1556  } else {
1557  // Create an automatically named enum
1558  h << " class " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << endl;
1559  h << " {" << endl;
1560  h << " public:" << endl;
1561  h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl;
1562  h << " };" << endl;
1563  }
1564  } else if ( !choices.external() ) {
1565  // Create a named enum
1566  h << " enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << " { " << values.join( ", " ) << " };" << endl;
1567  }
1568  }
1569  const QStringList values = (*itEntry)->paramValues();
1570  if ( !values.isEmpty() ) {
1571  if ( cfg.globalEnums ) {
1572  // ### FIXME!!
1573  // make the following string table an index-based string search!
1574  // ###
1575  h << " enum " << enumName( (*itEntry)->param() ) << " { " << values.join( ", " ) << " };" << endl;
1576  h << " static const char* const " << enumName( (*itEntry)->param() ) << "ToString[];" << endl;
1577  cppPreamble += "const char* const " + cfg.className + "::" + enumName( (*itEntry)->param() ) +
1578  "ToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
1579  } else {
1580  h << " class " << enumName( (*itEntry)->param() ) << endl;
1581  h << " {" << endl;
1582  h << " public:" << endl;
1583  h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl;
1584  h << " static const char* const enumToString[];" << endl;
1585  h << " };" << endl;
1586  cppPreamble += "const char* const " + cfg.className + "::" + enumName( (*itEntry)->param() ) +
1587  "::enumToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
1588  }
1589  }
1590  }
1591  if ( hasSignals ) {
1592  h << "\n enum {" << endl;
1593  unsigned val = 1;
1594  QList<Signal>::ConstIterator it, itEnd = signalList.constEnd();
1595  for ( it = signalList.constBegin(); it != itEnd; val <<= 1) {
1596  if ( !val ) {
1597  cerr << "Too many signals to create unique bit masks" << endl;
1598  exit(1);
1599  }
1600  Signal signal = *it;
1601  h << " " << signalEnumName(signal.name) << " = 0x" << hex << val;
1602  if ( ++it != itEnd )
1603  h << ",";
1604  h << endl;
1605  }
1606  h << " };" << dec << endl;
1607  }
1608  h << endl;
1609  // Constructor or singleton accessor
1610  if ( !cfg.singleton ) {
1611  h << " " << cfg.className << "(";
1612  if (cfgFileNameArg)
1613  {
1614  if(cfg.forceStringFilename)
1615  h << " const QString &cfgfilename"
1616  << (parameters.isEmpty() ? " = QString()" : ", ");
1617  else
1618  h << " KSharedConfig::Ptr config"
1619  << (parameters.isEmpty() ? " = KGlobal::config()" : ", ");
1620  }
1621  for (QList<Param>::ConstIterator it = parameters.constBegin();
1622  it != parameters.constEnd(); ++it)
1623  {
1624  if (it != parameters.constBegin())
1625  h << ",";
1626  h << " " << param((*it).type) << " " << (*it).name;
1627  }
1628  h << " );" << endl;
1629  } else {
1630  h << " static " << cfg.className << " *self();" << endl;
1631  if (cfgFileNameArg)
1632  {
1633  h << " static void instance(const QString& cfgfilename);" << endl;
1634  }
1635  }
1636 
1637  // Destructor
1638  h << " ~" << cfg.className << "();" << endl << endl;
1639 
1640  // global variables
1641  if (cfg.staticAccessors)
1642  This = "self()->";
1643  else
1644  Const = " const";
1645 
1646  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1647  QString n = (*itEntry)->name();
1648  QString t = (*itEntry)->type();
1649 
1650  // Manipulator
1651  if (cfg.allMutators || cfg.mutators.contains(n))
1652  {
1653  h << " /**" << endl;
1654  h << " Set " << (*itEntry)->label() << endl;
1655  h << " */" << endl;
1656  if (cfg.staticAccessors)
1657  h << " static" << endl;
1658  h << " void " << setFunction(n) << "( ";
1659  if (!(*itEntry)->param().isEmpty())
1660  h << cppType((*itEntry)->paramType()) << " i, ";
1661  if (cfg.useEnumTypes && t == "Enum")
1662  h << enumType(*itEntry, cfg.globalEnums);
1663  else
1664  h << param( t );
1665  h << " v )";
1666  // function body inline only if not using dpointer
1667  // for BC mode
1668  if ( !cfg.dpointer )
1669  {
1670  h << endl << " {" << endl;
1671  h << indent(memberMutatorBody(*itEntry, cfg), 6 );
1672  h << " }" << endl;
1673  }
1674  else
1675  {
1676  h << ";" << endl;
1677  }
1678  }
1679  h << endl;
1680  // Accessor
1681  h << " /**" << endl;
1682  h << " Get " << (*itEntry)->label() << endl;
1683  h << " */" << endl;
1684  if (cfg.staticAccessors)
1685  h << " static" << endl;
1686  h << " ";
1687  if (cfg.useEnumTypes && t == "Enum")
1688  h << enumType(*itEntry, cfg.globalEnums);
1689  else
1690  h << cppType(t);
1691  h << " " << getFunction(n) << "(";
1692  if (!(*itEntry)->param().isEmpty())
1693  h << " " << cppType((*itEntry)->paramType()) <<" i ";
1694  h << ")" << Const;
1695  // function body inline only if not using dpointer
1696  // for BC mode
1697  if ( !cfg.dpointer )
1698  {
1699  h << endl << " {" << endl;
1700  h << indent(memberAccessorBody(*itEntry, cfg.globalEnums, cfg), 6 );
1701  h << " }" << endl;
1702  }
1703  else
1704  {
1705  h << ";" << endl;
1706  }
1707 
1708  // Default value Accessor
1709  if ((cfg.allDefaultGetters || cfg.defaultGetters.contains(n)) && !(*itEntry)->defaultValue().isEmpty()) {
1710  h << endl;
1711  h << " /**" << endl;
1712  h << " Get " << (*itEntry)->label() << " default value" << endl;
1713  h << " */" << endl;
1714  if (cfg.staticAccessors)
1715  h << " static" << endl;
1716  h << " ";
1717  if (cfg.useEnumTypes && t == "Enum")
1718  h << enumType(*itEntry, cfg.globalEnums);
1719  else
1720  h << cppType(t);
1721  h << " " << getDefaultFunction(n) << "(";
1722  if ( !(*itEntry)->param().isEmpty() )
1723  h << " " << cppType( (*itEntry)->paramType() ) <<" i ";
1724  h << ")" << Const << endl;
1725  h << " {" << endl;
1726  h << " return ";
1727  if (cfg.useEnumTypes && t == "Enum")
1728  h << "static_cast<" << enumType(*itEntry, cfg.globalEnums) << ">(";
1729  h << getDefaultFunction(n) << "_helper(";
1730  if ( !(*itEntry)->param().isEmpty() )
1731  h << " i ";
1732  h << ")";
1733  if (cfg.useEnumTypes && t == "Enum")
1734  h << ")";
1735  h << ";" << endl;
1736  h << " }" << endl;
1737  }
1738 
1739  // Item accessor
1740  if ( cfg.itemAccessors ) {
1741  h << endl;
1742  h << " /**" << endl;
1743  h << " Get Item object corresponding to " << n << "()"
1744  << endl;
1745  h << " */" << endl;
1746  h << " Item" << itemType( (*itEntry)->type() ) << " *"
1747  << getFunction( n ) << "Item(";
1748  if (!(*itEntry)->param().isEmpty()) {
1749  h << " " << cppType((*itEntry)->paramType()) << " i ";
1750  }
1751  h << ")";
1752  if ( !cfg.dpointer )
1753  {
1754  h << endl << " {" << endl;
1755  h << indent( itemAccessorBody((*itEntry), cfg), 6);
1756  h << " }" << endl;
1757  }
1758  else
1759  {
1760  h << ";" << endl;
1761  }
1762  }
1763 
1764  h << endl;
1765  }
1766 
1767 
1768  // Signal definition.
1769  if( hasSignals ) {
1770  h << endl;
1771  h << " Q_SIGNALS:";
1772  foreach(const Signal &signal, signalList) {
1773  h << endl;
1774  if ( !signal.label.isEmpty() ) {
1775  h << " /**" << endl;
1776  h << " " << signal.label << endl;
1777  h << " */" << endl;
1778  }
1779  h << " void " << signal.name << "(";
1780  QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
1781  for ( it = signal.arguments.constBegin(); it != itEnd; ) {
1782  SignalArguments argument = *it;
1783  QString type = param(argument.type);
1784  if ( cfg.useEnumTypes && argument.type == "Enum" ) {
1785  for ( int i = 0, end = entries.count(); i < end; ++i ) {
1786  if ( entries[i]->name() == argument.variableName ) {
1787  type = enumType(entries[i], cfg.globalEnums);
1788  break;
1789  }
1790  }
1791  }
1792  h << type << " " << argument.variableName;
1793  if ( ++it != itEnd ) {
1794  h << ", ";
1795  }
1796  }
1797  h << ");" << endl;
1798  }
1799  h << endl;
1800  }
1801 
1802  h << " protected:" << endl;
1803 
1804  // Private constructor for singleton
1805  if ( cfg.singleton ) {
1806  h << " " << cfg.className << "(";
1807  if ( cfgFileNameArg )
1808  h << "const QString& arg";
1809  h << ");" << endl;
1810  h << " friend class " << cfg.className << "Helper;" << endl << endl;
1811  }
1812 
1813  if ( hasSignals ) {
1814  h << " virtual void usrWriteConfig();" << endl;
1815  }
1816 
1817  // Member variables
1818  if ( !cfg.memberVariables.isEmpty() && cfg.memberVariables != "private" && cfg.memberVariables != "dpointer") {
1819  h << " " << cfg.memberVariables << ":" << endl;
1820  }
1821 
1822  // Class Parameters
1823  for (QList<Param>::ConstIterator it = parameters.constBegin();
1824  it != parameters.constEnd(); ++it)
1825  {
1826  h << " " << cppType((*it).type) << " mParam" << (*it).name << ";" << endl;
1827  }
1828 
1829  if ( cfg.memberVariables != "dpointer" )
1830  {
1831  QString group;
1832  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1833  if ( (*itEntry)->group() != group ) {
1834  group = (*itEntry)->group();
1835  h << endl;
1836  h << " // " << group << endl;
1837  }
1838  h << " " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name(), cfg );
1839  if ( !(*itEntry)->param().isEmpty() )
1840  {
1841  h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
1842  }
1843  h << ";" << endl;
1844 
1845  if ( cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name()) )
1846  {
1847  h << " ";
1848  if (cfg.staticAccessors)
1849  h << "static ";
1850  h << cppType((*itEntry)->type()) << " " << getDefaultFunction((*itEntry)->name()) << "_helper(";
1851  if ( !(*itEntry)->param().isEmpty() )
1852  h << " " << cppType( (*itEntry)->paramType() ) <<" i ";
1853  h << ")" << Const << ";" << endl;
1854  }
1855  }
1856 
1857  h << endl << " private:" << endl;
1858  if ( cfg.itemAccessors ) {
1859  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1860  h << " Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry, cfg );
1861  if ( !(*itEntry)->param().isEmpty() ) h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
1862  h << ";" << endl;
1863  }
1864  }
1865  if ( hasSignals )
1866  h << " uint " << varName("settingsChanged", cfg) << ";" << endl;
1867 
1868  }
1869  else
1870  {
1871  // use a private class for both member variables and items
1872  h << " private:" << endl;
1873  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1874  if ( cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name()) ) {
1875  h << " ";
1876  if (cfg.staticAccessors)
1877  h << "static ";
1878  h << cppType((*itEntry)->type()) << " " << getDefaultFunction((*itEntry)->name()) << "_helper(";
1879  if ( !(*itEntry)->param().isEmpty() )
1880  h << " " << cppType( (*itEntry)->paramType() ) <<" i ";
1881  h << ")" << Const << ";" << endl;
1882  }
1883  }
1884  h << " " + cfg.className + "Private *d;" << endl;
1885  }
1886 
1887  if (cfg.customAddons)
1888  {
1889  h << " // Include custom additions" << endl;
1890  h << " #include \"" << filenameOnly(baseName) << "_addons.h\"" <<endl;
1891  }
1892 
1893  h << "};" << endl << endl;
1894 
1895  endNamespaces(cfg.nameSpace, h);
1896 
1897  h << "#endif" << endl << endl;
1898 
1899 
1900  header.close();
1901 
1902  QFile implementation( baseDir + implementationFileName );
1903  if ( !implementation.open( QIODevice::WriteOnly ) ) {
1904  cerr << "Can not open '" << implementationFileName << "for writing."
1905  << endl;
1906  return 1;
1907  }
1908 
1909  QTextStream cpp( &implementation );
1910 
1911 
1912  cpp << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
1913  cpp << "// All changes you do to this file will be lost." << endl << endl;
1914 
1915  cpp << "#include \"" << headerFileName << "\"" << endl << endl;
1916 
1917  for( it = cfg.sourceIncludes.constBegin(); it != cfg.sourceIncludes.constEnd(); ++it ) {
1918  if ( (*it).startsWith('"') )
1919  cpp << "#include " << *it << endl;
1920  else
1921  cpp << "#include <" << *it << ">" << endl;
1922  }
1923 
1924  if ( cfg.sourceIncludes.count() > 0 ) cpp << endl;
1925 
1926  if ( cfg.setUserTexts ) cpp << "#include <klocale.h>" << endl << endl;
1927 
1928  // Header required by singleton implementation
1929  if ( cfg.singleton )
1930  cpp << "#include <kglobal.h>" << endl << "#include <QtCore/QFile>" << endl << endl;
1931  if ( cfg.singleton && cfgFileNameArg )
1932  cpp << "#include <kdebug.h>" << endl << endl;
1933 
1934  if ( !cfg.nameSpace.isEmpty() )
1935  cpp << "using namespace " << cfg.nameSpace << ";" << endl << endl;
1936 
1937  QString group;
1938 
1939  // private class implementation
1940  if ( cfg.dpointer )
1941  {
1942  beginNamespaces(cfg.nameSpace, cpp);
1943  cpp << "class " << cfg.className << "Private" << endl;
1944  cpp << "{" << endl;
1945  cpp << " public:" << endl;
1946  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1947  if ( (*itEntry)->group() != group ) {
1948  group = (*itEntry)->group();
1949  cpp << endl;
1950  cpp << " // " << group << endl;
1951  }
1952  cpp << " " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name(), cfg );
1953  if ( !(*itEntry)->param().isEmpty() )
1954  {
1955  cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
1956  }
1957  cpp << ";" << endl;
1958  }
1959  cpp << endl << " // items" << endl;
1960  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1961  cpp << " "+cfg.inherits+"::Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry, cfg );
1962  if ( !(*itEntry)->param().isEmpty() ) cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
1963  cpp << ";" << endl;
1964  }
1965  if ( hasSignals ) {
1966  cpp << " uint " << varName("settingsChanged", cfg) << ";" << endl;
1967  }
1968 
1969  cpp << "};" << endl << endl;
1970  endNamespaces(cfg.nameSpace, cpp);
1971  }
1972 
1973  // Singleton implementation
1974  if ( cfg.singleton ) {
1975  beginNamespaces(cfg.nameSpace, cpp);
1976  cpp << "class " << cfg.className << "Helper" << endl;
1977  cpp << '{' << endl;
1978  cpp << " public:" << endl;
1979  cpp << " " << cfg.className << "Helper() : q(0) {}" << endl;
1980  cpp << " ~" << cfg.className << "Helper() { delete q; }" << endl;
1981  cpp << " " << cfg.className << " *q;" << endl;
1982  cpp << "};" << endl;
1983  endNamespaces(cfg.nameSpace, cpp);
1984  cpp << "K_GLOBAL_STATIC(" << cfg.className << "Helper, s_global" << cfg.className << ")" << endl;
1985 
1986  cpp << cfg.className << " *" << cfg.className << "::self()" << endl;
1987  cpp << "{" << endl;
1988  if ( cfgFileNameArg ) {
1989  cpp << " if (!s_global" << cfg.className << "->q)" << endl;
1990  cpp << " kFatal() << \"you need to call " << cfg.className << "::instance before using\";" << endl;
1991  } else {
1992  cpp << " if (!s_global" << cfg.className << "->q) {" << endl;
1993  cpp << " new " << cfg.className << ';' << endl;
1994  cpp << " s_global" << cfg.className << "->q->readConfig();" << endl;
1995  cpp << " }" << endl << endl;
1996  }
1997  cpp << " return s_global" << cfg.className << "->q;" << endl;
1998  cpp << "}" << endl << endl;
1999 
2000  if ( cfgFileNameArg ) {
2001  cpp << "void " << cfg.className << "::instance(const QString& cfgfilename)" << endl;
2002  cpp << "{" << endl;
2003  cpp << " if (s_global" << cfg.className << "->q) {" << endl;
2004  cpp << " kDebug() << \"" << cfg.className << "::instance called after the first use - ignoring\";" << endl;
2005  cpp << " return;" << endl;
2006  cpp << " }" << endl;
2007  cpp << " new " << cfg.className << "(cfgfilename);" << endl;
2008  cpp << " s_global" << cfg.className << "->q->readConfig();" << endl;
2009  cpp << "}" << endl << endl;
2010  }
2011  }
2012 
2013  if ( !cppPreamble.isEmpty() )
2014  cpp << cppPreamble << endl;
2015 
2016  // Constructor
2017  cpp << cfg.className << "::" << cfg.className << "( ";
2018  if ( cfgFileNameArg ) {
2019  if ( !cfg.singleton && ! cfg.forceStringFilename)
2020  cpp << " KSharedConfig::Ptr config";
2021  else
2022  cpp << " const QString& config";
2023  cpp << (parameters.isEmpty() ? " " : ", ");
2024  }
2025 
2026  for (QList<Param>::ConstIterator it = parameters.constBegin();
2027  it != parameters.constEnd(); ++it)
2028  {
2029  if (it != parameters.constBegin())
2030  cpp << ",";
2031  cpp << " " << param((*it).type) << " " << (*it).name;
2032  }
2033  cpp << " )" << endl;
2034 
2035  cpp << " : " << cfg.inherits << "(";
2036  if ( !cfgFileName.isEmpty() ) cpp << " QLatin1String( \"" << cfgFileName << "\" ";
2037  if ( cfgFileNameArg ) cpp << " config ";
2038  if ( !cfgFileName.isEmpty() ) cpp << ") ";
2039  cpp << ")" << endl;
2040 
2041  // Store parameters
2042  for (QList<Param>::ConstIterator it = parameters.constBegin();
2043  it != parameters.constEnd(); ++it)
2044  {
2045  cpp << " , mParam" << (*it).name << "(" << (*it).name << ")" << endl;
2046  }
2047 
2048  if ( hasSignals && !cfg.dpointer )
2049  cpp << " , " << varName("settingsChanged", cfg) << "(0)" << endl;
2050 
2051  cpp << "{" << endl;
2052 
2053  if (cfg.dpointer)
2054  {
2055  cpp << " d = new " + cfg.className + "Private;" << endl;
2056  if (hasSignals)
2057  cpp << " " << varPath("settingsChanged", cfg) << " = 0;" << endl;
2058  }
2059  // Needed in case the singleton class is used as baseclass for
2060  // another singleton.
2061  if (cfg.singleton) {
2062  cpp << " Q_ASSERT(!s_global" << cfg.className << "->q);" << endl;
2063  cpp << " s_global" << cfg.className << "->q = this;" << endl;
2064  }
2065 
2066  group.clear();
2067 
2068  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
2069  if ( (*itEntry)->group() != group ) {
2070  if ( !group.isEmpty() ) cpp << endl;
2071  group = (*itEntry)->group();
2072  cpp << " setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl;
2073  }
2074 
2075  QString key = paramString( (*itEntry)->key(), parameters );
2076  if ( !(*itEntry)->code().isEmpty() ) {
2077  cpp << (*itEntry)->code() << endl;
2078  }
2079  if ( (*itEntry)->type() == "Enum" ) {
2080  cpp << " QList<"+cfg.inherits+"::ItemEnum::Choice2> values"
2081  << (*itEntry)->name() << ";" << endl;
2082  const QList<CfgEntry::Choice> choices = (*itEntry)->choices().choices;
2083  QList<CfgEntry::Choice>::ConstIterator it;
2084  for( it = choices.constBegin(); it != choices.constEnd(); ++it ) {
2085  cpp << " {" << endl;
2086  cpp << " "+cfg.inherits+"::ItemEnum::Choice2 choice;" << endl;
2087  cpp << " choice.name = QLatin1String(\"" << (*it).name << "\");" << endl;
2088  if ( cfg.setUserTexts ) {
2089  if ( !(*it).label.isEmpty() ) {
2090  cpp << " choice.label = ";
2091  if ( !(*it).context.isEmpty() )
2092  cpp << "i18nc(" + quoteString((*it).context) + ", ";
2093  else
2094  cpp << "i18n(";
2095  cpp << quoteString((*it).label) << ");" << endl;
2096  }
2097  if ( !(*it).toolTip.isEmpty() ) {
2098  cpp << " choice.toolTip = ";
2099  if ( !(*it).context.isEmpty() )
2100  cpp << "i18nc(" + quoteString((*it).context) + ", ";
2101  else
2102  cpp << "i18n(";
2103  cpp << quoteString((*it).toolTip) << ");" << endl;
2104  }
2105  if ( !(*it).whatsThis.isEmpty() ) {
2106  cpp << " choice.whatsThis = ";
2107  if ( !(*it).context.isEmpty() )
2108  cpp << "i18nc(" + quoteString((*it).context) + ", ";
2109  else
2110  cpp << "i18n(";
2111  cpp << quoteString((*it).whatsThis) << ");" << endl;
2112  }
2113  }
2114  cpp << " values" << (*itEntry)->name() << ".append( choice );" << endl;
2115  cpp << " }" << endl;
2116  }
2117  }
2118 
2119  if (!cfg.dpointer)
2120  cpp << itemDeclaration( *itEntry, cfg );
2121 
2122  if ( (*itEntry)->param().isEmpty() )
2123  {
2124  // Normal case
2125  cpp << " " << itemPath( *itEntry, cfg ) << " = "
2126  << newItem( (*itEntry)->type(), (*itEntry)->name(), key, (*itEntry)->defaultValue(), cfg ) << endl;
2127 
2128  if ( !(*itEntry)->minValue().isEmpty() )
2129  cpp << " " << itemPath( *itEntry, cfg ) << "->setMinValue(" << (*itEntry)->minValue() << ");" << endl;
2130  if ( !(*itEntry)->maxValue().isEmpty() )
2131  cpp << " " << itemPath( *itEntry, cfg ) << "->setMaxValue(" << (*itEntry)->maxValue() << ");" << endl;
2132 
2133  if ( cfg.setUserTexts )
2134  cpp << userTextsFunctions( (*itEntry), cfg );
2135 
2136  cpp << " addItem( " << itemPath( *itEntry, cfg );
2137  QString quotedName = (*itEntry)->name();
2138  addQuotes( quotedName );
2139  if ( quotedName != key ) cpp << ", QLatin1String( \"" << (*itEntry)->name() << "\" )";
2140  cpp << " );" << endl;
2141  }
2142  else
2143  {
2144  // Indexed
2145  for(int i = 0; i <= (*itEntry)->paramMax(); i++)
2146  {
2147  QString defaultStr;
2148  QString itemVarStr(itemPath( *itEntry, cfg )+QString("[%1]").arg(i));
2149 
2150  if ( !(*itEntry)->paramDefaultValue(i).isEmpty() )
2151  defaultStr = (*itEntry)->paramDefaultValue(i);
2152  else if ( !(*itEntry)->defaultValue().isEmpty() )
2153  defaultStr = paramString( (*itEntry)->defaultValue(), (*itEntry), i );
2154  else
2155  defaultStr = defaultValue( (*itEntry)->type() );
2156 
2157  cpp << " " << itemVarStr << " = "
2158  << newItem( (*itEntry)->type(), (*itEntry)->name(), paramString(key, *itEntry, i), defaultStr,cfg, QString("[%1]").arg(i) )
2159  << endl;
2160 
2161  if ( cfg.setUserTexts )
2162  cpp << userTextsFunctions( *itEntry, cfg, itemVarStr, (*itEntry)->paramName() );
2163 
2164  // Make mutators for enum parameters work by adding them with $(..) replaced by the
2165  // param name. The check for isImmutable in the set* functions doesn't have the param
2166  // name available, just the corresponding enum value (int), so we need to store the
2167  // param names in a separate static list!.
2168  cpp << " addItem( " << itemVarStr << ", QLatin1String( \"";
2169  if ( (*itEntry)->paramType()=="Enum" )
2170  cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg((*itEntry)->paramValues()[i] );
2171  else
2172  cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg(i);
2173  cpp << "\" ) );" << endl;
2174  }
2175  }
2176  }
2177 
2178  cpp << "}" << endl << endl;
2179 
2180  if (cfg.dpointer)
2181  {
2182  // setters and getters go in Cpp if in dpointer mode
2183  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
2184  QString n = (*itEntry)->name();
2185  QString t = (*itEntry)->type();
2186 
2187  // Manipulator
2188  if (cfg.allMutators || cfg.mutators.contains(n))
2189  {
2190  cpp << "void " << setFunction(n, cfg.className) << "( ";
2191  if ( !(*itEntry)->param().isEmpty() )
2192  cpp << cppType( (*itEntry)->paramType() ) << " i, ";
2193  if (cfg.useEnumTypes && t == "Enum")
2194  cpp << enumType(*itEntry, cfg.globalEnums);
2195  else
2196  cpp << param( t );
2197  cpp << " v )" << endl;
2198  // function body inline only if not using dpointer
2199  // for BC mode
2200  cpp << "{" << endl;
2201  cpp << indent(memberMutatorBody( *itEntry, cfg ), 6);
2202  cpp << "}" << endl << endl;
2203  }
2204 
2205  // Accessor
2206  if (cfg.useEnumTypes && t == "Enum")
2207  cpp << enumType(*itEntry, cfg.globalEnums);
2208  else
2209  cpp << cppType(t);
2210  cpp << " " << getFunction(n, cfg.className) << "(";
2211  if ( !(*itEntry)->param().isEmpty() )
2212  cpp << " " << cppType( (*itEntry)->paramType() ) <<" i ";
2213  cpp << ")" << Const << endl;
2214  // function body inline only if not using dpointer
2215  // for BC mode
2216  cpp << "{" << endl;
2217  cpp << indent(memberAccessorBody( *itEntry, cfg.globalEnums, cfg ), 2);
2218  cpp << "}" << endl << endl;
2219 
2220  // Default value Accessor -- written by the loop below
2221 
2222  // Item accessor
2223  if ( cfg.itemAccessors )
2224  {
2225  cpp << endl;
2226  cpp << cfg.inherits+"::Item" << itemType( (*itEntry)->type() ) << " *"
2227  << getFunction( n, cfg.className ) << "Item(";
2228  if ( !(*itEntry)->param().isEmpty() ) {
2229  cpp << " " << cppType( (*itEntry)->paramType() ) << " i ";
2230  }
2231  cpp << ")" << endl;
2232  cpp << "{" << endl;
2233  cpp << indent(itemAccessorBody( *itEntry, cfg ), 2);
2234  cpp << "}" << endl;
2235  }
2236 
2237  cpp << endl;
2238  }
2239  }
2240 
2241  // default value getters always go in Cpp
2242  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
2243  QString n = (*itEntry)->name();
2244  QString t = (*itEntry)->type();
2245 
2246  // Default value Accessor, as "helper" function
2247  if (( cfg.allDefaultGetters || cfg.defaultGetters.contains(n) ) && !(*itEntry)->defaultValue().isEmpty() ) {
2248  cpp << cppType(t) << " " << getDefaultFunction(n, cfg.className) << "_helper(";
2249  if ( !(*itEntry)->param().isEmpty() )
2250  cpp << " " << cppType( (*itEntry)->paramType() ) <<" i ";
2251  cpp << ")" << Const << endl;
2252  cpp << "{" << endl;
2253  cpp << memberGetDefaultBody(*itEntry) << endl;
2254  cpp << "}" << endl << endl;
2255  }
2256  }
2257 
2258  // Destructor
2259  cpp << cfg.className << "::~" << cfg.className << "()" << endl;
2260  cpp << "{" << endl;
2261  if ( cfg.singleton ) {
2262  if ( cfg.dpointer )
2263  cpp << " delete d;" << endl;
2264  cpp << " if (!s_global" << cfg.className << ".isDestroyed()) {" << endl;
2265  cpp << " s_global" << cfg.className << "->q = 0;" << endl;
2266  cpp << " }" << endl;
2267  }
2268  cpp << "}" << endl << endl;
2269 
2270  if ( hasSignals ) {
2271  cpp << "void " << cfg.className << "::" << "usrWriteConfig()" << endl;
2272  cpp << "{" << endl;
2273  cpp << " " << cfg.inherits << "::usrWriteConfig();" << endl << endl;
2274  foreach(const Signal &signal, signalList) {
2275  cpp << " if ( " << varPath("settingsChanged", cfg) << " & " << signalEnumName(signal.name) << " ) " << endl;
2276  cpp << " emit " << signal.name << "(";
2277  QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
2278  for ( it = signal.arguments.constBegin(); it != itEnd; ) {
2279  SignalArguments argument = *it;
2280  bool cast = false;
2281  if ( cfg.useEnumTypes && argument.type == "Enum" ) {
2282  for ( int i = 0, end = entries.count(); i < end; ++i ) {
2283  if ( entries[i]->name() == argument.variableName ) {
2284  cpp << "static_cast<" << enumType(entries[i], cfg.globalEnums) << ">(";
2285  cast = true;
2286  break;
2287  }
2288  }
2289  }
2290  cpp << varPath(argument.variableName, cfg);
2291  if ( cast )
2292  cpp << ")";
2293  if ( ++it != itEnd )
2294  cpp << ", ";
2295  }
2296  cpp << ");" << endl << endl;
2297  }
2298  cpp << " " << varPath("settingsChanged", cfg) << " = 0;" << endl;
2299  cpp << "}" << endl;
2300  }
2301 
2302  // Add includemoc if they are signals defined.
2303  if( hasSignals ) {
2304  cpp << endl;
2305  cpp << "#include \"" << mocFileName << "\"" << endl;
2306  cpp << endl;
2307  }
2308 
2309  // clear entries list
2310  qDeleteAll( entries );
2311 
2312  implementation.close();
2313 }
preProcessDefault
static void preProcessDefault(QString &defaultValue, const QString &name, const QString &type, const CfgEntry::Choices &choices, QString &code, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:522
Const
QString Const
Definition: kconfig_compiler.cpp:104
userTextsFunctions
QString userTextsFunctions(CfgEntry *e, const CfgConfig &cfg, QString itemVarStr=QString(), QString i=QString())
Definition: kconfig_compiler.cpp:1102
param
QString param(const QString &t)
Return parameter declaration for given type.
Definition: kconfig_compiler.cpp:887
header
const char header[]
Definition: fake/kauth-policy-gen-polkit.cpp:26
paramString
QString paramString(const QString &s, const CfgEntry *e, int i)
Definition: kconfig_compiler.cpp:1058
allNames
QStringList allNames
Definition: kconfig_compiler.cpp:101
KMacroExpander::group
Definition: kmacroexpander_unix.cpp:34
filenameOnly
static QString filenameOnly(const QString &path)
Definition: kconfig_compiler.cpp:505
memberMutatorBody
QString memberMutatorBody(CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1172
itemVar
static QString itemVar(const CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1006
validNameRegexp
QRegExp * validNameRegexp
Definition: kconfig_compiler.cpp:102
getDefaultFunction
static QString getDefaultFunction(const QString &n, const QString &className=QString())
Definition: kconfig_compiler.cpp:442
parseEntry
CfgEntry * parseEntry(const QString &group, const QDomElement &element, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:602
setFunction
static QString setFunction(const QString &n, const QString &className=QString())
Definition: kconfig_compiler.cpp:432
QString
varPath
static QString varPath(const QString &n, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:374
indent
QString indent(QString text, int spaces)
Definition: kconfig_compiler.cpp:1285
prefix
QString prefix()
Definition: kstandarddirs_win.cpp:28
endNamespaces
void endNamespaces(const QString &p_ns, QTextStream &p_out)
Definition: kconfig_compiler.cpp:1316
literalString
static QString literalString(const QString &s)
Definition: kconfig_compiler.cpp:481
isUnsigned
static bool isUnsigned(const QString &type)
Definition: kconfig_compiler.cpp:877
itemAccessorBody
QString itemAccessorBody(CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1272
QStringList
memberAccessorBody
QString memberAccessorBody(CfgEntry *e, bool globalEnums, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1148
addQuotes
static void addQuotes(QString &s)
Definition: kconfig_compiler.cpp:463
beginNamespaces
void beginNamespaces(const QString &p_ns, QTextStream &p_out)
Definition: kconfig_compiler.cpp:1304
dumpNode
static QString dumpNode(const QDomNode &node)
Definition: kconfig_compiler.cpp:493
cppType
QString cppType(const QString &t)
Actual C++ storage type for given type.
Definition: kconfig_compiler.cpp:920
This
QString This
Definition: kconfig_compiler.cpp:103
itemType
QString itemType(const QString &type)
Definition: kconfig_compiler.cpp:980
itemDeclaration
static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:990
varName
static QString varName(const QString &n, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:360
memberGetDefaultBody
QString memberGetDefaultBody(CfgEntry *e)
Definition: kconfig_compiler.cpp:1246
signalEnumName
static QString signalEnumName(const QString &signalName)
Definition: kconfig_compiler.cpp:513
itemPath
static QString itemPath(const CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1030
parseArgs
static void parseArgs(const QStringList &args, QString &directory, QString &file1, QString &file2)
Definition: kconfig_compiler.cpp:49
newItem
QString newItem(const QString &type, const QString &name, const QString &key, const QString &defaultValue, const CfgConfig &cfg, const QString &param=QString())
Definition: kconfig_compiler.cpp:1042
enumName
static QString enumName(const QString &n)
Definition: kconfig_compiler.cpp:386
main
int main(int argc, char **argv)
Definition: kconfig_compiler.cpp:1327
getFunction
static QString getFunction(const QString &n, const QString &className=QString())
Definition: kconfig_compiler.cpp:452
enumTypeQualifier
static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
Definition: kconfig_compiler.cpp:417
QList< SignalArguments >
defaultValue
QString defaultValue(const QString &t)
Definition: kconfig_compiler.cpp:950
quoteString
static QString quoteString(const QString &s)
Definition: kconfig_compiler.cpp:471
enumType
static QString enumType(const CfgEntry *e, bool globalEnums)
Definition: kconfig_compiler.cpp:404
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:47:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal