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

KDECore

  • 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
43namespace
44{
45 QTextStream cout(stdout);
46 QTextStream cerr(stderr);
47}
48
49static 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
101QStringList allNames;
102QRegExp *validNameRegexp;
103QString This;
104QString Const;
105
109class CfgConfig
110{
111public:
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
145public:
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
170struct SignalArguments
171{
172 QString type;
173 QString variableName;
174};
175
176class Signal {
177public:
178 QString name;
179 QString label;
180 QList<SignalArguments> arguments;
181};
182
183
184
185
186class 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
351class Param {
352public:
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
360static 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
374static 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
386static QString enumName(const QString &n)
387{
388 QString result = QString::fromLatin1("Enum") + n;
389 result[4] = result[4].toUpper();
390 return result;
391}
392
393static 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
404static 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
417static 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
432static 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
442static 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
452static 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
463static 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
471static 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
481static 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
493static 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
505static 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
513static 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
522static 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
602CfgEntry *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
877static bool isUnsigned(const QString& type)
878{
879 if ( type == "UInt" ) return true;
880 if ( type == "ULongLong" ) return true;
881 return false;
882}
883
887QString 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
920QString 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
950QString 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
980QString 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
990static 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
1006static 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
1030static 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
1042QString 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
1058QString 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
1079QString 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 */
1102QString 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
1148QString 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
1172QString 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
1246QString 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
1272QString 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
1285QString 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
1304void 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
1316void 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
1327int 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}
QList
Definition: kaboutdata.h:33
QStringList
QString
header
const char header[]
Definition: fake/kauth-policy-gen-polkit.cpp:26
filenameOnly
static QString filenameOnly(const QString &path)
Definition: kconfig_compiler.cpp:505
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
memberMutatorBody
QString memberMutatorBody(CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1172
dumpNode
static QString dumpNode(const QDomNode &node)
Definition: kconfig_compiler.cpp:493
itemDeclaration
static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:990
setFunction
static QString setFunction(const QString &n, const QString &className=QString())
Definition: kconfig_compiler.cpp:432
validNameRegexp
QRegExp * validNameRegexp
Definition: kconfig_compiler.cpp:102
Const
QString Const
Definition: kconfig_compiler.cpp:104
paramString
QString paramString(const QString &s, const CfgEntry *e, int i)
Definition: kconfig_compiler.cpp:1058
defaultValue
QString defaultValue(const QString &t)
Definition: kconfig_compiler.cpp:950
itemVar
static QString itemVar(const CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1006
endNamespaces
void endNamespaces(const QString &p_ns, QTextStream &p_out)
Definition: kconfig_compiler.cpp:1316
main
int main(int argc, char **argv)
Definition: kconfig_compiler.cpp:1327
memberGetDefaultBody
QString memberGetDefaultBody(CfgEntry *e)
Definition: kconfig_compiler.cpp:1246
enumTypeQualifier
static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
Definition: kconfig_compiler.cpp:417
indent
QString indent(QString text, int spaces)
Definition: kconfig_compiler.cpp:1285
This
QString This
Definition: kconfig_compiler.cpp:103
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
parseArgs
static void parseArgs(const QStringList &args, QString &directory, QString &file1, QString &file2)
Definition: kconfig_compiler.cpp:49
getDefaultFunction
static QString getDefaultFunction(const QString &n, const QString &className=QString())
Definition: kconfig_compiler.cpp:442
itemAccessorBody
QString itemAccessorBody(CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1272
allNames
QStringList allNames
Definition: kconfig_compiler.cpp:101
parseEntry
CfgEntry * parseEntry(const QString &group, const QDomElement &element, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:602
signalEnumName
static QString signalEnumName(const QString &signalName)
Definition: kconfig_compiler.cpp:513
varPath
static QString varPath(const QString &n, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:374
itemType
QString itemType(const QString &type)
Definition: kconfig_compiler.cpp:980
enumName
static QString enumName(const QString &n)
Definition: kconfig_compiler.cpp:386
isUnsigned
static bool isUnsigned(const QString &type)
Definition: kconfig_compiler.cpp:877
quoteString
static QString quoteString(const QString &s)
Definition: kconfig_compiler.cpp:471
itemPath
static QString itemPath(const CfgEntry *e, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1030
beginNamespaces
void beginNamespaces(const QString &p_ns, QTextStream &p_out)
Definition: kconfig_compiler.cpp:1304
cppType
QString cppType(const QString &t)
Actual C++ storage type for given type.
Definition: kconfig_compiler.cpp:920
userTextsFunctions
QString userTextsFunctions(CfgEntry *e, const CfgConfig &cfg, QString itemVarStr=QString(), QString i=QString())
Definition: kconfig_compiler.cpp:1102
memberAccessorBody
QString memberAccessorBody(CfgEntry *e, bool globalEnums, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:1148
literalString
static QString literalString(const QString &s)
Definition: kconfig_compiler.cpp:481
enumType
static QString enumType(const CfgEntry *e, bool globalEnums)
Definition: kconfig_compiler.cpp:404
param
QString param(const QString &t)
Return parameter declaration for given type.
Definition: kconfig_compiler.cpp:887
addQuotes
static void addQuotes(QString &s)
Definition: kconfig_compiler.cpp:463
varName
static QString varName(const QString &n, const CfgConfig &cfg)
Definition: kconfig_compiler.cpp:360
getFunction
static QString getFunction(const QString &n, const QString &className=QString())
Definition: kconfig_compiler.cpp:452
prefix
QString prefix()
Definition: kstandarddirs_win.cpp:28
KMacroExpander::group
@ group
Definition: kmacroexpander_unix.cpp:34
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 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-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 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
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