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

KDECore

  • sources
  • kde-4.14
  • 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.setCodec("utf-8");
1490  h << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
1491  h << "// All changes you do to this file will be lost." << endl;
1492 
1493  h << "#ifndef " << ( !cfg.nameSpace.isEmpty() ? QString (QString(cfg.nameSpace).replace( "::", "_" ).toUpper() + '_') : "" )
1494  << cfg.className.toUpper() << "_H" << endl;
1495  h << "#define " << ( !cfg.nameSpace.isEmpty() ? QString (QString(cfg.nameSpace).replace( "::", "_" ).toUpper() + '_') : "" )
1496  << cfg.className.toUpper() << "_H" << endl << endl;
1497 
1498  // Includes
1499  QStringList::ConstIterator it;
1500  for( it = cfg.headerIncludes.constBegin(); it != cfg.headerIncludes.constEnd(); ++it ) {
1501  if ( (*it).startsWith('"') )
1502  h << "#include " << *it << endl;
1503  else
1504  h << "#include <" << *it << ">" << endl;
1505  }
1506 
1507  if ( cfg.headerIncludes.count() > 0 ) h << endl;
1508 
1509  if ( !cfg.singleton && parameters.isEmpty() )
1510  h << "#include <kglobal.h>" << endl;
1511 
1512  if ( cfg.inherits=="KCoreConfigSkeleton" ) {
1513  h << "#include <kcoreconfigskeleton.h>" << endl;
1514  } else {
1515  h << "#include <kconfigskeleton.h>" << endl;
1516  }
1517 
1518  h << "#include <kdebug.h>" << endl << endl;
1519 
1520  // Includes
1521  for( it = includes.constBegin(); it != includes.constEnd(); ++it ) {
1522  if ( (*it).startsWith('"') )
1523  h << "#include " << *it << endl;
1524  else
1525  h << "#include <" << *it << ">" << endl;
1526  }
1527 
1528  beginNamespaces(cfg.nameSpace, h);
1529 
1530  // Private class declaration
1531  if ( cfg.dpointer )
1532  h << "class " << cfg.className << "Private;" << endl << endl;
1533 
1534  // Class declaration header
1535  h << "class " << cfg.visibility << cfg.className << " : public " << cfg.inherits << endl;
1536 
1537  h << "{" << endl;
1538  // Add Q_OBJECT macro if the config need signals.
1539  if( hasSignals )
1540  h << " Q_OBJECT" << endl;
1541  h << " public:" << endl;
1542 
1543  // enums
1544  QList<CfgEntry*>::ConstIterator itEntry;
1545  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1546  const CfgEntry::Choices &choices = (*itEntry)->choices();
1547  const QList<CfgEntry::Choice> chlist = choices.choices;
1548  if ( !chlist.isEmpty() ) {
1549  QStringList values;
1550  QList<CfgEntry::Choice>::ConstIterator itChoice;
1551  for( itChoice = chlist.constBegin(); itChoice != chlist.constEnd(); ++itChoice ) {
1552  values.append( choices.prefix + (*itChoice).name );
1553  }
1554  if ( choices.name().isEmpty() ) {
1555  if ( cfg.globalEnums ) {
1556  h << " enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << " { " << values.join( ", " ) << " };" << endl;
1557  } else {
1558  // Create an automatically named enum
1559  h << " class " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << endl;
1560  h << " {" << endl;
1561  h << " public:" << endl;
1562  h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl;
1563  h << " };" << endl;
1564  }
1565  } else if ( !choices.external() ) {
1566  // Create a named enum
1567  h << " enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << " { " << values.join( ", " ) << " };" << endl;
1568  }
1569  }
1570  const QStringList values = (*itEntry)->paramValues();
1571  if ( !values.isEmpty() ) {
1572  if ( cfg.globalEnums ) {
1573  // ### FIXME!!
1574  // make the following string table an index-based string search!
1575  // ###
1576  h << " enum " << enumName( (*itEntry)->param() ) << " { " << values.join( ", " ) << " };" << endl;
1577  h << " static const char* const " << enumName( (*itEntry)->param() ) << "ToString[];" << endl;
1578  cppPreamble += "const char* const " + cfg.className + "::" + enumName( (*itEntry)->param() ) +
1579  "ToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
1580  } else {
1581  h << " class " << enumName( (*itEntry)->param() ) << endl;
1582  h << " {" << endl;
1583  h << " public:" << endl;
1584  h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl;
1585  h << " static const char* const enumToString[];" << endl;
1586  h << " };" << endl;
1587  cppPreamble += "const char* const " + cfg.className + "::" + enumName( (*itEntry)->param() ) +
1588  "::enumToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
1589  }
1590  }
1591  }
1592  if ( hasSignals ) {
1593  h << "\n enum {" << endl;
1594  unsigned val = 1;
1595  QList<Signal>::ConstIterator it, itEnd = signalList.constEnd();
1596  for ( it = signalList.constBegin(); it != itEnd; val <<= 1) {
1597  if ( !val ) {
1598  cerr << "Too many signals to create unique bit masks" << endl;
1599  exit(1);
1600  }
1601  Signal signal = *it;
1602  h << " " << signalEnumName(signal.name) << " = 0x" << hex << val;
1603  if ( ++it != itEnd )
1604  h << ",";
1605  h << endl;
1606  }
1607  h << " };" << dec << endl;
1608  }
1609  h << endl;
1610  // Constructor or singleton accessor
1611  if ( !cfg.singleton ) {
1612  h << " " << cfg.className << "(";
1613  if (cfgFileNameArg)
1614  {
1615  if(cfg.forceStringFilename)
1616  h << " const QString &cfgfilename"
1617  << (parameters.isEmpty() ? " = QString()" : ", ");
1618  else
1619  h << " KSharedConfig::Ptr config"
1620  << (parameters.isEmpty() ? " = KGlobal::config()" : ", ");
1621  }
1622  for (QList<Param>::ConstIterator it = parameters.constBegin();
1623  it != parameters.constEnd(); ++it)
1624  {
1625  if (it != parameters.constBegin())
1626  h << ",";
1627  h << " " << param((*it).type) << " " << (*it).name;
1628  }
1629  h << " );" << endl;
1630  } else {
1631  h << " static " << cfg.className << " *self();" << endl;
1632  if (cfgFileNameArg)
1633  {
1634  h << " static void instance(const QString& cfgfilename);" << endl;
1635  }
1636  }
1637 
1638  // Destructor
1639  h << " ~" << cfg.className << "();" << endl << endl;
1640 
1641  // global variables
1642  if (cfg.staticAccessors)
1643  This = "self()->";
1644  else
1645  Const = " const";
1646 
1647  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1648  QString n = (*itEntry)->name();
1649  QString t = (*itEntry)->type();
1650 
1651  // Manipulator
1652  if (cfg.allMutators || cfg.mutators.contains(n))
1653  {
1654  h << " /**" << endl;
1655  h << " Set " << (*itEntry)->label() << endl;
1656  h << " */" << endl;
1657  if (cfg.staticAccessors)
1658  h << " static" << endl;
1659  h << " void " << setFunction(n) << "( ";
1660  if (!(*itEntry)->param().isEmpty())
1661  h << cppType((*itEntry)->paramType()) << " i, ";
1662  if (cfg.useEnumTypes && t == "Enum")
1663  h << enumType(*itEntry, cfg.globalEnums);
1664  else
1665  h << param( t );
1666  h << " v )";
1667  // function body inline only if not using dpointer
1668  // for BC mode
1669  if ( !cfg.dpointer )
1670  {
1671  h << endl << " {" << endl;
1672  h << indent(memberMutatorBody(*itEntry, cfg), 6 );
1673  h << " }" << endl;
1674  }
1675  else
1676  {
1677  h << ";" << endl;
1678  }
1679  }
1680  h << endl;
1681  // Accessor
1682  h << " /**" << endl;
1683  h << " Get " << (*itEntry)->label() << endl;
1684  h << " */" << endl;
1685  if (cfg.staticAccessors)
1686  h << " static" << endl;
1687  h << " ";
1688  if (cfg.useEnumTypes && t == "Enum")
1689  h << enumType(*itEntry, cfg.globalEnums);
1690  else
1691  h << cppType(t);
1692  h << " " << getFunction(n) << "(";
1693  if (!(*itEntry)->param().isEmpty())
1694  h << " " << cppType((*itEntry)->paramType()) <<" i ";
1695  h << ")" << Const;
1696  // function body inline only if not using dpointer
1697  // for BC mode
1698  if ( !cfg.dpointer )
1699  {
1700  h << endl << " {" << endl;
1701  h << indent(memberAccessorBody(*itEntry, cfg.globalEnums, cfg), 6 );
1702  h << " }" << endl;
1703  }
1704  else
1705  {
1706  h << ";" << endl;
1707  }
1708 
1709  // Default value Accessor
1710  if ((cfg.allDefaultGetters || cfg.defaultGetters.contains(n)) && !(*itEntry)->defaultValue().isEmpty()) {
1711  h << endl;
1712  h << " /**" << endl;
1713  h << " Get " << (*itEntry)->label() << " default value" << endl;
1714  h << " */" << endl;
1715  if (cfg.staticAccessors)
1716  h << " static" << endl;
1717  h << " ";
1718  if (cfg.useEnumTypes && t == "Enum")
1719  h << enumType(*itEntry, cfg.globalEnums);
1720  else
1721  h << cppType(t);
1722  h << " " << getDefaultFunction(n) << "(";
1723  if ( !(*itEntry)->param().isEmpty() )
1724  h << " " << cppType( (*itEntry)->paramType() ) <<" i ";
1725  h << ")" << Const << endl;
1726  h << " {" << endl;
1727  h << " return ";
1728  if (cfg.useEnumTypes && t == "Enum")
1729  h << "static_cast<" << enumType(*itEntry, cfg.globalEnums) << ">(";
1730  h << getDefaultFunction(n) << "_helper(";
1731  if ( !(*itEntry)->param().isEmpty() )
1732  h << " i ";
1733  h << ")";
1734  if (cfg.useEnumTypes && t == "Enum")
1735  h << ")";
1736  h << ";" << endl;
1737  h << " }" << endl;
1738  }
1739 
1740  // Item accessor
1741  if ( cfg.itemAccessors ) {
1742  h << endl;
1743  h << " /**" << endl;
1744  h << " Get Item object corresponding to " << n << "()"
1745  << endl;
1746  h << " */" << endl;
1747  h << " Item" << itemType( (*itEntry)->type() ) << " *"
1748  << getFunction( n ) << "Item(";
1749  if (!(*itEntry)->param().isEmpty()) {
1750  h << " " << cppType((*itEntry)->paramType()) << " i ";
1751  }
1752  h << ")";
1753  if ( !cfg.dpointer )
1754  {
1755  h << endl << " {" << endl;
1756  h << indent( itemAccessorBody((*itEntry), cfg), 6);
1757  h << " }" << endl;
1758  }
1759  else
1760  {
1761  h << ";" << endl;
1762  }
1763  }
1764 
1765  h << endl;
1766  }
1767 
1768 
1769  // Signal definition.
1770  if( hasSignals ) {
1771  h << endl;
1772  h << " Q_SIGNALS:";
1773  foreach(const Signal &signal, signalList) {
1774  h << endl;
1775  if ( !signal.label.isEmpty() ) {
1776  h << " /**" << endl;
1777  h << " " << signal.label << endl;
1778  h << " */" << endl;
1779  }
1780  h << " void " << signal.name << "(";
1781  QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
1782  for ( it = signal.arguments.constBegin(); it != itEnd; ) {
1783  SignalArguments argument = *it;
1784  QString type = param(argument.type);
1785  if ( cfg.useEnumTypes && argument.type == "Enum" ) {
1786  for ( int i = 0, end = entries.count(); i < end; ++i ) {
1787  if ( entries[i]->name() == argument.variableName ) {
1788  type = enumType(entries[i], cfg.globalEnums);
1789  break;
1790  }
1791  }
1792  }
1793  h << type << " " << argument.variableName;
1794  if ( ++it != itEnd ) {
1795  h << ", ";
1796  }
1797  }
1798  h << ");" << endl;
1799  }
1800  h << endl;
1801  }
1802 
1803  h << " protected:" << endl;
1804 
1805  // Private constructor for singleton
1806  if ( cfg.singleton ) {
1807  h << " " << cfg.className << "(";
1808  if ( cfgFileNameArg )
1809  h << "const QString& arg";
1810  h << ");" << endl;
1811  h << " friend class " << cfg.className << "Helper;" << endl << endl;
1812  }
1813 
1814  if ( hasSignals ) {
1815  h << " virtual void usrWriteConfig();" << endl;
1816  }
1817 
1818  // Member variables
1819  if ( !cfg.memberVariables.isEmpty() && cfg.memberVariables != "private" && cfg.memberVariables != "dpointer") {
1820  h << " " << cfg.memberVariables << ":" << endl;
1821  }
1822 
1823  // Class Parameters
1824  for (QList<Param>::ConstIterator it = parameters.constBegin();
1825  it != parameters.constEnd(); ++it)
1826  {
1827  h << " " << cppType((*it).type) << " mParam" << (*it).name << ";" << endl;
1828  }
1829 
1830  if ( cfg.memberVariables != "dpointer" )
1831  {
1832  QString group;
1833  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1834  if ( (*itEntry)->group() != group ) {
1835  group = (*itEntry)->group();
1836  h << endl;
1837  h << " // " << group << endl;
1838  }
1839  h << " " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name(), cfg );
1840  if ( !(*itEntry)->param().isEmpty() )
1841  {
1842  h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
1843  }
1844  h << ";" << endl;
1845 
1846  if ( cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name()) )
1847  {
1848  h << " ";
1849  if (cfg.staticAccessors)
1850  h << "static ";
1851  h << cppType((*itEntry)->type()) << " " << getDefaultFunction((*itEntry)->name()) << "_helper(";
1852  if ( !(*itEntry)->param().isEmpty() )
1853  h << " " << cppType( (*itEntry)->paramType() ) <<" i ";
1854  h << ")" << Const << ";" << endl;
1855  }
1856  }
1857 
1858  h << endl << " private:" << endl;
1859  if ( cfg.itemAccessors ) {
1860  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1861  h << " Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry, cfg );
1862  if ( !(*itEntry)->param().isEmpty() ) h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
1863  h << ";" << endl;
1864  }
1865  }
1866  if ( hasSignals )
1867  h << " uint " << varName("settingsChanged", cfg) << ";" << endl;
1868 
1869  }
1870  else
1871  {
1872  // use a private class for both member variables and items
1873  h << " private:" << endl;
1874  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1875  if ( cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name()) ) {
1876  h << " ";
1877  if (cfg.staticAccessors)
1878  h << "static ";
1879  h << cppType((*itEntry)->type()) << " " << getDefaultFunction((*itEntry)->name()) << "_helper(";
1880  if ( !(*itEntry)->param().isEmpty() )
1881  h << " " << cppType( (*itEntry)->paramType() ) <<" i ";
1882  h << ")" << Const << ";" << endl;
1883  }
1884  }
1885  h << " " + cfg.className + "Private *d;" << endl;
1886  }
1887 
1888  if (cfg.customAddons)
1889  {
1890  h << " // Include custom additions" << endl;
1891  h << " #include \"" << filenameOnly(baseName) << "_addons.h\"" <<endl;
1892  }
1893 
1894  h << "};" << endl << endl;
1895 
1896  endNamespaces(cfg.nameSpace, h);
1897 
1898  h << "#endif" << endl << endl;
1899 
1900 
1901  header.close();
1902 
1903  QFile implementation( baseDir + implementationFileName );
1904  if ( !implementation.open( QIODevice::WriteOnly ) ) {
1905  cerr << "Can not open '" << implementationFileName << "for writing."
1906  << endl;
1907  return 1;
1908  }
1909 
1910  QTextStream cpp( &implementation );
1911 
1912  cpp.setCodec("utf-8");
1913  cpp << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
1914  cpp << "// All changes you do to this file will be lost." << endl << endl;
1915 
1916  cpp << "#include \"" << headerFileName << "\"" << endl << endl;
1917 
1918  for( it = cfg.sourceIncludes.constBegin(); it != cfg.sourceIncludes.constEnd(); ++it ) {
1919  if ( (*it).startsWith('"') )
1920  cpp << "#include " << *it << endl;
1921  else
1922  cpp << "#include <" << *it << ">" << endl;
1923  }
1924 
1925  if ( cfg.sourceIncludes.count() > 0 ) cpp << endl;
1926 
1927  if ( cfg.setUserTexts ) cpp << "#include <klocale.h>" << endl << endl;
1928 
1929  // Header required by singleton implementation
1930  if ( cfg.singleton )
1931  cpp << "#include <kglobal.h>" << endl << "#include <QtCore/QFile>" << endl << endl;
1932  if ( cfg.singleton && cfgFileNameArg )
1933  cpp << "#include <kdebug.h>" << endl << endl;
1934 
1935  if ( !cfg.nameSpace.isEmpty() )
1936  cpp << "using namespace " << cfg.nameSpace << ";" << endl << endl;
1937 
1938  QString group;
1939 
1940  // private class implementation
1941  if ( cfg.dpointer )
1942  {
1943  beginNamespaces(cfg.nameSpace, cpp);
1944  cpp << "class " << cfg.className << "Private" << endl;
1945  cpp << "{" << endl;
1946  cpp << " public:" << endl;
1947  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1948  if ( (*itEntry)->group() != group ) {
1949  group = (*itEntry)->group();
1950  cpp << endl;
1951  cpp << " // " << group << endl;
1952  }
1953  cpp << " " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name(), cfg );
1954  if ( !(*itEntry)->param().isEmpty() )
1955  {
1956  cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
1957  }
1958  cpp << ";" << endl;
1959  }
1960  cpp << endl << " // items" << endl;
1961  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
1962  cpp << " "+cfg.inherits+"::Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry, cfg );
1963  if ( !(*itEntry)->param().isEmpty() ) cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
1964  cpp << ";" << endl;
1965  }
1966  if ( hasSignals ) {
1967  cpp << " uint " << varName("settingsChanged", cfg) << ";" << endl;
1968  }
1969 
1970  cpp << "};" << endl << endl;
1971  endNamespaces(cfg.nameSpace, cpp);
1972  }
1973 
1974  // Singleton implementation
1975  if ( cfg.singleton ) {
1976  beginNamespaces(cfg.nameSpace, cpp);
1977  cpp << "class " << cfg.className << "Helper" << endl;
1978  cpp << '{' << endl;
1979  cpp << " public:" << endl;
1980  cpp << " " << cfg.className << "Helper() : q(0) {}" << endl;
1981  cpp << " ~" << cfg.className << "Helper() { delete q; }" << endl;
1982  cpp << " " << cfg.className << " *q;" << endl;
1983  cpp << "};" << endl;
1984  endNamespaces(cfg.nameSpace, cpp);
1985  cpp << "K_GLOBAL_STATIC(" << cfg.className << "Helper, s_global" << cfg.className << ")" << endl;
1986 
1987  cpp << cfg.className << " *" << cfg.className << "::self()" << endl;
1988  cpp << "{" << endl;
1989  if ( cfgFileNameArg ) {
1990  cpp << " if (!s_global" << cfg.className << "->q)" << endl;
1991  cpp << " kFatal() << \"you need to call " << cfg.className << "::instance before using\";" << endl;
1992  } else {
1993  cpp << " if (!s_global" << cfg.className << "->q) {" << endl;
1994  cpp << " new " << cfg.className << ';' << endl;
1995  cpp << " s_global" << cfg.className << "->q->readConfig();" << endl;
1996  cpp << " }" << endl << endl;
1997  }
1998  cpp << " return s_global" << cfg.className << "->q;" << endl;
1999  cpp << "}" << endl << endl;
2000 
2001  if ( cfgFileNameArg ) {
2002  cpp << "void " << cfg.className << "::instance(const QString& cfgfilename)" << endl;
2003  cpp << "{" << endl;
2004  cpp << " if (s_global" << cfg.className << "->q) {" << endl;
2005  cpp << " kDebug() << \"" << cfg.className << "::instance called after the first use - ignoring\";" << endl;
2006  cpp << " return;" << endl;
2007  cpp << " }" << endl;
2008  cpp << " new " << cfg.className << "(cfgfilename);" << endl;
2009  cpp << " s_global" << cfg.className << "->q->readConfig();" << endl;
2010  cpp << "}" << endl << endl;
2011  }
2012  }
2013 
2014  if ( !cppPreamble.isEmpty() )
2015  cpp << cppPreamble << endl;
2016 
2017  // Constructor
2018  cpp << cfg.className << "::" << cfg.className << "( ";
2019  if ( cfgFileNameArg ) {
2020  if ( !cfg.singleton && ! cfg.forceStringFilename)
2021  cpp << " KSharedConfig::Ptr config";
2022  else
2023  cpp << " const QString& config";
2024  cpp << (parameters.isEmpty() ? " " : ", ");
2025  }
2026 
2027  for (QList<Param>::ConstIterator it = parameters.constBegin();
2028  it != parameters.constEnd(); ++it)
2029  {
2030  if (it != parameters.constBegin())
2031  cpp << ",";
2032  cpp << " " << param((*it).type) << " " << (*it).name;
2033  }
2034  cpp << " )" << endl;
2035 
2036  cpp << " : " << cfg.inherits << "(";
2037  if ( !cfgFileName.isEmpty() ) cpp << " QLatin1String( \"" << cfgFileName << "\" ";
2038  if ( cfgFileNameArg ) cpp << " config ";
2039  if ( !cfgFileName.isEmpty() ) cpp << ") ";
2040  cpp << ")" << endl;
2041 
2042  // Store parameters
2043  for (QList<Param>::ConstIterator it = parameters.constBegin();
2044  it != parameters.constEnd(); ++it)
2045  {
2046  cpp << " , mParam" << (*it).name << "(" << (*it).name << ")" << endl;
2047  }
2048 
2049  if ( hasSignals && !cfg.dpointer )
2050  cpp << " , " << varName("settingsChanged", cfg) << "(0)" << endl;
2051 
2052  cpp << "{" << endl;
2053 
2054  if (cfg.dpointer)
2055  {
2056  cpp << " d = new " + cfg.className + "Private;" << endl;
2057  if (hasSignals)
2058  cpp << " " << varPath("settingsChanged", cfg) << " = 0;" << endl;
2059  }
2060  // Needed in case the singleton class is used as baseclass for
2061  // another singleton.
2062  if (cfg.singleton) {
2063  cpp << " Q_ASSERT(!s_global" << cfg.className << "->q);" << endl;
2064  cpp << " s_global" << cfg.className << "->q = this;" << endl;
2065  }
2066 
2067  group.clear();
2068 
2069  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
2070  if ( (*itEntry)->group() != group ) {
2071  if ( !group.isEmpty() ) cpp << endl;
2072  group = (*itEntry)->group();
2073  cpp << " setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl;
2074  }
2075 
2076  QString key = paramString( (*itEntry)->key(), parameters );
2077  if ( !(*itEntry)->code().isEmpty() ) {
2078  cpp << (*itEntry)->code() << endl;
2079  }
2080  if ( (*itEntry)->type() == "Enum" ) {
2081  cpp << " QList<"+cfg.inherits+"::ItemEnum::Choice2> values"
2082  << (*itEntry)->name() << ";" << endl;
2083  const QList<CfgEntry::Choice> choices = (*itEntry)->choices().choices;
2084  QList<CfgEntry::Choice>::ConstIterator it;
2085  for( it = choices.constBegin(); it != choices.constEnd(); ++it ) {
2086  cpp << " {" << endl;
2087  cpp << " "+cfg.inherits+"::ItemEnum::Choice2 choice;" << endl;
2088  cpp << " choice.name = QLatin1String(\"" << (*it).name << "\");" << endl;
2089  if ( cfg.setUserTexts ) {
2090  if ( !(*it).label.isEmpty() ) {
2091  cpp << " choice.label = ";
2092  if ( !(*it).context.isEmpty() )
2093  cpp << "i18nc(" + quoteString((*it).context) + ", ";
2094  else
2095  cpp << "i18n(";
2096  cpp << quoteString((*it).label) << ");" << endl;
2097  }
2098  if ( !(*it).toolTip.isEmpty() ) {
2099  cpp << " choice.toolTip = ";
2100  if ( !(*it).context.isEmpty() )
2101  cpp << "i18nc(" + quoteString((*it).context) + ", ";
2102  else
2103  cpp << "i18n(";
2104  cpp << quoteString((*it).toolTip) << ");" << endl;
2105  }
2106  if ( !(*it).whatsThis.isEmpty() ) {
2107  cpp << " choice.whatsThis = ";
2108  if ( !(*it).context.isEmpty() )
2109  cpp << "i18nc(" + quoteString((*it).context) + ", ";
2110  else
2111  cpp << "i18n(";
2112  cpp << quoteString((*it).whatsThis) << ");" << endl;
2113  }
2114  }
2115  cpp << " values" << (*itEntry)->name() << ".append( choice );" << endl;
2116  cpp << " }" << endl;
2117  }
2118  }
2119 
2120  if (!cfg.dpointer)
2121  cpp << itemDeclaration( *itEntry, cfg );
2122 
2123  if ( (*itEntry)->param().isEmpty() )
2124  {
2125  // Normal case
2126  cpp << " " << itemPath( *itEntry, cfg ) << " = "
2127  << newItem( (*itEntry)->type(), (*itEntry)->name(), key, (*itEntry)->defaultValue(), cfg ) << endl;
2128 
2129  if ( !(*itEntry)->minValue().isEmpty() )
2130  cpp << " " << itemPath( *itEntry, cfg ) << "->setMinValue(" << (*itEntry)->minValue() << ");" << endl;
2131  if ( !(*itEntry)->maxValue().isEmpty() )
2132  cpp << " " << itemPath( *itEntry, cfg ) << "->setMaxValue(" << (*itEntry)->maxValue() << ");" << endl;
2133 
2134  if ( cfg.setUserTexts )
2135  cpp << userTextsFunctions( (*itEntry), cfg );
2136 
2137  cpp << " addItem( " << itemPath( *itEntry, cfg );
2138  QString quotedName = (*itEntry)->name();
2139  addQuotes( quotedName );
2140  if ( quotedName != key ) cpp << ", QLatin1String( \"" << (*itEntry)->name() << "\" )";
2141  cpp << " );" << endl;
2142  }
2143  else
2144  {
2145  // Indexed
2146  for(int i = 0; i <= (*itEntry)->paramMax(); i++)
2147  {
2148  QString defaultStr;
2149  QString itemVarStr(itemPath( *itEntry, cfg )+QString("[%1]").arg(i));
2150 
2151  if ( !(*itEntry)->paramDefaultValue(i).isEmpty() )
2152  defaultStr = (*itEntry)->paramDefaultValue(i);
2153  else if ( !(*itEntry)->defaultValue().isEmpty() )
2154  defaultStr = paramString( (*itEntry)->defaultValue(), (*itEntry), i );
2155  else
2156  defaultStr = defaultValue( (*itEntry)->type() );
2157 
2158  cpp << " " << itemVarStr << " = "
2159  << newItem( (*itEntry)->type(), (*itEntry)->name(), paramString(key, *itEntry, i), defaultStr,cfg, QString("[%1]").arg(i) )
2160  << endl;
2161 
2162  if ( cfg.setUserTexts )
2163  cpp << userTextsFunctions( *itEntry, cfg, itemVarStr, (*itEntry)->paramName() );
2164 
2165  // Make mutators for enum parameters work by adding them with $(..) replaced by the
2166  // param name. The check for isImmutable in the set* functions doesn't have the param
2167  // name available, just the corresponding enum value (int), so we need to store the
2168  // param names in a separate static list!.
2169  cpp << " addItem( " << itemVarStr << ", QLatin1String( \"";
2170  if ( (*itEntry)->paramType()=="Enum" )
2171  cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg((*itEntry)->paramValues()[i] );
2172  else
2173  cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg(i);
2174  cpp << "\" ) );" << endl;
2175  }
2176  }
2177  }
2178 
2179  cpp << "}" << endl << endl;
2180 
2181  if (cfg.dpointer)
2182  {
2183  // setters and getters go in Cpp if in dpointer mode
2184  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
2185  QString n = (*itEntry)->name();
2186  QString t = (*itEntry)->type();
2187 
2188  // Manipulator
2189  if (cfg.allMutators || cfg.mutators.contains(n))
2190  {
2191  cpp << "void " << setFunction(n, cfg.className) << "( ";
2192  if ( !(*itEntry)->param().isEmpty() )
2193  cpp << cppType( (*itEntry)->paramType() ) << " i, ";
2194  if (cfg.useEnumTypes && t == "Enum")
2195  cpp << enumType(*itEntry, cfg.globalEnums);
2196  else
2197  cpp << param( t );
2198  cpp << " v )" << endl;
2199  // function body inline only if not using dpointer
2200  // for BC mode
2201  cpp << "{" << endl;
2202  cpp << indent(memberMutatorBody( *itEntry, cfg ), 6);
2203  cpp << "}" << endl << endl;
2204  }
2205 
2206  // Accessor
2207  if (cfg.useEnumTypes && t == "Enum")
2208  cpp << enumType(*itEntry, cfg.globalEnums);
2209  else
2210  cpp << cppType(t);
2211  cpp << " " << getFunction(n, cfg.className) << "(";
2212  if ( !(*itEntry)->param().isEmpty() )
2213  cpp << " " << cppType( (*itEntry)->paramType() ) <<" i ";
2214  cpp << ")" << Const << endl;
2215  // function body inline only if not using dpointer
2216  // for BC mode
2217  cpp << "{" << endl;
2218  cpp << indent(memberAccessorBody( *itEntry, cfg.globalEnums, cfg ), 2);
2219  cpp << "}" << endl << endl;
2220 
2221  // Default value Accessor -- written by the loop below
2222 
2223  // Item accessor
2224  if ( cfg.itemAccessors )
2225  {
2226  cpp << endl;
2227  cpp << cfg.inherits+"::Item" << itemType( (*itEntry)->type() ) << " *"
2228  << getFunction( n, cfg.className ) << "Item(";
2229  if ( !(*itEntry)->param().isEmpty() ) {
2230  cpp << " " << cppType( (*itEntry)->paramType() ) << " i ";
2231  }
2232  cpp << ")" << endl;
2233  cpp << "{" << endl;
2234  cpp << indent(itemAccessorBody( *itEntry, cfg ), 2);
2235  cpp << "}" << endl;
2236  }
2237 
2238  cpp << endl;
2239  }
2240  }
2241 
2242  // default value getters always go in Cpp
2243  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
2244  QString n = (*itEntry)->name();
2245  QString t = (*itEntry)->type();
2246 
2247  // Default value Accessor, as "helper" function
2248  if (( cfg.allDefaultGetters || cfg.defaultGetters.contains(n) ) && !(*itEntry)->defaultValue().isEmpty() ) {
2249  cpp << cppType(t) << " " << getDefaultFunction(n, cfg.className) << "_helper(";
2250  if ( !(*itEntry)->param().isEmpty() )
2251  cpp << " " << cppType( (*itEntry)->paramType() ) <<" i ";
2252  cpp << ")" << Const << endl;
2253  cpp << "{" << endl;
2254  cpp << memberGetDefaultBody(*itEntry) << endl;
2255  cpp << "}" << endl << endl;
2256  }
2257  }
2258 
2259  // Destructor
2260  cpp << cfg.className << "::~" << cfg.className << "()" << endl;
2261  cpp << "{" << endl;
2262  if ( cfg.singleton ) {
2263  if ( cfg.dpointer )
2264  cpp << " delete d;" << endl;
2265  cpp << " if (!s_global" << cfg.className << ".isDestroyed()) {" << endl;
2266  cpp << " s_global" << cfg.className << "->q = 0;" << endl;
2267  cpp << " }" << endl;
2268  }
2269  cpp << "}" << endl << endl;
2270 
2271  if ( hasSignals ) {
2272  cpp << "void " << cfg.className << "::" << "usrWriteConfig()" << endl;
2273  cpp << "{" << endl;
2274  cpp << " " << cfg.inherits << "::usrWriteConfig();" << endl << endl;
2275  foreach(const Signal &signal, signalList) {
2276  cpp << " if ( " << varPath("settingsChanged", cfg) << " & " << signalEnumName(signal.name) << " ) " << endl;
2277  cpp << " emit " << signal.name << "(";
2278  QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
2279  for ( it = signal.arguments.constBegin(); it != itEnd; ) {
2280  SignalArguments argument = *it;
2281  bool cast = false;
2282  if ( cfg.useEnumTypes && argument.type == "Enum" ) {
2283  for ( int i = 0, end = entries.count(); i < end; ++i ) {
2284  if ( entries[i]->name() == argument.variableName ) {
2285  cpp << "static_cast<" << enumType(entries[i], cfg.globalEnums) << ">(";
2286  cast = true;
2287  break;
2288  }
2289  }
2290  }
2291  cpp << varPath(argument.variableName, cfg);
2292  if ( cast )
2293  cpp << ")";
2294  if ( ++it != itEnd )
2295  cpp << ", ";
2296  }
2297  cpp << ");" << endl << endl;
2298  }
2299  cpp << " " << varPath("settingsChanged", cfg) << " = 0;" << endl;
2300  cpp << "}" << endl;
2301  }
2302 
2303  // Add includemoc if they are signals defined.
2304  if( hasSignals ) {
2305  cpp << endl;
2306  cpp << "#include \"" << mocFileName << "\"" << endl;
2307  cpp << endl;
2308  }
2309 
2310  // clear entries list
2311  qDeleteAll( entries );
2312 
2313  implementation.close();
2314 }
QTextStream::setCodec
void setCodec(QTextCodec *codec)
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
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
Const
QString Const
Definition: kconfig_compiler.cpp:104
QString::append
QString & append(QChar ch)
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
QString::toUpper
QString toUpper() const
paramString
QString paramString(const QString &s, const CfgEntry *e, int i)
Definition: kconfig_compiler.cpp:1058
allNames
QStringList allNames
Definition: kconfig_compiler.cpp:101
QTextStream::readLine
QString readLine(qint64 maxlen)
KMacroExpander::group
Definition: kmacroexpander_unix.cpp:34
QDomElement::attribute
QString attribute(const QString &name, const QString &defValue) const
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
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
QCoreApplication
QString::prepend
QString & prepend(QChar ch)
itemVar
static QString itemVar(const CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1006
validNameRegexp
QRegExp * validNameRegexp
Definition: kconfig_compiler.cpp:102
QList::at
const T & at(int i) const
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
QString::simplified
QString simplified() const
getDefaultFunction
static QString getDefaultFunction(const QString &n, const QString &className=QString())
Definition: kconfig_compiler.cpp:442
QDomDocument::documentElement
QDomElement documentElement() const
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
QDomNode
QStringList::join
QString join(const QString &separator) const
varPath
static QString varPath(const QString &n, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:374
QString::remove
QString & remove(int position, int n)
indent
QString indent(QString text, int spaces)
Definition: kconfig_compiler.cpp:1285
QFile
QTextStream
prefix
QString prefix()
Definition: kstandarddirs_win.cpp:28
QString::lastIndexOf
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QString::clear
void clear()
endNamespaces
void endNamespaces(const QString &p_ns, QTextStream &p_out)
Definition: kconfig_compiler.cpp:1316
QRegExp
literalString
static QString literalString(const QString &s)
Definition: kconfig_compiler.cpp:481
QString::number
QString number(int n, int base)
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
QTextStream::atEnd
bool atEnd() const
QList::empty
bool empty() const
isUnsigned
static bool isUnsigned(const QString &type)
Definition: kconfig_compiler.cpp:877
QFileInfo::fileName
QString fileName() const
itemAccessorBody
QString itemAccessorBody(CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1272
QChar::fromLatin1
QChar fromLatin1(char c)
QString::toInt
int toInt(bool *ok, int base) const
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QList::first
T & first()
QString
QList< SignalArguments >
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
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
cppType
QString cppType(const QString &t)
Actual C++ storage type for given type.
Definition: kconfig_compiler.cpp:920
QStringList
QFileInfo
This
QString This
Definition: kconfig_compiler.cpp:103
QString::toLower
QString toLower() const
QSettings
QString::contains
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QLatin1Char
QDomDocument
QFile::close
virtual void close()
QDomNode::isNull
bool isNull() const
itemType
QString itemType(const QString &type)
Definition: kconfig_compiler.cpp:980
QString::replace
QString & replace(int position, int n, QChar after)
QSettings::value
QVariant value(const QString &key, const QVariant &defaultValue) const
QDomNode::save
void save(QTextStream &str, int indent) const
QString::mid
QString mid(int position, int n) const
QVariant::toStringList
QStringList toStringList() const
itemDeclaration
static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:990
QLatin1String
varName
static QString varName(const QString &n, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:360
QString::count
int count() const
QString::sprintf
QString & sprintf(const char *cformat,...)
QDomNode::firstChildElement
QDomElement firstChildElement(const QString &tagName) const
QList::ConstIterator
typedef ConstIterator
memberGetDefaultBody
QString memberGetDefaultBody(CfgEntry *e)
Definition: kconfig_compiler.cpp:1246
QString::length
int length() const
signalEnumName
static QString signalEnumName(const QString &signalName)
Definition: kconfig_compiler.cpp:513
QVariant::toBool
bool toBool() const
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
QString::left
QString left(int n) const
QString::fromLatin1
QString fromLatin1(const char *str, int size)
QStringList::indexOf
int indexOf(const QRegExp &rx, int from) const
QList::constEnd
const_iterator constEnd() const
QCoreApplication::arguments
QStringList arguments()
QList::constBegin
const_iterator constBegin() const
QDomElement
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
QRegExp::exactMatch
bool exactMatch(const QString &str) const
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QVariant::toString
QString toString() const
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
QDomDocument::setContent
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
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-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:11 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
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • 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