Changeset View
Changeset View
Standalone View
Standalone View
src/kconfig_compiler/kconfig_compiler.cpp
Show All 25 Lines | |||||
26 | // Compiling this file with this flag is just crazy | 26 | // Compiling this file with this flag is just crazy | ||
27 | #undef QT_NO_CAST_FROM_ASCII | 27 | #undef QT_NO_CAST_FROM_ASCII | ||
28 | 28 | | |||
29 | #include <QCoreApplication> | 29 | #include <QCoreApplication> | ||
30 | #include <QFile> | 30 | #include <QFile> | ||
31 | #include <QFileInfo> | 31 | #include <QFileInfo> | ||
32 | #include <QSettings> | 32 | #include <QSettings> | ||
33 | #include <QTextStream> | 33 | #include <QTextStream> | ||
34 | #include <QDomAttr> | | |||
35 | #include <QRegExp> | 34 | #include <QRegExp> | ||
36 | #include <QStringList> | 35 | #include <QStringList> | ||
37 | 36 | | |||
38 | #include <qcommandlineparser.h> | 37 | #include <qcommandlineparser.h> | ||
39 | #include <qcommandlineoption.h> | 38 | #include <qcommandlineoption.h> | ||
40 | 39 | | |||
41 | #include <ostream> | 40 | #include <ostream> | ||
42 | #include <iostream> | 41 | #include <iostream> | ||
43 | #include <stdlib.h> | 42 | #include <stdlib.h> | ||
44 | 43 | | |||
45 | #include "../../kconfig_version.h" | 44 | #include "../../kconfig_version.h" | ||
45 | #include "KConfigXTParameters.h" | ||||
46 | #include "KConfigCommonStructs.h" | ||||
47 | #include "KConfigHeaderGenerator.h" | ||||
48 | #include "KConfigSourceGenerator.h" | ||||
49 | #include "KCFGXmlParser.h" | ||||
46 | 50 | | |||
47 | namespace | 51 | namespace | ||
48 | { | 52 | { | ||
49 | QTextStream cout(stdout); | 53 | QTextStream cout(stdout); | ||
50 | QTextStream cerr(stderr); | 54 | QTextStream cerr(stderr); | ||
51 | } | 55 | } | ||
52 | 56 | | |||
53 | QStringList allNames; | 57 | QStringList allNames; | ||
54 | QRegExp *validNameRegexp; | 58 | QRegExp *validNameRegexp; | ||
55 | QString This; | 59 | QString This; | ||
56 | QString Const; | 60 | QString Const; | ||
57 | 61 | | |||
58 | /** | 62 | QString varName(const QString &n, const KConfigXTParameters &cfg) | ||
59 | Configuration Compiler Configuration | | |||
60 | */ | | |||
61 | class CfgConfig | | |||
62 | { | | |||
63 | public: | | |||
64 | CfgConfig(const QString &codegenFilename) | | |||
65 | { | | |||
66 | // Configure the compiler with some settings | | |||
67 | QSettings codegenConfig(codegenFilename, QSettings::IniFormat); | | |||
68 | | ||||
69 | nameSpace = codegenConfig.value(QStringLiteral("NameSpace")).toString(); | | |||
70 | className = codegenConfig.value(QStringLiteral("ClassName")).toString(); | | |||
71 | if (className.isEmpty()) { | | |||
72 | cerr << "Class name missing" << endl; | | |||
73 | exit(1); | | |||
74 | } | | |||
75 | inherits = codegenConfig.value(QStringLiteral("Inherits")).toString(); | | |||
76 | if (inherits.isEmpty()) { | | |||
77 | inherits = QStringLiteral("KConfigSkeleton"); | | |||
78 | } | | |||
79 | visibility = codegenConfig.value(QStringLiteral("Visibility")).toString(); | | |||
80 | if (!visibility.isEmpty()) { | | |||
81 | visibility += ' '; | | |||
82 | } | | |||
83 | parentInConstructor = codegenConfig.value(QStringLiteral("ParentInConstructor"), false).toBool(); | | |||
84 | forceStringFilename = codegenConfig.value(QStringLiteral("ForceStringFilename"), false).toBool(); | | |||
85 | singleton = codegenConfig.value(QStringLiteral("Singleton"), false).toBool(); | | |||
86 | staticAccessors = singleton; | | |||
87 | customAddons = codegenConfig.value(QStringLiteral("CustomAdditions"), false).toBool(); | | |||
88 | memberVariables = codegenConfig.value(QStringLiteral("MemberVariables")).toString(); | | |||
89 | dpointer = (memberVariables == QLatin1String("dpointer")); | | |||
90 | headerIncludes = codegenConfig.value(QStringLiteral("IncludeFiles"), QStringList()).toStringList(); | | |||
91 | sourceIncludes = codegenConfig.value(QStringLiteral("SourceIncludeFiles"), QStringList()).toStringList(); | | |||
92 | mutators = codegenConfig.value(QStringLiteral("Mutators"), QStringList()).toStringList(); | | |||
93 | allMutators = ((mutators.count() == 1) && (mutators.at(0).toLower() == QLatin1String("true"))); | | |||
94 | itemAccessors = codegenConfig.value(QStringLiteral("ItemAccessors"), false).toBool(); | | |||
95 | setUserTexts = codegenConfig.value(QStringLiteral("SetUserTexts"), false).toBool(); | | |||
96 | defaultGetters = codegenConfig.value(QStringLiteral("DefaultValueGetters"), QStringList()).toStringList(); | | |||
97 | allDefaultGetters = (defaultGetters.count() == 1) && (defaultGetters.at(0).toLower() == QLatin1String("true")); | | |||
98 | notifiers = codegenConfig.value(QStringLiteral("Notifiers"), QStringList()).toStringList(); | | |||
99 | allNotifiers = ((notifiers.count() == 1) && (notifiers.at(0).toLower() == QLatin1String("true"))); | | |||
100 | globalEnums = codegenConfig.value(QStringLiteral("GlobalEnums"), false).toBool(); | | |||
101 | useEnumTypes = codegenConfig.value(QStringLiteral("UseEnumTypes"), false).toBool(); | | |||
102 | const QString trString = codegenConfig.value(QStringLiteral("TranslationSystem")).toString().toLower(); | | |||
103 | generateProperties = codegenConfig.value(QStringLiteral("GenerateProperties"), false).toBool(); | | |||
104 | if (trString == QLatin1String("kde")) { | | |||
105 | translationSystem = KdeTranslation; | | |||
106 | translationDomain = codegenConfig.value(QStringLiteral("TranslationDomain")).toString(); | | |||
107 | } else { | | |||
108 | if (!trString.isEmpty() && trString != QLatin1String("qt")) { | | |||
109 | cerr << "Unknown translation system, falling back to Qt tr()" << endl; | | |||
110 | } | | |||
111 | translationSystem = QtTranslation; | | |||
112 | } | | |||
113 | qCategoryLoggingName = codegenConfig.value(QStringLiteral("CategoryLoggingName"), QString()).toString(); | | |||
114 | headerExtension = codegenConfig.value(QStringLiteral("HeaderExtension"), QStringLiteral("h")).toString(); | | |||
115 | sourceExtension = codegenConfig.value(QStringLiteral("SourceExtension"), QStringLiteral("cpp")).toString(); | | |||
116 | } | | |||
117 | | ||||
118 | public: | | |||
119 | enum TranslationSystem { | | |||
120 | QtTranslation, | | |||
121 | KdeTranslation | | |||
122 | }; | | |||
123 | | ||||
124 | // These are read from the .kcfgc configuration file | | |||
125 | QString nameSpace; // The namespace for the class to be generated | | |||
126 | QString className; // The class name to be generated | | |||
127 | QString inherits; // The class the generated class inherits (if empty, from KConfigSkeleton) | | |||
128 | QString visibility; | | |||
129 | bool parentInConstructor; // The class has the optional parent parameter in its constructor | | |||
130 | bool forceStringFilename; | | |||
131 | bool singleton; // The class will be a singleton | | |||
132 | bool staticAccessors; // provide or not static accessors | | |||
133 | bool customAddons; | | |||
134 | QString memberVariables; | | |||
135 | QStringList headerIncludes; | | |||
136 | QStringList sourceIncludes; | | |||
137 | QStringList mutators; | | |||
138 | QStringList defaultGetters; | | |||
139 | QStringList notifiers; | | |||
140 | QString qCategoryLoggingName; | | |||
141 | QString headerExtension; | | |||
142 | QString sourceExtension; | | |||
143 | bool allMutators; | | |||
144 | bool setUserTexts; | | |||
145 | bool allDefaultGetters; | | |||
146 | bool dpointer; | | |||
147 | bool globalEnums; | | |||
148 | bool useEnumTypes; | | |||
149 | bool itemAccessors; | | |||
150 | bool allNotifiers; | | |||
151 | TranslationSystem translationSystem; | | |||
152 | QString translationDomain; | | |||
153 | bool generateProperties; | | |||
154 | }; | | |||
155 | | ||||
156 | struct SignalArguments { | | |||
157 | QString type; | | |||
158 | QString variableName; | | |||
159 | }; | | |||
160 | | ||||
161 | class Signal | | |||
162 | { | | |||
163 | public: | | |||
164 | Signal() : modify(false) {} | | |||
165 | | ||||
166 | QString name; | | |||
167 | QString label; | | |||
168 | QList<SignalArguments> arguments; | | |||
169 | bool modify; | | |||
170 | }; | | |||
171 | | ||||
172 | class CfgEntry | | |||
173 | { | | |||
174 | public: | | |||
175 | struct Choice { | | |||
176 | QString name; | | |||
177 | QString context; | | |||
178 | QString label; | | |||
179 | QString toolTip; | | |||
180 | QString whatsThis; | | |||
181 | }; | | |||
182 | class Choices | | |||
183 | { | | |||
184 | public: | | |||
185 | Choices() {} | | |||
186 | Choices(const QList<Choice> &d, const QString &n, const QString &p) | | |||
187 | : prefix(p), choices(d), mName(n) | | |||
188 | { | | |||
189 | int i = n.indexOf(QLatin1String("::")); | | |||
190 | if (i >= 0) { | | |||
191 | mExternalQual = n.left(i + 2); | | |||
192 | } | | |||
193 | } | | |||
194 | QString prefix; | | |||
195 | QList<Choice> choices; | | |||
196 | const QString &name() const | | |||
197 | { | | |||
198 | return mName; | | |||
199 | } | | |||
200 | const QString &externalQualifier() const | | |||
201 | { | | |||
202 | return mExternalQual; | | |||
203 | } | | |||
204 | bool external() const | | |||
205 | { | | |||
206 | return !mExternalQual.isEmpty(); | | |||
207 | } | | |||
208 | private: | | |||
209 | QString mName; | | |||
210 | QString mExternalQual; | | |||
211 | }; | | |||
212 | | ||||
213 | CfgEntry(const QString &group, const QString &type, const QString &key, | | |||
214 | const QString &name, const QString &labelContext, const QString &label, | | |||
215 | const QString &toolTipContext, const QString &toolTip, const QString &whatsThisContext, const QString &whatsThis, const QString &code, | | |||
216 | const QString &defaultValue, const Choices &choices, const QList<Signal> &signalList, | | |||
217 | bool hidden) | | |||
218 | : mGroup(group), mType(type), mKey(key), mName(name), | | |||
219 | mLabelContext(labelContext), mLabel(label), mToolTipContext(toolTipContext), mToolTip(toolTip), | | |||
220 | mWhatsThisContext(whatsThisContext), mWhatsThis(whatsThis), | | |||
221 | mCode(code), mDefaultValue(defaultValue), mChoices(choices), | | |||
222 | mSignalList(signalList), mParamMax(0), mHidden(hidden) | | |||
223 | { | | |||
224 | } | | |||
225 | | ||||
226 | void setGroup(const QString &group) | | |||
227 | { | | |||
228 | mGroup = group; | | |||
229 | } | | |||
230 | QString group() const | | |||
231 | { | | |||
232 | return mGroup; | | |||
233 | } | | |||
234 | | ||||
235 | void setType(const QString &type) | | |||
236 | { | | |||
237 | mType = type; | | |||
238 | } | | |||
239 | QString type() const | | |||
240 | { | | |||
241 | return mType; | | |||
242 | } | | |||
243 | | ||||
244 | void setKey(const QString &key) | | |||
245 | { | | |||
246 | mKey = key; | | |||
247 | } | | |||
248 | QString key() const | | |||
249 | { | | |||
250 | return mKey; | | |||
251 | } | | |||
252 | | ||||
253 | void setName(const QString &name) | | |||
254 | { | | |||
255 | mName = name; | | |||
256 | } | | |||
257 | QString name() const | | |||
258 | { | | |||
259 | return mName; | | |||
260 | } | | |||
261 | | ||||
262 | void setLabelContext(const QString &labelContext) | | |||
263 | { | | |||
264 | mLabelContext = labelContext; | | |||
265 | } | | |||
266 | QString labelContext() const | | |||
267 | { | | |||
268 | return mLabelContext; | | |||
269 | } | | |||
270 | | ||||
271 | void setLabel(const QString &label) | | |||
272 | { | | |||
273 | mLabel = label; | | |||
274 | } | | |||
275 | QString label() const | | |||
276 | { | | |||
277 | return mLabel; | | |||
278 | } | | |||
279 | | ||||
280 | void setToolTipContext(const QString &toolTipContext) | | |||
281 | { | | |||
282 | mToolTipContext = toolTipContext; | | |||
283 | } | | |||
284 | QString toolTipContext() const | | |||
285 | { | | |||
286 | return mToolTipContext; | | |||
287 | } | | |||
288 | | ||||
289 | void setToolTip(const QString &toolTip) | | |||
290 | { | | |||
291 | mToolTip = toolTip; | | |||
292 | } | | |||
293 | QString toolTip() const | | |||
294 | { | | |||
295 | return mToolTip; | | |||
296 | } | | |||
297 | | ||||
298 | void setWhatsThisContext(const QString &whatsThisContext) | | |||
299 | { | | |||
300 | mWhatsThisContext = whatsThisContext; | | |||
301 | } | | |||
302 | QString whatsThisContext() const | | |||
303 | { | | |||
304 | return mWhatsThisContext; | | |||
305 | } | | |||
306 | | ||||
307 | void setWhatsThis(const QString &whatsThis) | | |||
308 | { | | |||
309 | mWhatsThis = whatsThis; | | |||
310 | } | | |||
311 | QString whatsThis() const | | |||
312 | { | | |||
313 | return mWhatsThis; | | |||
314 | } | | |||
315 | | ||||
316 | void setDefaultValue(const QString &d) | | |||
317 | { | | |||
318 | mDefaultValue = d; | | |||
319 | } | | |||
320 | QString defaultValue() const | | |||
321 | { | | |||
322 | return mDefaultValue; | | |||
323 | } | | |||
324 | | ||||
325 | void setCode(const QString &d) | | |||
326 | { | | |||
327 | mCode = d; | | |||
328 | } | | |||
329 | QString code() const | | |||
330 | { | | |||
331 | return mCode; | | |||
332 | } | | |||
333 | | ||||
334 | void setMinValue(const QString &d) | | |||
335 | { | | |||
336 | mMin = d; | | |||
337 | } | | |||
338 | QString minValue() const | | |||
339 | { | | |||
340 | return mMin; | | |||
341 | } | | |||
342 | | ||||
343 | void setMaxValue(const QString &d) | | |||
344 | { | | |||
345 | mMax = d; | | |||
346 | } | | |||
347 | QString maxValue() const | | |||
348 | { | | |||
349 | return mMax; | | |||
350 | } | | |||
351 | | ||||
352 | void setParam(const QString &d) | | |||
353 | { | | |||
354 | mParam = d; | | |||
355 | } | | |||
356 | QString param() const | | |||
357 | { | | |||
358 | return mParam; | | |||
359 | } | | |||
360 | | ||||
361 | void setParamName(const QString &d) | | |||
362 | { | | |||
363 | mParamName = d; | | |||
364 | } | | |||
365 | QString paramName() const | | |||
366 | { | | |||
367 | return mParamName; | | |||
368 | } | | |||
369 | | ||||
370 | void setParamType(const QString &d) | | |||
371 | { | | |||
372 | mParamType = d; | | |||
373 | } | | |||
374 | QString paramType() const | | |||
375 | { | | |||
376 | return mParamType; | | |||
377 | } | | |||
378 | | ||||
379 | void setChoices(const QList<Choice> &d, const QString &n, const QString &p) | | |||
380 | { | | |||
381 | mChoices = Choices(d, n, p); | | |||
382 | } | | |||
383 | Choices choices() const | | |||
384 | { | | |||
385 | return mChoices; | | |||
386 | } | | |||
387 | | ||||
388 | void setParamValues(const QStringList &d) | | |||
389 | { | | |||
390 | mParamValues = d; | | |||
391 | } | | |||
392 | QStringList paramValues() const | | |||
393 | { | | |||
394 | return mParamValues; | | |||
395 | } | | |||
396 | | ||||
397 | void setParamDefaultValues(const QStringList &d) | | |||
398 | { | | |||
399 | mParamDefaultValues = d; | | |||
400 | } | | |||
401 | QString paramDefaultValue(int i) const | | |||
402 | { | | |||
403 | return mParamDefaultValues[i]; | | |||
404 | } | | |||
405 | | ||||
406 | void setParamMax(int d) | | |||
407 | { | | |||
408 | mParamMax = d; | | |||
409 | } | | |||
410 | int paramMax() const | | |||
411 | { | | |||
412 | return mParamMax; | | |||
413 | } | | |||
414 | | ||||
415 | void setSignalList(const QList<Signal> &value) | | |||
416 | { | | |||
417 | mSignalList = value; | | |||
418 | } | | |||
419 | QList<Signal> signalList() const | | |||
420 | { | | |||
421 | return mSignalList; | | |||
422 | } | | |||
423 | | ||||
424 | bool hidden() const | | |||
425 | { | | |||
426 | return mHidden; | | |||
427 | } | | |||
428 | | ||||
429 | void dump() const | | |||
430 | { | | |||
431 | cerr << "<entry>" << endl; | | |||
432 | cerr << " group: " << mGroup << endl; | | |||
433 | cerr << " type: " << mType << endl; | | |||
434 | cerr << " key: " << mKey << endl; | | |||
435 | cerr << " name: " << mName << endl; | | |||
436 | cerr << " label context: " << mLabelContext << endl; | | |||
437 | cerr << " label: " << mLabel << endl; | | |||
438 | // whatsthis | | |||
439 | cerr << " code: " << mCode << endl; | | |||
440 | // cerr << " values: " << mValues.join(":") << endl; | | |||
441 | | ||||
442 | if (!param().isEmpty()) { | | |||
443 | cerr << " param name: " << mParamName << endl; | | |||
444 | cerr << " param type: " << mParamType << endl; | | |||
445 | cerr << " paramvalues: " << mParamValues.join(QChar::fromLatin1(':')) << endl; | | |||
446 | } | | |||
447 | cerr << " default: " << mDefaultValue << endl; | | |||
448 | cerr << " hidden: " << mHidden << endl; | | |||
449 | cerr << " min: " << mMin << endl; | | |||
450 | cerr << " max: " << mMax << endl; | | |||
451 | cerr << "</entry>" << endl; | | |||
452 | } | | |||
453 | | ||||
454 | private: | | |||
455 | QString mGroup; | | |||
456 | QString mType; | | |||
457 | QString mKey; | | |||
458 | QString mName; | | |||
459 | QString mLabelContext; | | |||
460 | QString mLabel; | | |||
461 | QString mToolTipContext; | | |||
462 | QString mToolTip; | | |||
463 | QString mWhatsThisContext; | | |||
464 | QString mWhatsThis; | | |||
465 | QString mCode; | | |||
466 | QString mDefaultValue; | | |||
467 | QString mParam; | | |||
468 | QString mParamName; | | |||
469 | QString mParamType; | | |||
470 | Choices mChoices; | | |||
471 | QList<Signal> mSignalList; | | |||
472 | QStringList mParamValues; | | |||
473 | QStringList mParamDefaultValues; | | |||
474 | int mParamMax; | | |||
475 | bool mHidden; | | |||
476 | QString mMin; | | |||
477 | QString mMax; | | |||
478 | }; | | |||
479 | | ||||
480 | class Param | | |||
481 | { | | |||
482 | public: | | |||
483 | QString name; | | |||
484 | QString type; | | |||
485 | }; | | |||
486 | | ||||
487 | // returns the name of an member variable | | |||
488 | // use itemPath to know the full path | | |||
489 | // like using d-> in case of dpointer | | |||
490 | static QString varName(const QString &n, const CfgConfig &cfg) | | |||
491 | { | 63 | { | ||
492 | QString result; | 64 | QString result; | ||
493 | if (!cfg.dpointer) { | 65 | if (!cfg.dpointer) { | ||
494 | result = QChar::fromLatin1('m') + n; | 66 | result = QChar::fromLatin1('m') + n; | ||
495 | result[1] = result[1].toUpper(); | 67 | result[1] = result[1].toUpper(); | ||
496 | } else { | 68 | } else { | ||
497 | result = n; | 69 | result = n; | ||
498 | result[0] = result[0].toLower(); | 70 | result[0] = result[0].toLower(); | ||
499 | } | 71 | } | ||
500 | return result; | 72 | return result; | ||
501 | } | 73 | } | ||
502 | 74 | | |||
503 | static QString varPath(const QString &n, const CfgConfig &cfg) | 75 | QString varPath(const QString &n, const KConfigXTParameters &cfg) | ||
504 | { | 76 | { | ||
505 | QString result; | 77 | QString result; | ||
506 | if (cfg.dpointer) { | 78 | if (cfg.dpointer) { | ||
507 | result = "d->" + varName(n, cfg); | 79 | result = "d->" + varName(n, cfg); | ||
508 | } else { | 80 | } else { | ||
509 | result = varName(n, cfg); | 81 | result = varName(n, cfg); | ||
510 | } | 82 | } | ||
511 | return result; | 83 | return result; | ||
512 | } | 84 | } | ||
513 | 85 | | |||
514 | static QString enumName(const QString &n) | 86 | QString enumName(const QString &n) | ||
515 | { | 87 | { | ||
516 | QString result = QLatin1String("Enum") + n; | 88 | QString result = QLatin1String("Enum") + n; | ||
517 | result[4] = result[4].toUpper(); | 89 | result[4] = result[4].toUpper(); | ||
518 | return result; | 90 | return result; | ||
519 | } | 91 | } | ||
520 | 92 | | |||
521 | static QString enumName(const QString &n, const CfgEntry::Choices &c) | 93 | QString enumName(const QString &n, const CfgEntry::Choices &c) | ||
522 | { | 94 | { | ||
523 | QString result = c.name(); | 95 | QString result = c.name(); | ||
524 | if (result.isEmpty()) { | 96 | if (result.isEmpty()) { | ||
525 | result = QLatin1String("Enum") + n; | 97 | result = QLatin1String("Enum") + n; | ||
526 | result[4] = result[4].toUpper(); | 98 | result[4] = result[4].toUpper(); | ||
527 | } | 99 | } | ||
528 | return result; | 100 | return result; | ||
529 | } | 101 | } | ||
530 | 102 | | |||
531 | static QString enumType(const CfgEntry *e, bool globalEnums) | 103 | QString enumType(const CfgEntry *e, bool globalEnums) | ||
532 | { | 104 | { | ||
533 | QString result = e->choices().name(); | 105 | QString result = e->choices.name(); | ||
534 | if (result.isEmpty()) { | 106 | if (result.isEmpty()) { | ||
535 | result = QLatin1String("Enum") + e->name(); | 107 | result = QLatin1String("Enum") + e->name; | ||
536 | if (!globalEnums) { | 108 | if (!globalEnums) { | ||
537 | result += QLatin1String("::type"); | 109 | result += QLatin1String("::type"); | ||
538 | } | 110 | } | ||
539 | result[4] = result[4].toUpper(); | 111 | result[4] = result[4].toUpper(); | ||
540 | } | 112 | } | ||
541 | return result; | 113 | return result; | ||
542 | } | 114 | } | ||
543 | 115 | | |||
544 | static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c) | 116 | static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c) | ||
545 | { | 117 | { | ||
546 | QString result = c.name(); | 118 | QString result = c.name(); | ||
547 | if (result.isEmpty()) { | 119 | if (result.isEmpty()) { | ||
548 | result = QLatin1String("Enum") + n + QLatin1String("::"); | 120 | result = QLatin1String("Enum") + n + QLatin1String("::"); | ||
549 | result[4] = result[4].toUpper(); | 121 | result[4] = result[4].toUpper(); | ||
550 | } else if (c.external()) { | 122 | } else if (c.external()) { | ||
551 | result = c.externalQualifier(); | 123 | result = c.externalQualifier(); | ||
552 | } else { | 124 | } else { | ||
553 | result.clear(); | 125 | result.clear(); | ||
554 | } | 126 | } | ||
555 | return result; | 127 | return result; | ||
556 | } | 128 | } | ||
557 | 129 | | |||
558 | static QString setFunction(const QString &n, const QString &className = QString()) | 130 | QString setFunction(const QString &n, const QString &className) | ||
559 | { | 131 | { | ||
560 | QString result = QLatin1String("set") + n; | 132 | QString result = QLatin1String("set") + n; | ||
561 | result[3] = result[3].toUpper(); | 133 | result[3] = result[3].toUpper(); | ||
562 | 134 | | |||
563 | if (!className.isEmpty()) { | 135 | if (!className.isEmpty()) { | ||
564 | result = className + QLatin1String("::") + result; | 136 | result = className + QLatin1String("::") + result; | ||
565 | } | 137 | } | ||
566 | return result; | 138 | return result; | ||
567 | } | 139 | } | ||
568 | 140 | | |||
569 | static QString changeSignalName(const QString &n) | 141 | QString changeSignalName(const QString &n) | ||
570 | { | 142 | { | ||
571 | return n+QStringLiteral("Changed"); | 143 | return n+QStringLiteral("Changed"); | ||
572 | } | 144 | } | ||
573 | 145 | | |||
574 | static QString getDefaultFunction(const QString &n, const QString &className = QString()) | 146 | QString getDefaultFunction(const QString &n, const QString &className) | ||
575 | { | 147 | { | ||
576 | QString result = QLatin1String("default") + n + QLatin1String("Value"); | 148 | QString result = QLatin1String("default") + n + QLatin1String("Value"); | ||
577 | result[7] = result[7].toUpper(); | 149 | result[7] = result[7].toUpper(); | ||
578 | 150 | | |||
579 | if (!className.isEmpty()) { | 151 | if (!className.isEmpty()) { | ||
580 | result = className + QLatin1String("::") + result; | 152 | result = className + QLatin1String("::") + result; | ||
581 | } | 153 | } | ||
582 | return result; | 154 | return result; | ||
583 | } | 155 | } | ||
584 | 156 | | |||
585 | static QString getFunction(const QString &n, const QString &className = QString()) | 157 | QString getFunction(const QString &n, const QString &className) | ||
586 | { | 158 | { | ||
587 | QString result = n; | 159 | QString result = n; | ||
588 | result[0] = result[0].toLower(); | 160 | result[0] = result[0].toLower(); | ||
589 | 161 | | |||
590 | if (!className.isEmpty()) { | 162 | if (!className.isEmpty()) { | ||
591 | result = className + QLatin1String("::") + result; | 163 | result = className + QLatin1String("::") + result; | ||
592 | } | 164 | } | ||
593 | return result; | 165 | return result; | ||
594 | } | 166 | } | ||
595 | 167 | | |||
596 | static void addQuotes(QString &s) | 168 | void addQuotes(QString &s) | ||
597 | { | 169 | { | ||
598 | if (!s.startsWith(QLatin1Char('"'))) { | 170 | if (!s.startsWith(QLatin1Char('"'))) { | ||
599 | s.prepend(QLatin1Char('"')); | 171 | s.prepend(QLatin1Char('"')); | ||
600 | } | 172 | } | ||
601 | if (!s.endsWith(QLatin1Char('"'))) { | 173 | if (!s.endsWith(QLatin1Char('"'))) { | ||
602 | s.append(QLatin1Char('"')); | 174 | s.append(QLatin1Char('"')); | ||
603 | } | 175 | } | ||
604 | } | 176 | } | ||
605 | 177 | | |||
606 | static QString quoteString(const QString &s) | 178 | static QString quoteString(const QString &s) | ||
607 | { | 179 | { | ||
608 | QString r = s; | 180 | QString r = s; | ||
609 | r.replace(QLatin1Char('\\'), QLatin1String("\\\\")); | 181 | r.replace(QLatin1Char('\\'), QLatin1String("\\\\")); | ||
610 | r.replace(QLatin1Char('\"'), QLatin1String("\\\"")); | 182 | r.replace(QLatin1Char('\"'), QLatin1String("\\\"")); | ||
611 | r.remove(QLatin1Char('\r')); | 183 | r.remove(QLatin1Char('\r')); | ||
612 | r.replace(QLatin1Char('\n'), QLatin1String("\\n\"\n\"")); | 184 | r.replace(QLatin1Char('\n'), QLatin1String("\\n\"\n\"")); | ||
613 | return QLatin1Char('\"') + r + QLatin1Char('\"'); | 185 | return QLatin1Char('\"') + r + QLatin1Char('\"'); | ||
614 | } | 186 | } | ||
615 | 187 | | |||
616 | static QString literalString(const QString &s) | 188 | QString literalString(const QString &s) | ||
617 | { | 189 | { | ||
618 | bool isAscii = true; | 190 | bool isAscii = true; | ||
619 | for (int i = s.length(); i--;) | 191 | for (int i = s.length(); i--;) | ||
620 | if (s[i].unicode() > 127) { | 192 | if (s[i].unicode() > 127) { | ||
621 | isAscii = false; | 193 | isAscii = false; | ||
622 | } | 194 | } | ||
623 | 195 | | |||
624 | if (isAscii) { | 196 | if (isAscii) { | ||
625 | return QLatin1String("QStringLiteral( ") + quoteString(s) + QLatin1String(" )"); | 197 | return QLatin1String("QStringLiteral( ") + quoteString(s) + QLatin1String(" )"); | ||
626 | } else { | 198 | } else { | ||
627 | return QLatin1String("QString::fromUtf8( ") + quoteString(s) + QLatin1String(" )"); | 199 | return QLatin1String("QString::fromUtf8( ") + quoteString(s) + QLatin1String(" )"); | ||
628 | } | 200 | } | ||
629 | } | 201 | } | ||
630 | 202 | | |||
631 | static QString dumpNode(const QDomNode &node) | | |||
632 | { | | |||
633 | QString msg; | | |||
634 | QTextStream s(&msg, QIODevice::WriteOnly); | | |||
635 | node.save(s, 0); | | |||
636 | | ||||
637 | msg = msg.simplified(); | | |||
638 | if (msg.length() > 40) { | | |||
639 | return msg.left(37) + QLatin1String("..."); | | |||
640 | } | | |||
641 | return msg; | | |||
642 | } | | |||
643 | 203 | | |||
644 | static QString filenameOnly(const QString &path) | 204 | QString filenameOnly(const QString &path) | ||
645 | { | 205 | { | ||
646 | int i = path.lastIndexOf(QRegExp(QStringLiteral("[/\\]"))); | 206 | int i = path.lastIndexOf(QRegExp(QStringLiteral("[/\\]"))); | ||
647 | if (i >= 0) { | 207 | if (i >= 0) { | ||
648 | return path.mid(i + 1); | 208 | return path.mid(i + 1); | ||
649 | } | 209 | } | ||
650 | return path; | 210 | return path; | ||
651 | } | 211 | } | ||
652 | 212 | | |||
653 | static QString signalEnumName(const QString &signalName) | 213 | QString signalEnumName(const QString &signalName) | ||
654 | { | 214 | { | ||
655 | QString result; | 215 | QString result; | ||
656 | result = QLatin1String("signal") + signalName; | 216 | result = QLatin1String("signal") + signalName; | ||
657 | result[6] = result[6].toUpper(); | 217 | result[6] = result[6].toUpper(); | ||
658 | 218 | | |||
659 | return result; | 219 | return result; | ||
660 | } | 220 | } | ||
661 | 221 | | |||
662 | static void preProcessDefault(QString &defaultValue, const QString &name, | | |||
663 | const QString &type, | | |||
664 | const CfgEntry::Choices &choices, | | |||
665 | QString &code, const CfgConfig &cfg) | | |||
666 | { | | |||
667 | if (type == QLatin1String("String") && !defaultValue.isEmpty()) { | | |||
668 | defaultValue = literalString(defaultValue); | | |||
669 | | ||||
670 | } else if (type == QLatin1String("Path") && !defaultValue.isEmpty()) { | | |||
671 | defaultValue = literalString(defaultValue); | | |||
672 | } else if (type == QLatin1String("Url") && !defaultValue.isEmpty()) { | | |||
673 | // Use fromUserInput in order to support absolute paths and absolute urls, like KDE4's KUrl(QString) did. | | |||
674 | defaultValue = QLatin1String("QUrl::fromUserInput( ") + literalString(defaultValue) + QLatin1Char(')'); | | |||
675 | } else if ((type == QLatin1String("UrlList") || type == QLatin1String("StringList") || type == QLatin1String("PathList")) && !defaultValue.isEmpty()) { | | |||
676 | QTextStream cpp(&code, QIODevice::WriteOnly | QIODevice::Append); | | |||
677 | if (!code.isEmpty()) { | | |||
678 | cpp << endl; | | |||
679 | } | | |||
680 | | ||||
681 | if (type == QLatin1String("UrlList")) { | | |||
682 | cpp << " QList<QUrl> default" << name << ";" << endl; | | |||
683 | } else { | | |||
684 | cpp << " QStringList default" << name << ";" << endl; | | |||
685 | } | | |||
686 | const QStringList defaults = defaultValue.split(QLatin1Char(',')); | | |||
687 | QStringList::ConstIterator it; | | |||
688 | for (it = defaults.constBegin(); it != defaults.constEnd(); ++it) { | | |||
689 | cpp << " default" << name << ".append( "; | | |||
690 | if (type == QLatin1String("UrlList")) { | | |||
691 | cpp << "QUrl::fromUserInput("; | | |||
692 | } | | |||
693 | cpp << "QString::fromUtf8( \"" << *it << "\" ) "; | | |||
694 | if (type == QLatin1String("UrlList")) { | | |||
695 | cpp << ") "; | | |||
696 | } | | |||
697 | cpp << ");" << endl; | | |||
698 | } | | |||
699 | defaultValue = QLatin1String("default") + name; | | |||
700 | | ||||
701 | } else if (type == QLatin1String("Color") && !defaultValue.isEmpty()) { | | |||
702 | QRegExp colorRe(QStringLiteral("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?")); | | |||
703 | if (colorRe.exactMatch(defaultValue)) { | | |||
704 | defaultValue = QLatin1String("QColor( ") + defaultValue + QLatin1String(" )"); | | |||
705 | } else { | | |||
706 | defaultValue = QLatin1String("QColor( \"") + defaultValue + QLatin1String("\" )"); | | |||
707 | } | | |||
708 | | ||||
709 | } else if (type == QLatin1String("Enum")) { | | |||
710 | QList<CfgEntry::Choice>::ConstIterator it; | | |||
711 | for (it = choices.choices.constBegin(); it != choices.choices.constEnd(); ++it) { | | |||
712 | if ((*it).name == defaultValue) { | | |||
713 | if (cfg.globalEnums && choices.name().isEmpty()) { | | |||
714 | defaultValue.prepend(choices.prefix); | | |||
715 | } else { | | |||
716 | defaultValue.prepend(enumTypeQualifier(name, choices) + choices.prefix); | | |||
717 | } | | |||
718 | break; | | |||
719 | } | | |||
720 | } | | |||
721 | | ||||
722 | } else if (type == QLatin1String("IntList")) { | | |||
723 | QTextStream cpp(&code, QIODevice::WriteOnly | QIODevice::Append); | | |||
724 | if (!code.isEmpty()) { | | |||
725 | cpp << endl; | | |||
726 | } | | |||
727 | | ||||
728 | cpp << " QList<int> default" << name << ";" << endl; | | |||
729 | if (!defaultValue.isEmpty()) { | | |||
730 | const QStringList defaults = defaultValue.split(QLatin1Char(',')); | | |||
731 | QStringList::ConstIterator it; | | |||
732 | for (it = defaults.constBegin(); it != defaults.constEnd(); ++it) { | | |||
733 | cpp << " default" << name << ".append( " << *it << " );" | | |||
734 | << endl; | | |||
735 | } | | |||
736 | } | | |||
737 | defaultValue = QLatin1String("default") + name; | | |||
738 | } | | |||
739 | } | | |||
740 | | ||||
741 | CfgEntry *parseEntry(const QString &group, const QDomElement &element, const CfgConfig &cfg) | | |||
742 | { | | |||
743 | bool defaultCode = false; | | |||
744 | QString type = element.attribute(QStringLiteral("type")); | | |||
745 | QString name = element.attribute(QStringLiteral("name")); | | |||
746 | QString key = element.attribute(QStringLiteral("key")); | | |||
747 | QString hidden = element.attribute(QStringLiteral("hidden")); | | |||
748 | QString labelContext; | | |||
749 | QString label; | | |||
750 | QString toolTipContext; | | |||
751 | QString toolTip; | | |||
752 | QString whatsThisContext; | | |||
753 | QString whatsThis; | | |||
754 | QString defaultValue; | | |||
755 | QString code; | | |||
756 | QString param; | | |||
757 | QString paramName; | | |||
758 | QString paramType; | | |||
759 | CfgEntry::Choices choices; | | |||
760 | QList<Signal> signalList; | | |||
761 | QStringList paramValues; | | |||
762 | QStringList paramDefaultValues; | | |||
763 | QString minValue; | | |||
764 | QString maxValue; | | |||
765 | int paramMax = 0; | | |||
766 | | ||||
767 | for (QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) { | | |||
768 | QString tag = e.tagName(); | | |||
769 | if (tag == QLatin1String("label")) { | | |||
770 | label = e.text(); | | |||
771 | labelContext = e.attribute(QStringLiteral("context")); | | |||
772 | } else if (tag == QLatin1String("tooltip")) { | | |||
773 | toolTip = e.text(); | | |||
774 | toolTipContext = e.attribute(QStringLiteral("context")); | | |||
775 | } else if (tag == QLatin1String("whatsthis")) { | | |||
776 | whatsThis = e.text(); | | |||
777 | whatsThisContext = e.attribute(QStringLiteral("context")); | | |||
778 | } else if (tag == QLatin1String("min")) { | | |||
779 | minValue = e.text(); | | |||
780 | } else if (tag == QLatin1String("max")) { | | |||
781 | maxValue = e.text(); | | |||
782 | } else if (tag == QLatin1String("code")) { | | |||
783 | code = e.text(); | | |||
784 | } else if (tag == QLatin1String("parameter")) { | | |||
785 | param = e.attribute(QStringLiteral("name")); | | |||
786 | paramType = e.attribute(QStringLiteral("type")); | | |||
787 | if (param.isEmpty()) { | | |||
788 | cerr << "Parameter must have a name: " << dumpNode(e) << endl; | | |||
789 | return nullptr; | | |||
790 | } | | |||
791 | if (paramType.isEmpty()) { | | |||
792 | cerr << "Parameter must have a type: " << dumpNode(e) << endl; | | |||
793 | return nullptr; | | |||
794 | } | | |||
795 | if ((paramType == QLatin1String("Int")) || (paramType == QLatin1String("UInt"))) { | | |||
796 | bool ok; | | |||
797 | paramMax = e.attribute(QStringLiteral("max")).toInt(&ok); | | |||
798 | if (!ok) { | | |||
799 | cerr << "Integer parameter must have a maximum (e.g. max=\"0\"): " | | |||
800 | << dumpNode(e) << endl; | | |||
801 | return nullptr; | | |||
802 | } | | |||
803 | } else if (paramType == QLatin1String("Enum")) { | | |||
804 | for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) { | | |||
805 | if (e2.tagName() == QLatin1String("values")) { | | |||
806 | for (QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement()) { | | |||
807 | if (e3.tagName() == QLatin1String("value")) { | | |||
808 | paramValues.append(e3.text()); | | |||
809 | } | | |||
810 | } | | |||
811 | break; | | |||
812 | } | | |||
813 | } | | |||
814 | if (paramValues.isEmpty()) { | | |||
815 | cerr << "No values specified for parameter '" << param | | |||
816 | << "'." << endl; | | |||
817 | return nullptr; | | |||
818 | } | | |||
819 | paramMax = paramValues.count() - 1; | | |||
820 | } else { | | |||
821 | cerr << "Parameter '" << param << "' has type " << paramType | | |||
822 | << " but must be of type int, uint or Enum." << endl; | | |||
823 | return nullptr; | | |||
824 | } | | |||
825 | } else if (tag == QLatin1String("default")) { | | |||
826 | if (e.attribute(QStringLiteral("param")).isEmpty()) { | | |||
827 | defaultValue = e.text(); | | |||
828 | if (e.attribute(QStringLiteral("code")) == QLatin1String("true")) { | | |||
829 | defaultCode = true; | | |||
830 | } | | |||
831 | } | | |||
832 | } else if (tag == QLatin1String("choices")) { | | |||
833 | QString name = e.attribute(QStringLiteral("name")); | | |||
834 | QString prefix = e.attribute(QStringLiteral("prefix")); | | |||
835 | QList<CfgEntry::Choice> chlist; | | |||
836 | for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) { | | |||
837 | if (e2.tagName() == QLatin1String("choice")) { | | |||
838 | CfgEntry::Choice choice; | | |||
839 | choice.name = e2.attribute(QStringLiteral("name")); | | |||
840 | if (choice.name.isEmpty()) { | | |||
841 | cerr << "Tag <choice> requires attribute 'name'." << endl; | | |||
842 | } | | |||
843 | for (QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement()) { | | |||
844 | if (e3.tagName() == QLatin1String("label")) { | | |||
845 | choice.label = e3.text(); | | |||
846 | choice.context = e3.attribute(QStringLiteral("context")); | | |||
847 | } | | |||
848 | if (e3.tagName() == QLatin1String("tooltip")) { | | |||
849 | choice.toolTip = e3.text(); | | |||
850 | choice.context = e3.attribute(QStringLiteral("context")); | | |||
851 | } | | |||
852 | if (e3.tagName() == QLatin1String("whatsthis")) { | | |||
853 | choice.whatsThis = e3.text(); | | |||
854 | choice.context = e3.attribute(QStringLiteral("context")); | | |||
855 | } | | |||
856 | } | | |||
857 | chlist.append(choice); | | |||
858 | } | | |||
859 | } | | |||
860 | choices = CfgEntry::Choices(chlist, name, prefix); | | |||
861 | } else if (tag == QLatin1String("emit")) { | | |||
862 | Signal signal; | | |||
863 | signal.name = e.attribute(QStringLiteral("signal")); | | |||
864 | signalList.append(signal); | | |||
865 | } | | |||
866 | } | | |||
867 | | ||||
868 | if (cfg.generateProperties && (cfg.allMutators || cfg.mutators.contains(name))) { | | |||
869 | Signal s; | | |||
870 | s.name = changeSignalName(name); | | |||
871 | s.modify = true; | | |||
872 | signalList.append(s); | | |||
873 | } | | |||
874 | | ||||
875 | bool nameIsEmpty = name.isEmpty(); | | |||
876 | if (nameIsEmpty && key.isEmpty()) { | | |||
877 | cerr << "Entry must have a name or a key: " << dumpNode(element) << endl; | | |||
878 | return nullptr; | | |||
879 | } | | |||
880 | | ||||
881 | if (key.isEmpty()) { | | |||
882 | key = name; | | |||
883 | } | | |||
884 | | ||||
885 | if (nameIsEmpty) { | | |||
886 | name = key; | | |||
887 | name.remove(' '); | | |||
888 | } else if (name.contains(' ')) { | | |||
889 | cout << "Entry '" << name << "' contains spaces! <name> elements can not contain spaces!" << endl; | | |||
890 | name.remove(' '); | | |||
891 | } | | |||
892 | | ||||
893 | if (name.contains(QStringLiteral("$("))) { | | |||
894 | if (param.isEmpty()) { | | |||
895 | cerr << "Name may not be parameterized: " << name << endl; | | |||
896 | return nullptr; | | |||
897 | } | | |||
898 | } else { | | |||
899 | if (!param.isEmpty()) { | | |||
900 | cerr << "Name must contain '$(" << param << ")': " << name << endl; | | |||
901 | return nullptr; | | |||
902 | } | | |||
903 | } | | |||
904 | | ||||
905 | if (label.isEmpty()) { | | |||
906 | label = key; | | |||
907 | } | | |||
908 | | ||||
909 | if (type.isEmpty()) { | | |||
910 | type = QStringLiteral("String"); // XXX : implicit type might be bad | | |||
911 | } | | |||
912 | | ||||
913 | if (!param.isEmpty()) { | | |||
914 | // Adjust name | | |||
915 | paramName = name; | | |||
916 | name.remove("$(" + param + ')'); | | |||
917 | // Lookup defaults for indexed entries | | |||
918 | for (int i = 0; i <= paramMax; i++) { | | |||
919 | paramDefaultValues.append(QString()); | | |||
920 | } | | |||
921 | | ||||
922 | for (QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) { | | |||
923 | QString tag = e.tagName(); | | |||
924 | if (tag == QLatin1String("default")) { | | |||
925 | QString index = e.attribute(QStringLiteral("param")); | | |||
926 | if (index.isEmpty()) { | | |||
927 | continue; | | |||
928 | } | | |||
929 | | ||||
930 | bool ok; | | |||
931 | int i = index.toInt(&ok); | | |||
932 | if (!ok) { | | |||
933 | i = paramValues.indexOf(index); | | |||
934 | if (i == -1) { | | |||
935 | cerr << "Index '" << index << "' for default value is unknown." << endl; | | |||
936 | return nullptr; | | |||
937 | } | | |||
938 | } | | |||
939 | | ||||
940 | if ((i < 0) || (i > paramMax)) { | | |||
941 | cerr << "Index '" << i << "' for default value is out of range [0, " << paramMax << "]." << endl; | | |||
942 | return nullptr; | | |||
943 | } | | |||
944 | | ||||
945 | QString tmpDefaultValue = e.text(); | | |||
946 | | ||||
947 | if (e.attribute(QStringLiteral("code")) != QLatin1String("true")) { | | |||
948 | preProcessDefault(tmpDefaultValue, name, type, choices, code, cfg); | | |||
949 | } | | |||
950 | | ||||
951 | paramDefaultValues[i] = tmpDefaultValue; | | |||
952 | } | | |||
953 | } | | |||
954 | } | | |||
955 | | ||||
956 | if (!validNameRegexp->exactMatch(name)) { | | |||
957 | if (nameIsEmpty) | | |||
958 | cerr << "The key '" << key << "' can not be used as name for the entry because " | | |||
959 | "it is not a valid name. You need to specify a valid name for this entry." << endl; | | |||
960 | else { | | |||
961 | cerr << "The name '" << name << "' is not a valid name for an entry." << endl; | | |||
962 | } | | |||
963 | return nullptr; | | |||
964 | } | | |||
965 | | ||||
966 | if (allNames.contains(name)) { | | |||
967 | if (nameIsEmpty) | | |||
968 | cerr << "The key '" << key << "' can not be used as name for the entry because " | | |||
969 | "it does not result in a unique name. You need to specify a unique name for this entry." << endl; | | |||
970 | else { | | |||
971 | cerr << "The name '" << name << "' is not unique." << endl; | | |||
972 | } | | |||
973 | return nullptr; | | |||
974 | } | | |||
975 | allNames.append(name); | | |||
976 | | ||||
977 | if (!defaultCode) { | | |||
978 | preProcessDefault(defaultValue, name, type, choices, code, cfg); | | |||
979 | } | | |||
980 | | ||||
981 | CfgEntry *result = new CfgEntry(group, type, key, name, labelContext, label, toolTipContext, toolTip, whatsThisContext, whatsThis, | | |||
982 | code, defaultValue, choices, signalList, | | |||
983 | hidden == QLatin1String("true")); | | |||
984 | if (!param.isEmpty()) { | | |||
985 | result->setParam(param); | | |||
986 | result->setParamName(paramName); | | |||
987 | result->setParamType(paramType); | | |||
988 | result->setParamValues(paramValues); | | |||
989 | result->setParamDefaultValues(paramDefaultValues); | | |||
990 | result->setParamMax(paramMax); | | |||
991 | } | | |||
992 | result->setMinValue(minValue); | | |||
993 | result->setMaxValue(maxValue); | | |||
994 | | ||||
995 | return result; | | |||
996 | } | | |||
997 | | ||||
998 | static bool isUnsigned(const QString &type) | 222 | static bool isUnsigned(const QString &type) | ||
999 | { | 223 | { | ||
1000 | if (type == QLatin1String("UInt")) { | 224 | if (type == QLatin1String("UInt")) { | ||
1001 | return true; | 225 | return true; | ||
1002 | } | 226 | } | ||
1003 | if (type == QLatin1String("ULongLong")) { | 227 | if (type == QLatin1String("ULongLong")) { | ||
1004 | return true; | 228 | return true; | ||
1005 | } | 229 | } | ||
▲ Show 20 Lines • Show All 164 Lines • ▼ Show 20 Line(s) | 393 | { | |||
1170 | QString t; | 394 | QString t; | ||
1171 | 395 | | |||
1172 | t = type; | 396 | t = type; | ||
1173 | t.replace(0, 1, t.left(1).toUpper()); | 397 | t.replace(0, 1, t.left(1).toUpper()); | ||
1174 | 398 | | |||
1175 | return t; | 399 | return t; | ||
1176 | } | 400 | } | ||
1177 | 401 | | |||
1178 | static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg) | 402 | QString itemDeclaration(const CfgEntry *e, const KConfigXTParameters &cfg) | ||
1179 | { | 403 | { | ||
1180 | if (cfg.itemAccessors) { | 404 | if (cfg.itemAccessors) { | ||
1181 | return QString(); | 405 | return QString(); | ||
1182 | } | 406 | } | ||
1183 | 407 | | |||
1184 | QString type; | 408 | QString type; | ||
1185 | if (!e->signalList().isEmpty()) { | 409 | if (!e->signalList.isEmpty()) { | ||
1186 | type = QStringLiteral("KConfigCompilerSignallingItem"); | 410 | type = QStringLiteral("KConfigCompilerSignallingItem"); | ||
1187 | } else { | 411 | } else { | ||
1188 | type = cfg.inherits + "::Item" + itemType(e->type()); | 412 | type = cfg.inherits + "::Item" + itemType(e->type); | ||
1189 | } | 413 | } | ||
1190 | 414 | | |||
1191 | QString fCap = e->name(); | 415 | QString fCap = e->name; | ||
1192 | fCap[0] = fCap[0].toUpper(); | 416 | fCap[0] = fCap[0].toUpper(); | ||
1193 | return " " + type + " *item" + fCap + | 417 | return " " + type + " *item" + fCap + | ||
1194 | ( (!e->param().isEmpty())?(QStringLiteral("[%1]").arg(e->paramMax()+1)) : QString()) + ";\n"; | 418 | ( (!e->param.isEmpty())?(QStringLiteral("[%1]").arg(e->paramMax+1)) : QString()) + ";\n"; | ||
1195 | } | 419 | } | ||
1196 | 420 | | |||
1197 | // returns the name of an item variable | 421 | // returns the name of an item variable | ||
1198 | // use itemPath to know the full path | 422 | // use itemPath to know the full path | ||
1199 | // like using d-> in case of dpointer | 423 | // like using d-> in case of dpointer | ||
1200 | static QString itemVar(const CfgEntry *e, const CfgConfig &cfg) | 424 | QString itemVar(const CfgEntry *e, const KConfigXTParameters &cfg) | ||
1201 | { | 425 | { | ||
1202 | QString result; | 426 | QString result; | ||
1203 | if (cfg.itemAccessors) { | 427 | if (cfg.itemAccessors) { | ||
1204 | if (!cfg.dpointer) { | 428 | if (!cfg.dpointer) { | ||
1205 | result = 'm' + e->name() + "Item"; | 429 | result = 'm' + e->name + "Item"; | ||
1206 | result[1] = result[1].toUpper(); | 430 | result[1] = result[1].toUpper(); | ||
1207 | } else { | 431 | } else { | ||
1208 | result = e->name() + "Item"; | 432 | result = e->name + "Item"; | ||
1209 | result[0] = result[0].toLower(); | 433 | result[0] = result[0].toLower(); | ||
1210 | } | 434 | } | ||
1211 | } else { | 435 | } else { | ||
1212 | result = "item" + e->name(); | 436 | result = "item" + e->name; | ||
1213 | result[4] = result[4].toUpper(); | 437 | result[4] = result[4].toUpper(); | ||
1214 | } | 438 | } | ||
1215 | return result; | 439 | return result; | ||
1216 | } | 440 | } | ||
1217 | 441 | | |||
1218 | static QString itemPath(const CfgEntry *e, const CfgConfig &cfg) | 442 | QString itemPath(const CfgEntry *e, const KConfigXTParameters &cfg) | ||
1219 | { | 443 | { | ||
1220 | QString result; | 444 | QString result; | ||
1221 | if (cfg.dpointer) { | 445 | if (cfg.dpointer) { | ||
1222 | result = "d->" + itemVar(e, cfg); | 446 | result = "d->" + itemVar(e, cfg); | ||
1223 | } else { | 447 | } else { | ||
1224 | result = itemVar(e, cfg); | 448 | result = itemVar(e, cfg); | ||
1225 | } | 449 | } | ||
1226 | return result; | 450 | return result; | ||
1227 | } | 451 | } | ||
1228 | 452 | | |||
1229 | QString newItem(const CfgEntry* entry, const QString &key, const QString& defaultValue, | 453 | QString newItem(const CfgEntry* entry, const QString &key, const QString& defaultValue, | ||
1230 | const CfgConfig &cfg, const QString ¶m = QString()) { | 454 | const KConfigXTParameters &cfg, const QString ¶m) { | ||
1231 | 455 | | |||
1232 | QList<Signal> sigs = entry->signalList(); | 456 | QList<Signal> sigs = entry->signalList; | ||
1233 | QString t; | 457 | QString t; | ||
1234 | if (!sigs.isEmpty()) { | 458 | if (!sigs.isEmpty()) { | ||
1235 | t += QLatin1String("new KConfigCompilerSignallingItem("); | 459 | t += QLatin1String("new KConfigCompilerSignallingItem("); | ||
1236 | } | 460 | } | ||
1237 | t += "new "+ cfg.inherits + "::Item" + itemType(entry->type()) + "( currentGroup(), " | 461 | t += "new "+ cfg.inherits + "::Item" + itemType(entry->type) + "( currentGroup(), " | ||
1238 | + key + ", " + varPath( entry->name(), cfg ) + param; | 462 | + key + ", " + varPath( entry->name, cfg ) + param; | ||
1239 | 463 | | |||
1240 | if (entry->type() == QLatin1String("Enum")) { | 464 | if (entry->type == QLatin1String("Enum")) { | ||
1241 | t += ", values" + entry->name(); | 465 | t += ", values" + entry->name; | ||
1242 | } | 466 | } | ||
1243 | if (!defaultValue.isEmpty()) { | 467 | if (!defaultValue.isEmpty()) { | ||
1244 | t += QLatin1String(", ") + defaultValue; | 468 | t += QLatin1String(", ") + defaultValue; | ||
1245 | } | 469 | } | ||
1246 | t += QLatin1String(" )"); | 470 | t += QLatin1String(" )"); | ||
1247 | 471 | | |||
1248 | if (!sigs.isEmpty()) { | 472 | if (!sigs.isEmpty()) { | ||
1249 | t += QLatin1String(", this, notifyFunction, "); | 473 | t += QLatin1String(", this, notifyFunction, "); | ||
1250 | //append the signal flags | 474 | //append the signal flags | ||
1251 | for (int i = 0; i < sigs.size(); ++i) { | 475 | for (int i = 0; i < sigs.size(); ++i) { | ||
1252 | if (i != 0) | 476 | if (i != 0) | ||
1253 | t += QLatin1String(" | "); | 477 | t += QLatin1String(" | "); | ||
1254 | t += signalEnumName(sigs[i].name); | 478 | t += signalEnumName(sigs[i].name); | ||
1255 | } | 479 | } | ||
1256 | t += QLatin1String(")"); | 480 | t += QLatin1String(")"); | ||
1257 | } | 481 | } | ||
1258 | t += QLatin1String(";"); | 482 | t += QLatin1String(";"); | ||
1259 | return t; | 483 | return t; | ||
1260 | } | 484 | } | ||
1261 | 485 | | |||
1262 | QString paramString(const QString &s, const CfgEntry *e, int i) | 486 | QString paramString(const QString &s, const CfgEntry *e, int i) | ||
1263 | { | 487 | { | ||
1264 | QString result = s; | 488 | QString result = s; | ||
1265 | QString needle = "$(" + e->param() + ')'; | 489 | QString needle = "$(" + e->param + ')'; | ||
1266 | if (result.contains(needle)) { | 490 | if (result.contains(needle)) { | ||
1267 | QString tmp; | 491 | QString tmp; | ||
1268 | if (e->paramType() == QLatin1String("Enum")) { | 492 | if (e->paramType == QLatin1String("Enum")) { | ||
1269 | tmp = e->paramValues().at(i); | 493 | tmp = e->paramValues.at(i); | ||
1270 | } else { | 494 | } else { | ||
1271 | tmp = QString::number(i); | 495 | tmp = QString::number(i); | ||
1272 | } | 496 | } | ||
1273 | 497 | | |||
1274 | result.replace(needle, tmp); | 498 | result.replace(needle, tmp); | ||
1275 | } | 499 | } | ||
1276 | return result; | 500 | return result; | ||
1277 | } | 501 | } | ||
Show All 13 Lines | 504 | { | |||
1291 | } | 515 | } | ||
1292 | if (arguments.isEmpty()) { | 516 | if (arguments.isEmpty()) { | ||
1293 | return "QStringLiteral( \"" + group + "\" )"; | 517 | return "QStringLiteral( \"" + group + "\" )"; | ||
1294 | } | 518 | } | ||
1295 | 519 | | |||
1296 | return "QStringLiteral( \"" + paramString + "\" )" + arguments; | 520 | return "QStringLiteral( \"" + paramString + "\" )" + arguments; | ||
1297 | } | 521 | } | ||
1298 | 522 | | |||
1299 | QString translatedString(const CfgConfig &cfg, const QString &string, const QString &context = QString(), const QString ¶m = QString(), const QString ¶mValue = QString()) | 523 | QString translatedString(const KConfigXTParameters &cfg, const QString &string, const QString &context, const QString ¶m, const QString ¶mValue) | ||
1300 | { | 524 | { | ||
1301 | QString result; | 525 | QString result; | ||
1302 | 526 | | |||
1303 | switch (cfg.translationSystem) { | 527 | switch (cfg.translationSystem) { | ||
1304 | case CfgConfig::QtTranslation: | 528 | case KConfigXTParameters::QtTranslation: | ||
1305 | if (!context.isEmpty()) { | 529 | if (!context.isEmpty()) { | ||
1306 | result += "/*: " + context + " */ QCoreApplication::translate(\""; | 530 | result += "/*: " + context + " */ QCoreApplication::translate(\""; | ||
1307 | } else { | 531 | } else { | ||
1308 | result += QLatin1String("QCoreApplication::translate(\""); | 532 | result += QLatin1String("QCoreApplication::translate(\""); | ||
1309 | } | 533 | } | ||
1310 | result += cfg.className + "\", "; | 534 | result += cfg.className + "\", "; | ||
1311 | break; | 535 | break; | ||
1312 | 536 | | |||
1313 | case CfgConfig::KdeTranslation: | 537 | case KConfigXTParameters::KdeTranslation: | ||
1314 | if (!cfg.translationDomain.isEmpty() && !context.isEmpty()) { | 538 | if (!cfg.translationDomain.isEmpty() && !context.isEmpty()) { | ||
1315 | result += "i18ndc(" + quoteString(cfg.translationDomain) + ", " + quoteString(context) + ", "; | 539 | result += "i18ndc(" + quoteString(cfg.translationDomain) + ", " + quoteString(context) + ", "; | ||
1316 | } else if (!cfg.translationDomain.isEmpty()) { | 540 | } else if (!cfg.translationDomain.isEmpty()) { | ||
1317 | result += "i18nd(" + quoteString(cfg.translationDomain) + ", "; | 541 | result += "i18nd(" + quoteString(cfg.translationDomain) + ", "; | ||
1318 | } else if (!context.isEmpty()) { | 542 | } else if (!context.isEmpty()) { | ||
1319 | result += "i18nc(" + quoteString(context) + ", "; | 543 | result += "i18nc(" + quoteString(context) + ", "; | ||
1320 | } else { | 544 | } else { | ||
1321 | result += QLatin1String("i18n("); | 545 | result += QLatin1String("i18n("); | ||
Show All 10 Lines | |||||
1332 | } | 556 | } | ||
1333 | 557 | | |||
1334 | result += ')'; | 558 | result += ')'; | ||
1335 | 559 | | |||
1336 | return result; | 560 | return result; | ||
1337 | } | 561 | } | ||
1338 | 562 | | |||
1339 | /* int i is the value of the parameter */ | 563 | /* int i is the value of the parameter */ | ||
1340 | QString userTextsFunctions(CfgEntry *e, const CfgConfig &cfg, QString itemVarStr = QString(), const QString &i = QString()) | 564 | QString userTextsFunctions(CfgEntry *e, const KConfigXTParameters &cfg, QString itemVarStr, const QString &i) | ||
1341 | { | 565 | { | ||
1342 | QString txt; | 566 | QString txt; | ||
1343 | if (itemVarStr.isNull()) { | 567 | if (itemVarStr.isNull()) { | ||
1344 | itemVarStr = itemPath(e, cfg); | 568 | itemVarStr = itemPath(e, cfg); | ||
1345 | } | 569 | } | ||
1346 | if (!e->label().isEmpty()) { | 570 | if (!e->label.isEmpty()) { | ||
1347 | txt += " " + itemVarStr + "->setLabel( "; | 571 | txt += " " + itemVarStr + "->setLabel( "; | ||
1348 | txt += translatedString(cfg, e->label(), e->labelContext(), e->param(), i); | 572 | txt += translatedString(cfg, e->label, e->labelContext, e->param, i); | ||
1349 | txt += QLatin1String(" );\n"); | 573 | txt += QLatin1String(" );\n"); | ||
1350 | } | 574 | } | ||
1351 | if (!e->toolTip().isEmpty()) { | 575 | if (!e->toolTip.isEmpty()) { | ||
1352 | txt += " " + itemVarStr + "->setToolTip( "; | 576 | txt += " " + itemVarStr + "->setToolTip( "; | ||
1353 | txt += translatedString(cfg, e->toolTip(), e->toolTipContext(), e->param(), i); | 577 | txt += translatedString(cfg, e->toolTip, e->toolTipContext, e->param, i); | ||
1354 | txt += QLatin1String(" );\n"); | 578 | txt += QLatin1String(" );\n"); | ||
1355 | } | 579 | } | ||
1356 | if (!e->whatsThis().isEmpty()) { | 580 | if (!e->whatsThis.isEmpty()) { | ||
1357 | txt += " " + itemVarStr + "->setWhatsThis( "; | 581 | txt += " " + itemVarStr + "->setWhatsThis( "; | ||
1358 | txt += translatedString(cfg, e->whatsThis(), e->whatsThisContext(), e->param(), i); | 582 | txt += translatedString(cfg, e->whatsThis, e->whatsThisContext, e->param, i); | ||
1359 | txt += QLatin1String(" );\n"); | 583 | txt += QLatin1String(" );\n"); | ||
1360 | } | 584 | } | ||
1361 | return txt; | 585 | return txt; | ||
1362 | } | 586 | } | ||
1363 | 587 | | |||
1364 | // returns the member accesor implementation | 588 | // returns the member accesor implementation | ||
1365 | // which should go in the h file if inline | 589 | // which should go in the h file if inline | ||
1366 | // or the cpp file if not inline | 590 | // or the cpp file if not inline | ||
1367 | QString memberAccessorBody(CfgEntry *e, bool globalEnums, const CfgConfig &cfg) | 591 | QString memberAccessorBody(CfgEntry *e, bool globalEnums, const KConfigXTParameters &cfg) | ||
1368 | { | 592 | { | ||
1369 | QString result; | 593 | QString result; | ||
1370 | QTextStream out(&result, QIODevice::WriteOnly); | 594 | QTextStream out(&result, QIODevice::WriteOnly); | ||
1371 | QString n = e->name(); | 595 | QString n = e->name; | ||
1372 | QString t = e->type(); | 596 | QString t = e->type; | ||
1373 | bool useEnumType = cfg.useEnumTypes && t == QLatin1String("Enum"); | 597 | bool useEnumType = cfg.useEnumTypes && t == QLatin1String("Enum"); | ||
1374 | 598 | | |||
1375 | out << "return "; | 599 | out << "return "; | ||
1376 | if (useEnumType) { | 600 | if (useEnumType) { | ||
1377 | out << "static_cast<" << enumType(e, globalEnums) << ">("; | 601 | out << "static_cast<" << enumType(e, globalEnums) << ">("; | ||
1378 | } | 602 | } | ||
1379 | out << This << varPath(n, cfg); | 603 | out << This << varPath(n, cfg); | ||
1380 | if (!e->param().isEmpty()) { | 604 | if (!e->param.isEmpty()) { | ||
1381 | out << "[i]"; | 605 | out << "[i]"; | ||
1382 | } | 606 | } | ||
1383 | if (useEnumType) { | 607 | if (useEnumType) { | ||
1384 | out << ")"; | 608 | out << ")"; | ||
1385 | } | 609 | } | ||
1386 | out << ";" << endl; | 610 | out << ";" << endl; | ||
1387 | 611 | | |||
1388 | return result; | 612 | return result; | ||
1389 | } | 613 | } | ||
1390 | 614 | | |||
1391 | // returns the member mutator implementation | 615 | // returns the member mutator implementation | ||
1392 | // which should go in the h file if inline | 616 | // which should go in the h file if inline | ||
1393 | // or the cpp file if not inline | 617 | // or the cpp file if not inline | ||
1394 | 618 | | |||
1395 | void addDebugMethod(QTextStream &out, const CfgConfig &cfg, const QString &n) | 619 | void addDebugMethod(QTextStream &out, const KConfigXTParameters &cfg, const QString &n) | ||
1396 | { | 620 | { | ||
1397 | if (cfg.qCategoryLoggingName.isEmpty()) { | 621 | if (cfg.qCategoryLoggingName.isEmpty()) { | ||
1398 | out << " qDebug() << \"" << setFunction(n); | 622 | out << " qDebug() << \"" << setFunction(n); | ||
1399 | } else { | 623 | } else { | ||
1400 | out << " qCDebug(" << cfg.qCategoryLoggingName << ") << \"" << setFunction(n); | 624 | out << " qCDebug(" << cfg.qCategoryLoggingName << ") << \"" << setFunction(n); | ||
1401 | } | 625 | } | ||
1402 | } | 626 | } | ||
1403 | 627 | | |||
1404 | QString memberMutatorBody(CfgEntry *e, const CfgConfig &cfg) | 628 | QString memberMutatorBody(CfgEntry *e, const KConfigXTParameters &cfg) | ||
1405 | { | 629 | { | ||
1406 | QString result; | 630 | QString result; | ||
1407 | QTextStream out(&result, QIODevice::WriteOnly); | 631 | QTextStream out(&result, QIODevice::WriteOnly); | ||
1408 | QString n = e->name(); | 632 | QString n = e->name; | ||
1409 | QString t = e->type(); | 633 | QString t = e->type; | ||
1410 | 634 | | |||
1411 | if (!e->minValue().isEmpty()) { | 635 | if (!e->min.isEmpty()) { | ||
1412 | if (e->minValue() != QLatin1String("0") || !isUnsigned(t)) { // skip writing "if uint<0" (#187579) | 636 | if (e->min != QLatin1String("0") || !isUnsigned(t)) { // skip writing "if uint<0" (#187579) | ||
1413 | out << "if (v < " << e->minValue() << ")" << endl; | 637 | out << "if (v < " << e->min << ")" << endl; | ||
1414 | out << "{" << endl; | 638 | out << "{" << endl; | ||
1415 | addDebugMethod(out, cfg, n); | 639 | addDebugMethod(out, cfg, n); | ||
1416 | out << ": value \" << v << \" is less than the minimum value of "; | 640 | out << ": value \" << v << \" is less than the minimum value of "; | ||
1417 | out << e->minValue() << "\";" << endl; | 641 | out << e->min << "\";" << endl; | ||
1418 | out << " v = " << e->minValue() << ";" << endl; | 642 | out << " v = " << e->min << ";" << endl; | ||
1419 | out << "}" << endl; | 643 | out << "}" << endl; | ||
1420 | } | 644 | } | ||
1421 | } | 645 | } | ||
1422 | 646 | | |||
1423 | if (!e->maxValue().isEmpty()) { | 647 | if (!e->max.isEmpty()) { | ||
1424 | out << endl << "if (v > " << e->maxValue() << ")" << endl; | 648 | out << endl << "if (v > " << e->max << ")" << endl; | ||
1425 | out << "{" << endl; | 649 | out << "{" << endl; | ||
1426 | addDebugMethod(out, cfg, n); | 650 | addDebugMethod(out, cfg, n); | ||
1427 | out << ": value \" << v << \" is greater than the maximum value of "; | 651 | out << ": value \" << v << \" is greater than the maximum value of "; | ||
1428 | out << e->maxValue() << "\";" << endl; | 652 | out << e->max << "\";" << endl; | ||
1429 | out << " v = " << e->maxValue() << ";" << endl; | 653 | out << " v = " << e->max << ";" << endl; | ||
1430 | out << "}" << endl << endl; | 654 | out << "}" << endl << endl; | ||
1431 | } | 655 | } | ||
1432 | 656 | | |||
1433 | const QString varExpression = This + varPath(n, cfg) + (e->param().isEmpty() ? QString() : QStringLiteral("[i]")); | 657 | const QString varExpression = This + varPath(n, cfg) + (e->param.isEmpty() ? QString() : QStringLiteral("[i]")); | ||
1434 | 658 | | |||
1435 | const bool hasBody = !e->signalList().empty() || cfg.generateProperties; | 659 | const bool hasBody = !e->signalList.empty() || cfg.generateProperties; | ||
1436 | out << "if ("; | 660 | out << "if ("; | ||
1437 | if (hasBody) { | 661 | if (hasBody) { | ||
1438 | out << "v != " << varExpression << " && "; | 662 | out << "v != " << varExpression << " && "; | ||
1439 | } | 663 | } | ||
1440 | out << "!" << This << "isImmutable( QStringLiteral( \""; | 664 | out << "!" << This << "isImmutable( QStringLiteral( \""; | ||
1441 | if (!e->param().isEmpty()) { | 665 | if (!e->param.isEmpty()) { | ||
1442 | out << e->paramName().replace("$(" + e->param() + ")", QLatin1String("%1")) << "\" ).arg( "; | 666 | out << e->paramName.replace("$(" + e->param + ")", QLatin1String("%1")) << "\" ).arg( "; | ||
1443 | if (e->paramType() == QLatin1String("Enum")) { | 667 | if (e->paramType == QLatin1String("Enum")) { | ||
1444 | out << "QLatin1String( "; | 668 | out << "QLatin1String( "; | ||
1445 | 669 | | |||
1446 | if (cfg.globalEnums) { | 670 | if (cfg.globalEnums) { | ||
1447 | out << enumName(e->param()) << "ToString[i]"; | 671 | out << enumName(e->param) << "ToString[i]"; | ||
1448 | } else { | 672 | } else { | ||
1449 | out << enumName(e->param()) << "::enumToString[i]"; | 673 | out << enumName(e->param) << "::enumToString[i]"; | ||
1450 | } | 674 | } | ||
1451 | 675 | | |||
1452 | out << " )"; | 676 | out << " )"; | ||
1453 | } else { | 677 | } else { | ||
1454 | out << "i"; | 678 | out << "i"; | ||
1455 | } | 679 | } | ||
1456 | out << " )"; | 680 | out << " )"; | ||
1457 | } else { | 681 | } else { | ||
1458 | out << n << "\" )"; | 682 | out << n << "\" )"; | ||
1459 | } | 683 | } | ||
1460 | out << " ))" << (hasBody ? " {" : "") << endl; | 684 | out << " ))" << (hasBody ? " {" : "") << endl; | ||
1461 | out << " " << varExpression << " = v;" << endl; | 685 | out << " " << varExpression << " = v;" << endl; | ||
1462 | 686 | | |||
1463 | const auto listSignal = e->signalList(); | 687 | const auto listSignal = e->signalList; | ||
1464 | for (const Signal &signal : listSignal) { | 688 | for (const Signal &signal : listSignal) { | ||
1465 | if (signal.modify) { | 689 | if (signal.modify) { | ||
1466 | out << " Q_EMIT " << This << signal.name << "();" << endl; | 690 | out << " Q_EMIT " << This << signal.name << "();" << endl; | ||
1467 | } else { | 691 | } else { | ||
1468 | out << " " << This << varPath(QStringLiteral("settingsChanged"), cfg) << " |= " << signalEnumName(signal.name) << ";" << endl; | 692 | out << " " << This << varPath(QStringLiteral("settingsChanged"), cfg) << " |= " << signalEnumName(signal.name) << ";" << endl; | ||
1469 | } | 693 | } | ||
1470 | } | 694 | } | ||
1471 | if (hasBody) { | 695 | if (hasBody) { | ||
1472 | out << "}" << endl; | 696 | out << "}" << endl; | ||
1473 | } | 697 | } | ||
1474 | 698 | | |||
1475 | return result; | 699 | return result; | ||
1476 | } | 700 | } | ||
1477 | 701 | | |||
1478 | // returns the member get default implementation | 702 | // returns the member get default implementation | ||
1479 | // which should go in the h file if inline | 703 | // which should go in the h file if inline | ||
1480 | // or the cpp file if not inline | 704 | // or the cpp file if not inline | ||
1481 | QString memberGetDefaultBody(CfgEntry *e) | 705 | QString memberGetDefaultBody(CfgEntry *e) | ||
1482 | { | 706 | { | ||
1483 | QString result = e->code(); | 707 | QString result = e->code; | ||
1484 | QTextStream out(&result, QIODevice::WriteOnly); | 708 | QTextStream out(&result, QIODevice::WriteOnly); | ||
1485 | out << endl; | 709 | out << endl; | ||
1486 | 710 | | |||
1487 | if (!e->param().isEmpty()) { | 711 | if (!e->param.isEmpty()) { | ||
1488 | out << " switch (i) {" << endl; | 712 | out << " switch (i) {" << endl; | ||
1489 | for (int i = 0; i <= e->paramMax(); ++i) { | 713 | for (int i = 0; i <= e->paramMax; ++i) { | ||
1490 | if (!e->paramDefaultValue(i).isEmpty()) { | 714 | if (!e->paramDefaultValues[i].isEmpty()) { | ||
1491 | out << " case " << i << ": return " << e->paramDefaultValue(i) << ';' << endl; | 715 | out << " case " << i << ": return " << e->paramDefaultValues[i] << ';' << endl; | ||
1492 | } | 716 | } | ||
1493 | } | 717 | } | ||
1494 | out << " default:" << endl; | 718 | out << " default:" << endl; | ||
1495 | out << " return " << e->defaultValue().replace("$(" + e->param() + ')', QLatin1String("i")) << ';' << endl; | 719 | out << " return " << e->defaultValue.replace("$(" + e->param + ')', QLatin1String("i")) << ';' << endl; | ||
1496 | out << " }" << endl; | 720 | out << " }" << endl; | ||
1497 | } else { | 721 | } else { | ||
1498 | out << " return " << e->defaultValue() << ';'; | 722 | out << " return " << e->defaultValue << ';'; | ||
1499 | } | 723 | } | ||
1500 | 724 | | |||
1501 | return result; | 725 | return result; | ||
1502 | } | 726 | } | ||
1503 | 727 | | |||
1504 | // returns the item accesor implementation | 728 | // returns the item accesor implementation | ||
1505 | // which should go in the h file if inline | 729 | // which should go in the h file if inline | ||
1506 | // or the cpp file if not inline | 730 | // or the cpp file if not inline | ||
1507 | QString itemAccessorBody(CfgEntry *e, const CfgConfig &cfg) | 731 | QString itemAccessorBody(CfgEntry *e, const KConfigXTParameters &cfg) | ||
1508 | { | 732 | { | ||
1509 | QString result; | 733 | QString result; | ||
1510 | QTextStream out(&result, QIODevice::WriteOnly); | 734 | QTextStream out(&result, QIODevice::WriteOnly); | ||
1511 | 735 | | |||
1512 | out << "return " << itemPath(e, cfg); | 736 | out << "return " << itemPath(e, cfg); | ||
1513 | if (!e->param().isEmpty()) { | 737 | if (!e->param.isEmpty()) { | ||
1514 | out << "[i]"; | 738 | out << "[i]"; | ||
1515 | } | 739 | } | ||
1516 | out << ";" << endl; | 740 | out << ";" << endl; | ||
1517 | 741 | | |||
1518 | return result; | 742 | return result; | ||
1519 | } | 743 | } | ||
1520 | 744 | | |||
1521 | //indents text adding X spaces per line | 745 | //indents text adding X spaces per line | ||
Show All 9 Lines | 754 | if (!currLine.isEmpty()) | |||
1531 | for (int i = 0; i < spaces; i++) { | 755 | for (int i = 0; i < spaces; i++) { | ||
1532 | out << " "; | 756 | out << " "; | ||
1533 | } | 757 | } | ||
1534 | out << currLine << endl; | 758 | out << currLine << endl; | ||
1535 | } | 759 | } | ||
1536 | return result; | 760 | return result; | ||
1537 | } | 761 | } | ||
1538 | 762 | | |||
1539 | // adds as many 'namespace foo {' lines to p_out as | 763 | bool hasErrors(KCFGXmlParser &parser, const ParseResult& parseResult, const KConfigXTParameters &cfg) | ||
ervin: Space before & not after | |||||
1540 | // there are namespaces in p_ns | | |||
1541 | void beginNamespaces(const QString &p_ns, QTextStream &p_out) | | |||
1542 | { | 764 | { | ||
1543 | if (!p_ns.isEmpty()) { | 765 | if (!parser.errorString().isEmpty()) { | ||
1544 | const QStringList nameSpaces = p_ns.split(QStringLiteral("::")); | 766 | cerr << parser.errorString(); | ||
1545 | for (const QString &ns : nameSpaces) { | 767 | return true; | ||
1546 | p_out << "namespace " << ns << " {" << endl; | | |||
1547 | } | | |||
1548 | p_out << endl; | | |||
1549 | } | | |||
1550 | } | 768 | } | ||
1551 | 769 | | |||
1552 | // adds as many '}' lines to p_out as | 770 | if (cfg.className.isEmpty()) { | ||
1553 | // there are namespaces in p_ns | 771 | cerr << "Class name missing" << endl; | ||
1554 | void endNamespaces(const QString &p_ns, QTextStream &p_out) | 772 | return true; | ||
1555 | { | | |||
1556 | if (!p_ns.isEmpty()) { | | |||
1557 | const int namespaceCount = p_ns.count(QStringLiteral("::")) + 1; | | |||
1558 | for (int i = 0; i < namespaceCount; ++i) { | | |||
1559 | p_out << "}" << endl; | | |||
1560 | } | | |||
1561 | p_out << endl; | | |||
1562 | } | 773 | } | ||
774 | | ||||
775 | if (cfg.singleton && !parseResult.parameters.isEmpty()) { | ||||
776 | cerr << "Singleton class can not have parameters" << endl; | ||||
777 | return true; | ||||
778 | } | ||||
779 | | ||||
780 | if (!parseResult.cfgFileName.isEmpty() && parseResult.cfgFileNameArg) { | ||||
781 | cerr << "Having both a fixed filename and a filename as argument is not possible." << endl; | ||||
782 | return true; | ||||
783 | } | ||||
784 | | ||||
785 | if (parseResult.entries.isEmpty()) { | ||||
786 | cerr << "No entries." << endl; | ||||
787 | return true; | ||||
788 | } | ||||
789 | | ||||
790 | return false; | ||||
1563 | } | 791 | } | ||
1564 | 792 | | |||
1565 | int main(int argc, char **argv) | 793 | int main(int argc, char **argv) | ||
1566 | { | 794 | { | ||
1567 | QCoreApplication app(argc, argv); | 795 | QCoreApplication app(argc, argv); | ||
1568 | app.setApplicationName(QStringLiteral("kconfig_compiler")); | 796 | app.setApplicationName(QStringLiteral("kconfig_compiler")); | ||
1569 | app.setApplicationVersion(QStringLiteral(KCONFIG_VERSION_STRING)); | 797 | app.setApplicationVersion(QStringLiteral(KCONFIG_VERSION_STRING)); | ||
1570 | 798 | | |||
Show All 28 Lines | 821 | cout << "Copyright 2003 Cornelius Schumacher, Waldo Bastian, Zack Rusin," << endl; | |||
1599 | return 0; | 827 | return 0; | ||
1600 | } | 828 | } | ||
1601 | 829 | | |||
1602 | const QStringList args = parser.positionalArguments(); | 830 | const QStringList args = parser.positionalArguments(); | ||
1603 | if (args.count() < 2) { | 831 | if (args.count() < 2) { | ||
1604 | cerr << "Too few arguments." << endl; | 832 | cerr << "Too few arguments." << endl; | ||
1605 | return 1; | 833 | return 1; | ||
1606 | } | 834 | } | ||
835 | | ||||
1607 | if (args.count() > 2) { | 836 | if (args.count() > 2) { | ||
1608 | cerr << "Too many arguments." << endl; | 837 | cerr << "Too many arguments." << endl; | ||
1609 | return 1; | 838 | return 1; | ||
1610 | } | 839 | } | ||
1611 | inputFilename = args.at(0); | 840 | inputFilename = args.at(0); | ||
1612 | codegenFilename = args.at(1); | 841 | codegenFilename = args.at(1); | ||
1613 | 842 | | |||
843 | // TODO: Transform baseDir into a helper. | ||||
1614 | QString baseDir = parser.value(targetDirectoryOption); | 844 | QString baseDir = parser.value(targetDirectoryOption); | ||
1615 | 845 | | |||
1616 | #ifdef Q_OS_WIN | 846 | #ifdef Q_OS_WIN | ||
1617 | if (!baseDir.endsWith('/') && !baseDir.endsWith('\\')) | 847 | if (!baseDir.endsWith('/') && !baseDir.endsWith('\\')) | ||
1618 | #else | 848 | #else | ||
1619 | if (!baseDir.endsWith('/')) | 849 | if (!baseDir.endsWith('/')) | ||
1620 | #endif | 850 | #endif | ||
1621 | baseDir.append("/"); | 851 | baseDir.append("/"); | ||
1622 | 852 | | |||
1623 | if (!codegenFilename.endsWith(QLatin1String(".kcfgc"))) { | 853 | KConfigXTParameters cfg = KConfigXTParameters(codegenFilename); | ||
dfaure: it's shorter and simpler to write KConfigXTParameters cfg(codegenFilename);
| |||||
dfaure: const ... ? | |||||
that was a bit harder than I want, but done. Inside of the code generation there was code that manipulated the ParseResult. I think this is one of the good spots that show that this rewrite is really needed. tcanabrava: that was a bit harder than I want, but done. Inside of the code generation there was code that… | |||||
aaaaaand no, this introduced regressions, I'll try to solve it later but it's not as simple. this will unfortunately still be modified inside of the generator files. :/ tcanabrava: aaaaaand no, this introduced regressions, I'll try to solve it later but it's not as simple. | |||||
1624 | cerr << "Codegen options file must have extension .kcfgc" << endl; | 854 | KCFGXmlParser xmlParser; | ||
dfaure: ^ | |||||
1625 | return 1; | | |||
1626 | } | | |||
1627 | QString baseName = QFileInfo(codegenFilename).fileName(); | | |||
1628 | baseName = baseName.left(baseName.length() - 6); | | |||
1629 | | ||||
1630 | CfgConfig cfg = CfgConfig(codegenFilename); | | |||
1631 | | ||||
1632 | QFile input(inputFilename); | | |||
1633 | | ||||
1634 | QDomDocument doc; | | |||
1635 | QString errorMsg; | | |||
1636 | int errorRow; | | |||
1637 | int errorCol; | | |||
1638 | if (!doc.setContent(&input, &errorMsg, &errorRow, &errorCol)) { | | |||
1639 | cerr << "Unable to load document." << endl; | | |||
1640 | cerr << "Parse error in " << inputFilename << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl; | | |||
1641 | return 1; | | |||
1642 | } | | |||
1643 | | ||||
1644 | QDomElement cfgElement = doc.documentElement(); | | |||
1645 | | ||||
1646 | if (cfgElement.isNull()) { | | |||
1647 | cerr << "No document in kcfg file" << endl; | | |||
1648 | return 1; | | |||
1649 | } | | |||
1650 | | ||||
1651 | QString cfgFileName; | | |||
1652 | bool cfgFileNameArg = false; | | |||
1653 | QList<Param> parameters; | | |||
1654 | QList<Signal> signalList; | | |||
1655 | QStringList includes; | | |||
1656 | | ||||
1657 | QList<CfgEntry *> entries; | | |||
1658 | | ||||
1659 | for (QDomElement e = cfgElement.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) { | | |||
1660 | QString tag = e.tagName(); | | |||
1661 | | ||||
1662 | if (tag == QLatin1String("include")) { | | |||
1663 | QString includeFile = e.text(); | | |||
1664 | if (!includeFile.isEmpty()) { | | |||
1665 | includes.append(includeFile); | | |||
1666 | } | | |||
1667 | | ||||
1668 | } else if (tag == QLatin1String("kcfgfile")) { | | |||
1669 | cfgFileName = e.attribute(QStringLiteral("name")); | | |||
1670 | cfgFileNameArg = e.attribute(QStringLiteral("arg")).toLower() == QLatin1String("true"); | | |||
1671 | for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) { | | |||
1672 | if (e2.tagName() == QLatin1String("parameter")) { | | |||
1673 | Param p; | | |||
1674 | p.name = e2.attribute(QStringLiteral("name")); | | |||
1675 | p.type = e2.attribute(QStringLiteral("type")); | | |||
1676 | if (p.type.isEmpty()) { | | |||
1677 | p.type = QStringLiteral("String"); | | |||
1678 | } | | |||
1679 | parameters.append(p); | | |||
1680 | } | | |||
1681 | } | | |||
1682 | | ||||
1683 | } else if (tag == QLatin1String("group")) { | | |||
1684 | QString group = e.attribute(QStringLiteral("name")); | | |||
1685 | if (group.isEmpty()) { | | |||
1686 | cerr << "Group without name" << endl; | | |||
1687 | return 1; | | |||
1688 | } | | |||
1689 | for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) { | | |||
1690 | if (e2.tagName() != QLatin1String("entry")) { | | |||
1691 | continue; | | |||
1692 | } | | |||
1693 | CfgEntry *entry = parseEntry(group, e2, cfg); | | |||
1694 | if (entry) { | | |||
1695 | entries.append(entry); | | |||
1696 | } else { | | |||
1697 | cerr << "Can not parse entry." << endl; | | |||
1698 | return 1; | | |||
1699 | } | | |||
1700 | } | | |||
1701 | } else if (tag == QLatin1String("signal")) { | | |||
1702 | QString signalName = e.attribute(QStringLiteral("name")); | | |||
1703 | if (signalName.isEmpty()) { | | |||
1704 | cerr << "Signal without name." << endl; | | |||
1705 | return 1; | | |||
1706 | } | | |||
1707 | Signal theSignal; | | |||
1708 | theSignal.name = signalName; | | |||
1709 | | ||||
1710 | for (QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement()) { | | |||
1711 | if (e2.tagName() == QLatin1String("argument")) { | | |||
1712 | SignalArguments argument; | | |||
1713 | argument.type = e2.attribute(QStringLiteral("type")); | | |||
1714 | if (argument.type.isEmpty()) { | | |||
1715 | cerr << "Signal argument without type." << endl; | | |||
1716 | return 1; | | |||
1717 | } | | |||
1718 | argument.variableName = e2.text(); | | |||
1719 | theSignal.arguments.append(argument); | | |||
1720 | } else if (e2.tagName() == QLatin1String("label")) { | | |||
1721 | theSignal.label = e2.text(); | | |||
1722 | } | | |||
1723 | } | | |||
1724 | signalList.append(theSignal); | | |||
1725 | } | | |||
1726 | } | | |||
1727 | | ||||
1728 | if (cfg.className.isEmpty()) { | | |||
1729 | cerr << "Class name missing" << endl; | | |||
1730 | return 1; | | |||
1731 | } | | |||
1732 | | ||||
1733 | if (cfg.singleton && !parameters.isEmpty()) { | | |||
1734 | cerr << "Singleton class can not have parameters" << endl; | | |||
1735 | return 1; | | |||
1736 | } | | |||
1737 | | ||||
1738 | if (!cfgFileName.isEmpty() && cfgFileNameArg) { | | |||
1739 | cerr << "Having both a fixed filename and a filename as argument is not possible." << endl; | | |||
1740 | return 1; | | |||
1741 | } | | |||
1742 | | ||||
1743 | if (entries.isEmpty()) { | | |||
1744 | cerr << "No entries." << endl; | | |||
1745 | } | | |||
1746 | | ||||
1747 | #if 0 | | |||
1748 | CfgEntry *cfg; | | |||
1749 | for (cfg = entries.first(); cfg; cfg = entries.next()) { | | |||
1750 | cfg->dump(); | | |||
1751 | } | | |||
1752 | #endif | | |||
1753 | | ||||
1754 | QString headerFileName = baseName + '.' + cfg.headerExtension; | | |||
1755 | QString implementationFileName = baseName + '.' + cfg.sourceExtension; | | |||
1756 | QString mocFileName = baseName + ".moc"; | | |||
1757 | QString cppPreamble; // code to be inserted at the beginnin of the cpp file, e.g. initialization of static values | | |||
1758 | | ||||
1759 | QFile header(baseDir + headerFileName); | | |||
1760 | if (!header.open(QIODevice::WriteOnly)) { | | |||
1761 | cerr << "Can not open '" << baseDir << headerFileName << "for writing." << endl; | | |||
1762 | return 1; | | |||
1763 | } | | |||
1764 | | ||||
1765 | QTextStream h(&header); | | |||
1766 | | ||||
1767 | h.setCodec("utf-8"); | | |||
1768 | | ||||
1769 | h << "// This file is generated by kconfig_compiler_kf5 from " << QFileInfo(inputFilename).fileName() << "." << endl; | | |||
1770 | h << "// All changes you do to this file will be lost." << endl; | | |||
1771 | | ||||
1772 | h << "#ifndef " << (!cfg.nameSpace.isEmpty() ? QString(QString(cfg.nameSpace).replace(QLatin1String("::"), QLatin1String("_")).toUpper() + '_') : QLatin1String("")) | | |||
1773 | << cfg.className.toUpper() << "_H" << endl; | | |||
1774 | h << "#define " << (!cfg.nameSpace.isEmpty() ? QString(QString(cfg.nameSpace).replace(QLatin1String("::"), QLatin1String("_")).toUpper() + '_') : QLatin1String("")) | | |||
1775 | << cfg.className.toUpper() << "_H" << endl << endl; | | |||
1776 | | ||||
1777 | // Includes | | |||
1778 | QStringList::ConstIterator it; | | |||
1779 | for (it = cfg.headerIncludes.constBegin(); it != cfg.headerIncludes.constEnd(); ++it) { | | |||
1780 | if ((*it).startsWith('"')) { | | |||
1781 | h << "#include " << *it << endl; | | |||
1782 | } else { | | |||
1783 | h << "#include <" << *it << ">" << endl; | | |||
1784 | } | | |||
1785 | } | | |||
1786 | | ||||
1787 | if (!cfg.headerIncludes.isEmpty()) { | | |||
1788 | h << endl; | | |||
1789 | } | | |||
1790 | | ||||
1791 | if (!cfg.singleton && parameters.isEmpty()) { | | |||
1792 | h << "#include <qglobal.h>" << endl; | | |||
1793 | } | | |||
1794 | | ||||
1795 | if (cfg.inherits == QLatin1String("KCoreConfigSkeleton")) { | | |||
1796 | h << "#include <kcoreconfigskeleton.h>" << endl; | | |||
1797 | } else { | | |||
1798 | h << "#include <kconfigskeleton.h>" << endl; | | |||
1799 | } | | |||
1800 | | ||||
1801 | h << "#include <QCoreApplication>" << endl; | | |||
1802 | h << "#include <QDebug>" << endl << endl; | | |||
1803 | | ||||
1804 | // Includes | | |||
1805 | for (it = includes.constBegin(); it != includes.constEnd(); ++it) { | | |||
1806 | if ((*it).startsWith('"')) { | | |||
1807 | h << "#include " << *it << endl; | | |||
1808 | } else { | | |||
1809 | h << "#include <" << *it << ">" << endl; | | |||
1810 | } | | |||
1811 | } | | |||
1812 | | ||||
1813 | beginNamespaces(cfg.nameSpace, h); | | |||
1814 | | ||||
1815 | // Private class declaration | | |||
1816 | if (cfg.dpointer) { | | |||
1817 | h << "class " << cfg.className << "Private;" << endl << endl; | | |||
1818 | } | | |||
1819 | | ||||
1820 | // Class declaration header | | |||
1821 | h << "class " << cfg.visibility << cfg.className << " : public " << cfg.inherits << endl; | | |||
1822 | | ||||
1823 | h << "{" << endl; | | |||
1824 | // Add Q_OBJECT macro if the config need signals. | | |||
1825 | if (!signalList.isEmpty() || cfg.generateProperties) { | | |||
1826 | h << " Q_OBJECT" << endl; | | |||
1827 | } | | |||
1828 | h << " public:" << endl; | | |||
1829 | | ||||
1830 | // enums | | |||
1831 | QList<CfgEntry *>::ConstIterator itEntry; | | |||
1832 | for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { | | |||
1833 | const CfgEntry::Choices &choices = (*itEntry)->choices(); | | |||
1834 | const QList<CfgEntry::Choice> chlist = choices.choices; | | |||
1835 | if (!chlist.isEmpty()) { | | |||
1836 | QStringList values; | | |||
1837 | QList<CfgEntry::Choice>::ConstIterator itChoice; | | |||
1838 | for (itChoice = chlist.constBegin(); itChoice != chlist.constEnd(); ++itChoice) { | | |||
1839 | values.append(choices.prefix + (*itChoice).name); | | |||
1840 | } | | |||
1841 | if (choices.name().isEmpty()) { | | |||
1842 | if (cfg.globalEnums) { | | |||
1843 | h << " enum " << enumName((*itEntry)->name(), (*itEntry)->choices()) << " { " << values.join(QStringLiteral(", ")) << " };" << endl; | | |||
1844 | } else { | | |||
1845 | // Create an automatically named enum | | |||
1846 | h << " class " << enumName((*itEntry)->name(), (*itEntry)->choices()) << endl; | | |||
1847 | h << " {" << endl; | | |||
1848 | h << " public:" << endl; | | |||
1849 | h << " enum type { " << values.join(QStringLiteral(", ")) << ", COUNT };" << endl; | | |||
1850 | h << " };" << endl; | | |||
1851 | } | | |||
1852 | } else if (!choices.external()) { | | |||
1853 | // Create a named enum | | |||
1854 | h << " enum " << enumName((*itEntry)->name(), (*itEntry)->choices()) << " { " << values.join(QStringLiteral(", ")) << " };" << endl; | | |||
1855 | } | | |||
1856 | } | | |||
1857 | const QStringList values = (*itEntry)->paramValues(); | | |||
1858 | if (!values.isEmpty()) { | | |||
1859 | if (cfg.globalEnums) { | | |||
1860 | // ### FIXME!! | | |||
1861 | // make the following string table an index-based string search! | | |||
1862 | // ### | | |||
1863 | h << " enum " << enumName((*itEntry)->param()) << " { " << values.join(QStringLiteral(", ")) << " };" << endl; | | |||
1864 | h << " static const char* const " << enumName((*itEntry)->param()) << "ToString[];" << endl; | | |||
1865 | cppPreamble += "const char* const " + cfg.className + "::" + enumName((*itEntry)->param()) + | | |||
1866 | "ToString[] = { \"" + values.join(QStringLiteral("\", \"")) + "\" };\n"; | | |||
1867 | } else { | | |||
1868 | h << " class " << enumName((*itEntry)->param()) << endl; | | |||
1869 | h << " {" << endl; | | |||
1870 | h << " public:" << endl; | | |||
1871 | h << " enum type { " << values.join(QStringLiteral(", ")) << ", COUNT };" << endl; | | |||
1872 | h << " static const char* const enumToString[];" << endl; | | |||
1873 | h << " };" << endl; | | |||
1874 | cppPreamble += "const char* const " + cfg.className + "::" + enumName((*itEntry)->param()) + | | |||
1875 | "::enumToString[] = { \"" + values.join(QStringLiteral("\", \"")) + "\" };\n"; | | |||
1876 | } | | |||
1877 | } | | |||
1878 | } | | |||
1879 | h << endl; | | |||
1880 | | ||||
1881 | | ||||
1882 | // Constructor or singleton accessor | | |||
1883 | if (!cfg.singleton) { | | |||
1884 | h << " " << cfg.className << "("; | | |||
1885 | if (cfgFileNameArg) { | | |||
1886 | if (cfg.forceStringFilename) | | |||
1887 | h << " const QString &cfgfilename" | | |||
1888 | << (parameters.isEmpty() ? " = QString()" : ", "); | | |||
1889 | else | | |||
1890 | h << " KSharedConfig::Ptr config" | | |||
1891 | << (parameters.isEmpty() ? " = KSharedConfig::openConfig()" : ", "); | | |||
1892 | } | | |||
1893 | for (QList<Param>::ConstIterator it = parameters.constBegin(); | | |||
1894 | it != parameters.constEnd(); ++it) { | | |||
1895 | if (it != parameters.constBegin()) { | | |||
1896 | h << ","; | | |||
1897 | } | | |||
1898 | h << " " << param((*it).type) << " " << (*it).name; | | |||
1899 | } | | |||
1900 | if (cfg.parentInConstructor) { | | |||
1901 | if (cfgFileNameArg || !parameters.isEmpty()) { | | |||
1902 | h << ","; | | |||
1903 | } | | |||
1904 | h << " QObject *parent = nullptr"; | | |||
1905 | } | | |||
1906 | h << " );" << endl; | | |||
1907 | } else { | | |||
1908 | h << " static " << cfg.className << " *self();" << endl; | | |||
1909 | if (cfgFileNameArg) { | | |||
1910 | h << " static void instance(const QString& cfgfilename);" << endl; | | |||
1911 | h << " static void instance(KSharedConfig::Ptr config);" << endl; | | |||
1912 | } | | |||
1913 | } | | |||
1914 | | ||||
1915 | // Destructor | | |||
1916 | h << " ~" << cfg.className << "();" << endl << endl; | | |||
1917 | | ||||
1918 | // global variables | | |||
1919 | if (cfg.staticAccessors) { | | |||
1920 | This = QStringLiteral("self()->"); | | |||
1921 | } else { | | |||
1922 | Const = QStringLiteral(" const"); | | |||
1923 | } | | |||
1924 | | ||||
1925 | for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { | | |||
1926 | QString n = (*itEntry)->name(); | | |||
1927 | QString t = (*itEntry)->type(); | | |||
1928 | | ||||
1929 | // Manipulator | | |||
1930 | if (cfg.allMutators || cfg.mutators.contains(n)) { | | |||
1931 | h << " /**" << endl; | | |||
1932 | h << " Set " << (*itEntry)->label() << endl; | | |||
1933 | h << " */" << endl; | | |||
1934 | if (cfg.staticAccessors) { | | |||
1935 | h << " static" << endl; | | |||
1936 | } | | |||
1937 | h << " void " << setFunction(n) << "( "; | | |||
1938 | if (!(*itEntry)->param().isEmpty()) { | | |||
1939 | h << cppType((*itEntry)->paramType()) << " i, "; | | |||
1940 | } | | |||
1941 | if (cfg.useEnumTypes && t == QLatin1String("Enum")) { | | |||
1942 | h << enumType(*itEntry, cfg.globalEnums); | | |||
1943 | } else { | | |||
1944 | h << param(t); | | |||
1945 | } | | |||
1946 | h << " v )"; | | |||
1947 | // function body inline only if not using dpointer | | |||
1948 | // for BC mode | | |||
1949 | if (!cfg.dpointer) { | | |||
1950 | h << endl << " {" << endl; | | |||
1951 | h << indent(memberMutatorBody(*itEntry, cfg), 6); | | |||
1952 | h << " }" << endl; | | |||
1953 | } else { | | |||
1954 | h << ";" << endl; | | |||
1955 | } | | |||
1956 | } | | |||
1957 | h << endl; | | |||
1958 | | ||||
1959 | QString returnType; | | |||
1960 | if (cfg.useEnumTypes && t == QLatin1String("Enum")) { | | |||
1961 | returnType = enumType(*itEntry, cfg.globalEnums); | | |||
1962 | } else { | | |||
1963 | returnType = cppType(t); | | |||
1964 | } | | |||
1965 | | ||||
1966 | if (cfg.generateProperties) { | | |||
1967 | h << " Q_PROPERTY(" << returnType << ' ' << getFunction(n); | | |||
1968 | h << " READ " << getFunction(n); | | |||
1969 | if (cfg.allMutators || cfg.mutators.contains(n)) { | | |||
1970 | const QString signal = changeSignalName(n); | | |||
1971 | h << " WRITE " << setFunction(n); | | |||
1972 | h << " NOTIFY " << signal; | | |||
1973 | | ||||
1974 | //If we have the modified signal, we'll also need | | |||
1975 | //the changed signal as well | | |||
1976 | Signal s; | | |||
1977 | s.name = signal; | | |||
1978 | s.modify = true; | | |||
1979 | signalList.append(s); | | |||
1980 | } else { | | |||
1981 | h << " CONSTANT"; | | |||
1982 | } | | |||
1983 | h << ")" << endl; | | |||
1984 | } | | |||
1985 | // Accessor | | |||
1986 | h << " /**" << endl; | | |||
1987 | h << " Get " << (*itEntry)->label() << endl; | | |||
1988 | h << " */" << endl; | | |||
1989 | if (cfg.staticAccessors) { | | |||
1990 | h << " static" << endl; | | |||
1991 | } | | |||
1992 | h << " "; | | |||
1993 | h << returnType; | | |||
1994 | h << " " << getFunction(n) << "("; | | |||
1995 | if (!(*itEntry)->param().isEmpty()) { | | |||
1996 | h << " " << cppType((*itEntry)->paramType()) << " i "; | | |||
1997 | } | | |||
1998 | h << ")" << Const; | | |||
1999 | // function body inline only if not using dpointer | | |||
2000 | // for BC mode | | |||
2001 | if (!cfg.dpointer) { | | |||
2002 | h << endl << " {" << endl; | | |||
2003 | h << indent(memberAccessorBody(*itEntry, cfg.globalEnums, cfg), 6); | | |||
2004 | h << " }" << endl; | | |||
2005 | } else { | | |||
2006 | h << ";" << endl; | | |||
2007 | } | | |||
2008 | | ||||
2009 | // Default value Accessor | | |||
2010 | if ((cfg.allDefaultGetters || cfg.defaultGetters.contains(n)) && !(*itEntry)->defaultValue().isEmpty()) { | | |||
2011 | h << endl; | | |||
2012 | h << " /**" << endl; | | |||
2013 | h << " Get " << (*itEntry)->label() << " default value" << endl; | | |||
2014 | h << " */" << endl; | | |||
2015 | if (cfg.staticAccessors) { | | |||
2016 | h << " static" << endl; | | |||
2017 | } | | |||
2018 | h << " "; | | |||
2019 | if (cfg.useEnumTypes && t == QLatin1String("Enum")) { | | |||
2020 | h << enumType(*itEntry, cfg.globalEnums); | | |||
2021 | } else { | | |||
2022 | h << cppType(t); | | |||
2023 | } | | |||
2024 | h << " " << getDefaultFunction(n) << "("; | | |||
2025 | if (!(*itEntry)->param().isEmpty()) { | | |||
2026 | h << " " << cppType((*itEntry)->paramType()) << " i "; | | |||
2027 | } | | |||
2028 | h << ")" << Const << endl; | | |||
2029 | h << " {" << endl; | | |||
2030 | h << " return "; | | |||
2031 | if (cfg.useEnumTypes && t == QLatin1String("Enum")) { | | |||
2032 | h << "static_cast<" << enumType(*itEntry, cfg.globalEnums) << ">("; | | |||
2033 | } | | |||
2034 | h << getDefaultFunction(n) << "_helper("; | | |||
2035 | if (!(*itEntry)->param().isEmpty()) { | | |||
2036 | h << " i "; | | |||
2037 | } | | |||
2038 | h << ")"; | | |||
2039 | if (cfg.useEnumTypes && t == QLatin1String("Enum")) { | | |||
2040 | h << ")"; | | |||
2041 | } | | |||
2042 | h << ";" << endl; | | |||
2043 | h << " }" << endl; | | |||
2044 | } | | |||
2045 | | ||||
2046 | // Item accessor | | |||
2047 | if (cfg.itemAccessors) { | | |||
2048 | h << endl; | | |||
2049 | h << " /**" << endl; | | |||
2050 | h << " Get Item object corresponding to " << n << "()" | | |||
2051 | << endl; | | |||
2052 | h << " */" << endl; | | |||
2053 | h << " Item" << itemType((*itEntry)->type()) << " *" | | |||
2054 | << getFunction(n) << "Item("; | | |||
2055 | if (!(*itEntry)->param().isEmpty()) { | | |||
2056 | h << " " << cppType((*itEntry)->paramType()) << " i "; | | |||
2057 | } | | |||
2058 | h << ")"; | | |||
2059 | if (!cfg.dpointer) { | | |||
2060 | h << endl << " {" << endl; | | |||
2061 | h << indent(itemAccessorBody((*itEntry), cfg), 6); | | |||
2062 | h << " }" << endl; | | |||
2063 | } else { | | |||
2064 | h << ";" << endl; | | |||
2065 | } | | |||
2066 | } | | |||
2067 | | ||||
2068 | h << endl; | | |||
2069 | } | | |||
2070 | | ||||
2071 | // Signal definition. | | |||
2072 | const bool hasSignals = !signalList.isEmpty(); | | |||
2073 | bool hasNonModifySignals = false; | | |||
2074 | if (hasSignals) { | | |||
2075 | h << "\n enum {" << endl; | | |||
2076 | unsigned val = 1; | | |||
2077 | QList<Signal>::ConstIterator it, itEnd = signalList.constEnd(); | | |||
2078 | for (it = signalList.constBegin(); it != itEnd; val <<= 1) { | | |||
2079 | hasNonModifySignals |= !it->modify; | | |||
2080 | if (!val) { | | |||
2081 | cerr << "Too many signals to create unique bit masks" << endl; | | |||
2082 | exit(1); | | |||
2083 | } | | |||
2084 | Signal signal = *it; | | |||
2085 | h << " " << signalEnumName(signal.name) << " = 0x" << hex << val; | | |||
2086 | if (++it != itEnd) { | | |||
2087 | h << ","; | | |||
2088 | } | | |||
2089 | h << endl; | | |||
2090 | } | | |||
2091 | h << " };" << dec << endl << endl; | | |||
2092 | | ||||
2093 | h << " Q_SIGNALS:"; | | |||
2094 | for (const Signal &signal : qAsConst(signalList)) { | | |||
2095 | h << endl; | | |||
2096 | if (!signal.label.isEmpty()) { | | |||
2097 | h << " /**" << endl; | | |||
2098 | h << " " << signal.label << endl; | | |||
2099 | h << " */" << endl; | | |||
2100 | } | | |||
2101 | h << " void " << signal.name << "("; | | |||
2102 | QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd(); | | |||
2103 | for (it = signal.arguments.constBegin(); it != itEnd;) { | | |||
2104 | SignalArguments argument = *it; | | |||
2105 | QString type = param(argument.type); | | |||
2106 | if (cfg.useEnumTypes && argument.type == QLatin1String("Enum")) { | | |||
2107 | for (int i = 0, end = entries.count(); i < end; ++i) { | | |||
2108 | if (entries[i]->name() == argument.variableName) { | | |||
2109 | type = enumType(entries[i], cfg.globalEnums); | | |||
2110 | break; | | |||
2111 | } | | |||
2112 | } | | |||
2113 | } | | |||
2114 | h << type << " " << argument.variableName; | | |||
2115 | if (++it != itEnd) { | | |||
2116 | h << ", "; | | |||
2117 | } | | |||
2118 | } | | |||
2119 | h << ");" << endl; | | |||
2120 | } | | |||
2121 | h << endl; | | |||
2122 | | ||||
2123 | h << " private:" << endl; | | |||
2124 | h << " void itemChanged(quint64 flags);" << endl; | | |||
2125 | h << endl; | | |||
2126 | } | | |||
2127 | | ||||
2128 | h << " protected:" << endl; | | |||
2129 | | ||||
2130 | // Private constructor for singleton | | |||
2131 | if (cfg.singleton) { | | |||
2132 | h << " " << cfg.className << "("; | | |||
2133 | if (cfgFileNameArg) { | | |||
2134 | h << "KSharedConfig::Ptr config"; | | |||
2135 | } | | |||
2136 | if (cfg.parentInConstructor) { | | |||
2137 | if (cfgFileNameArg) { | | |||
2138 | h << ", "; | | |||
2139 | } | | |||
2140 | h << "QObject *parent = nullptr"; | | |||
2141 | } | | |||
2142 | h << ");" << endl; | | |||
2143 | h << " friend class " << cfg.className << "Helper;" << endl << endl; | | |||
2144 | } | | |||
2145 | | ||||
2146 | if (hasNonModifySignals) { | | |||
2147 | h << " bool usrSave() override;" << endl; | | |||
2148 | } | | |||
2149 | | ||||
2150 | // Member variables | | |||
2151 | if (!cfg.memberVariables.isEmpty() && cfg.memberVariables != QLatin1String("private") && cfg.memberVariables != QLatin1String("dpointer")) { | | |||
2152 | h << " " << cfg.memberVariables << ":" << endl; | | |||
2153 | } | | |||
2154 | | ||||
2155 | // Class Parameters | | |||
2156 | for (QList<Param>::ConstIterator it = parameters.constBegin(); | | |||
2157 | it != parameters.constEnd(); ++it) { | | |||
2158 | h << " " << cppType((*it).type) << " mParam" << (*it).name << ";" << endl; | | |||
2159 | } | | |||
2160 | | ||||
2161 | if (cfg.memberVariables != QLatin1String("dpointer")) { | | |||
2162 | QString group; | | |||
2163 | for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { | | |||
2164 | if ((*itEntry)->group() != group) { | | |||
2165 | group = (*itEntry)->group(); | | |||
2166 | h << endl; | | |||
2167 | h << " // " << group << endl; | | |||
2168 | } | | |||
2169 | h << " " << cppType((*itEntry)->type()) << " " << varName((*itEntry)->name(), cfg); | | |||
2170 | if (!(*itEntry)->param().isEmpty()) { | | |||
2171 | h << QStringLiteral("[%1]").arg((*itEntry)->paramMax() + 1); | | |||
2172 | } | | |||
2173 | h << ";" << endl; | | |||
2174 | | ||||
2175 | if (cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name())) { | | |||
2176 | h << " "; | | |||
2177 | if (cfg.staticAccessors) { | | |||
2178 | h << "static "; | | |||
2179 | } | | |||
2180 | h << cppType((*itEntry)->type()) << " " << getDefaultFunction((*itEntry)->name()) << "_helper("; | | |||
2181 | if (!(*itEntry)->param().isEmpty()) { | | |||
2182 | h << " " << cppType((*itEntry)->paramType()) << " i "; | | |||
2183 | } | | |||
2184 | h << ")" << Const << ";" << endl; | | |||
2185 | } | | |||
2186 | } | | |||
2187 | | ||||
2188 | h << endl << " private:" << endl; | | |||
2189 | if (cfg.itemAccessors) { | | |||
2190 | for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { | | |||
2191 | h << " Item" << itemType((*itEntry)->type()) << " *" << itemVar(*itEntry, cfg); | | |||
2192 | if (!(*itEntry)->param().isEmpty()) { | | |||
2193 | h << QStringLiteral("[%1]").arg((*itEntry)->paramMax() + 1); | | |||
2194 | } | | |||
2195 | h << ";" << endl; | | |||
2196 | } | | |||
2197 | } | | |||
2198 | if (hasNonModifySignals) { | | |||
2199 | h << " uint " << varName(QStringLiteral("settingsChanged"), cfg) << ";" << endl; | | |||
2200 | } | | |||
2201 | | ||||
2202 | } else { | | |||
2203 | // use a private class for both member variables and items | | |||
2204 | h << " private:" << endl; | | |||
2205 | for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { | | |||
2206 | if (cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name())) { | | |||
2207 | h << " "; | | |||
2208 | if (cfg.staticAccessors) { | | |||
2209 | h << "static "; | | |||
2210 | } | | |||
2211 | h << cppType((*itEntry)->type()) << " " << getDefaultFunction((*itEntry)->name()) << "_helper("; | | |||
2212 | if (!(*itEntry)->param().isEmpty()) { | | |||
2213 | h << " " << cppType((*itEntry)->paramType()) << " i "; | | |||
2214 | } | | |||
2215 | h << ")" << Const << ";" << endl; | | |||
2216 | } | | |||
2217 | } | | |||
2218 | h << " " + cfg.className + "Private *d;" << endl; | | |||
2219 | } | | |||
2220 | | ||||
2221 | if (cfg.customAddons) { | | |||
2222 | h << " // Include custom additions" << endl; | | |||
2223 | h << " #include \"" << filenameOnly(baseName) << "_addons." << cfg.headerExtension << '"' << endl; | | |||
2224 | } | | |||
2225 | | ||||
2226 | h << "};" << endl << endl; | | |||
2227 | | ||||
2228 | endNamespaces(cfg.nameSpace, h); | | |||
2229 | 855 | | |||
2230 | h << "#endif" << endl << endl; | 856 | xmlParser.setInputFileName(inputFilename); | ||
857 | xmlParser.setConfigurationParameters(cfg); | ||||
858 | xmlParser.start(); | ||||
859 | ParseResult parseResult = xmlParser.getParseResult(); | ||||
2231 | 860 | | |||
2232 | header.close(); | 861 | if (hasErrors(xmlParser, parseResult, cfg)) { | ||
2233 | | ||||
2234 | QFile implementation(baseDir + implementationFileName); | | |||
2235 | if (!implementation.open(QIODevice::WriteOnly)) { | | |||
2236 | cerr << "Can not open '" << implementationFileName << "for writing." | | |||
2237 | << endl; | | |||
2238 | return 1; | 862 | return 1; | ||
2239 | } | 863 | } | ||
2240 | 864 | | |||
2241 | QTextStream cpp(&implementation); | 865 | // TODO: Move this to somewhere saner. | ||
2242 | 866 | for (const auto &signal : qAsConst(parseResult.signalList)) { | |||
2243 | cpp.setCodec("utf-8"); | 867 | parseResult.hasNonModifySignals |= !signal.modify; | ||
2244 | | ||||
2245 | cpp << "// This file is generated by kconfig_compiler_kf5 from " << QFileInfo(inputFilename).fileName() << "." << endl; | | |||
2246 | cpp << "// All changes you do to this file will be lost." << endl << endl; | | |||
2247 | | ||||
2248 | cpp << "#include \"" << headerFileName << "\"" << endl << endl; | | |||
2249 | | ||||
2250 | for (it = cfg.sourceIncludes.constBegin(); it != cfg.sourceIncludes.constEnd(); ++it) { | | |||
2251 | if ((*it).startsWith('"')) { | | |||
2252 | cpp << "#include " << *it << endl; | | |||
2253 | } else { | | |||
2254 | cpp << "#include <" << *it << ">" << endl; | | |||
2255 | } | | |||
2256 | } | | |||
2257 | | ||||
2258 | if (!cfg.sourceIncludes.isEmpty()) { | | |||
2259 | cpp << endl; | | |||
2260 | } | | |||
2261 | | ||||
2262 | if (cfg.setUserTexts && cfg.translationSystem == CfgConfig::KdeTranslation) { | | |||
2263 | cpp << "#include <klocalizedstring.h>" << endl << endl; | | |||
2264 | } | | |||
2265 | | ||||
2266 | // Header required by singleton implementation | | |||
2267 | if (cfg.singleton) { | | |||
2268 | cpp << "#include <qglobal.h>" << endl << "#include <QFile>" << endl << endl; | | |||
2269 | } | | |||
2270 | if (cfg.singleton && cfgFileNameArg) { | | |||
2271 | cpp << "#include <QDebug>" << endl << endl; | | |||
2272 | } | | |||
2273 | | ||||
2274 | if (!cfg.nameSpace.isEmpty()) { | | |||
2275 | cpp << "using namespace " << cfg.nameSpace << ";" << endl << endl; | | |||
2276 | } | | |||
2277 | | ||||
2278 | QString group; | | |||
2279 | | ||||
2280 | // private class implementation | | |||
2281 | if (cfg.dpointer) { | | |||
2282 | beginNamespaces(cfg.nameSpace, cpp); | | |||
2283 | cpp << "class " << cfg.className << "Private" << endl; | | |||
2284 | cpp << "{" << endl; | | |||
2285 | cpp << " public:" << endl; | | |||
2286 | for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { | | |||
2287 | if ((*itEntry)->group() != group) { | | |||
2288 | group = (*itEntry)->group(); | | |||
2289 | cpp << endl; | | |||
2290 | cpp << " // " << group << endl; | | |||
2291 | } | | |||
2292 | cpp << " " << cppType((*itEntry)->type()) << " " << varName((*itEntry)->name(), cfg); | | |||
2293 | if (!(*itEntry)->param().isEmpty()) { | | |||
2294 | cpp << QStringLiteral("[%1]").arg((*itEntry)->paramMax() + 1); | | |||
2295 | } | | |||
2296 | cpp << ";" << endl; | | |||
2297 | } | | |||
2298 | cpp << endl << " // items" << endl; | | |||
2299 | for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { | | |||
2300 | const QString declType = (*itEntry)->signalList().isEmpty() | | |||
2301 | ? QString(cfg.inherits + "::Item" + itemType((*itEntry)->type())) | | |||
2302 | : QStringLiteral("KConfigCompilerSignallingItem"); | | |||
2303 | cpp << " " << declType << " *" << itemVar( *itEntry, cfg ); | | |||
2304 | if (!(*itEntry)->param().isEmpty()) { | | |||
2305 | cpp << QStringLiteral("[%1]").arg((*itEntry)->paramMax() + 1); | | |||
2306 | } | | |||
2307 | cpp << ";" << endl; | | |||
2308 | } | | |||
2309 | if (hasNonModifySignals) { | | |||
2310 | cpp << " uint " << varName(QStringLiteral("settingsChanged"), cfg) << ";" << endl; | | |||
2311 | } | | |||
2312 | | ||||
2313 | cpp << "};" << endl << endl; | | |||
2314 | endNamespaces(cfg.nameSpace, cpp); | | |||
2315 | } | | |||
2316 | | ||||
2317 | // Singleton implementation | | |||
2318 | if (cfg.singleton) { | | |||
2319 | beginNamespaces(cfg.nameSpace, cpp); | | |||
2320 | cpp << "class " << cfg.className << "Helper" << endl; | | |||
2321 | cpp << '{' << endl; | | |||
2322 | cpp << " public:" << endl; | | |||
2323 | cpp << " " << cfg.className << "Helper() : q(nullptr) {}" << endl; | | |||
2324 | cpp << " ~" << cfg.className << "Helper() { delete q; }" << endl; | | |||
2325 | cpp << " " << cfg.className << "Helper(const " << cfg.className << "Helper&) = delete;" << endl; | | |||
2326 | cpp << " " << cfg.className << "Helper& operator=(const " << cfg.className << "Helper&) = delete;" << endl; | | |||
2327 | cpp << " " << cfg.className << " *q;" << endl; | | |||
2328 | cpp << "};" << endl; | | |||
2329 | endNamespaces(cfg.nameSpace, cpp); | | |||
2330 | cpp << "Q_GLOBAL_STATIC(" << cfg.className << "Helper, s_global" << cfg.className << ")" << endl; | | |||
2331 | | ||||
2332 | cpp << cfg.className << " *" << cfg.className << "::self()" << endl; | | |||
2333 | cpp << "{" << endl; | | |||
2334 | if (cfgFileNameArg) { | | |||
2335 | cpp << " if (!s_global" << cfg.className << "()->q)" << endl; | | |||
2336 | cpp << " qFatal(\"you need to call " << cfg.className << "::instance before using\");" << endl; | | |||
2337 | } else { | | |||
2338 | cpp << " if (!s_global" << cfg.className << "()->q) {" << endl; | | |||
2339 | cpp << " new " << cfg.className << ';' << endl; | | |||
2340 | cpp << " s_global" << cfg.className << "()->q->read();" << endl; | | |||
2341 | cpp << " }" << endl << endl; | | |||
2342 | } | | |||
2343 | cpp << " return s_global" << cfg.className << "()->q;" << endl; | | |||
2344 | cpp << "}" << endl << endl; | | |||
2345 | | ||||
2346 | if (cfgFileNameArg) { | | |||
2347 | auto instance = [&cfg, &cpp] (const QString &type, const QString &arg, bool isString) { | | |||
2348 | cpp << "void " << cfg.className << "::instance(" << type << " " << arg << ")" << endl; | | |||
2349 | cpp << "{" << endl; | | |||
2350 | cpp << " if (s_global" << cfg.className << "()->q) {" << endl; | | |||
2351 | cpp << " qDebug() << \"" << cfg.className << "::instance called after the first use - ignoring\";" << endl; | | |||
2352 | cpp << " return;" << endl; | | |||
2353 | cpp << " }" << endl; | | |||
2354 | cpp << " new " << cfg.className << "("; | | |||
2355 | if (isString) { | | |||
2356 | cpp << "KSharedConfig::openConfig(" << arg << ")"; | | |||
2357 | } else { | | |||
2358 | cpp << "std::move(" << arg << ")"; | | |||
2359 | } | | |||
2360 | cpp << ");" << endl; | | |||
2361 | cpp << " s_global" << cfg.className << "()->q->read();" << endl; | | |||
2362 | cpp << "}" << endl << endl; | | |||
2363 | }; | | |||
2364 | instance(QStringLiteral("const QString&"), QStringLiteral("cfgfilename"), true); | | |||
2365 | instance(QStringLiteral("KSharedConfig::Ptr"), QStringLiteral("config"), false); | | |||
2366 | } | | |||
2367 | } | | |||
2368 | | ||||
2369 | if (!cppPreamble.isEmpty()) { | | |||
2370 | cpp << cppPreamble << endl; | | |||
2371 | } | | |||
2372 | | ||||
2373 | // Constructor | | |||
2374 | cpp << cfg.className << "::" << cfg.className << "("; | | |||
2375 | if (cfgFileNameArg) { | | |||
2376 | if (! cfg.forceStringFilename) { | | |||
2377 | cpp << " KSharedConfig::Ptr config"; | | |||
2378 | } else { | | |||
2379 | cpp << " const QString& config"; | | |||
2380 | } | | |||
2381 | cpp << (parameters.isEmpty() ? "" : ","); | | |||
2382 | } | | |||
2383 | | ||||
2384 | for (QList<Param>::ConstIterator it = parameters.constBegin(); | | |||
2385 | it != parameters.constEnd(); ++it) { | | |||
2386 | if (it != parameters.constBegin()) { | | |||
2387 | cpp << ","; | | |||
2388 | } | | |||
2389 | cpp << " " << param((*it).type) << " " << (*it).name; | | |||
2390 | } | | |||
2391 | | ||||
2392 | if (cfg.parentInConstructor) { | | |||
2393 | if (cfgFileNameArg || !parameters.isEmpty()) { | | |||
2394 | cpp << ","; | | |||
2395 | } | | |||
2396 | cpp << " QObject *parent"; | | |||
2397 | } | | |||
2398 | cpp << " )" << endl; | | |||
2399 | | ||||
2400 | cpp << " : " << cfg.inherits << "("; | | |||
2401 | if (!cfgFileName.isEmpty()) { | | |||
2402 | cpp << " QStringLiteral( \"" << cfgFileName << "\" "; | | |||
2403 | } | | |||
2404 | if (cfgFileNameArg) { | | |||
2405 | if (! cfg.forceStringFilename) { | | |||
2406 | cpp << " std::move( config ) "; | | |||
2407 | } else { | | |||
2408 | cpp << " config "; | | |||
2409 | } | | |||
2410 | } | | |||
2411 | if (!cfgFileName.isEmpty()) { | | |||
2412 | cpp << ") "; | | |||
2413 | } | | |||
2414 | cpp << ")" << endl; | | |||
2415 | | ||||
2416 | // Store parameters | | |||
2417 | for (QList<Param>::ConstIterator it = parameters.constBegin(); | | |||
2418 | it != parameters.constEnd(); ++it) { | | |||
2419 | cpp << " , mParam" << (*it).name << "(" << (*it).name << ")" << endl; | | |||
2420 | } | | |||
2421 | | ||||
2422 | if (hasNonModifySignals && !cfg.dpointer) { | | |||
2423 | cpp << " , " << varName(QStringLiteral("settingsChanged"), cfg) << "(0)" << endl; | | |||
2424 | } | | |||
2425 | | ||||
2426 | cpp << "{" << endl; | | |||
2427 | | ||||
2428 | if (cfg.parentInConstructor) { | | |||
2429 | cpp << " setParent(parent);" << endl; | | |||
2430 | } | | |||
2431 | | ||||
2432 | if (cfg.dpointer) { | | |||
2433 | cpp << " d = new " + cfg.className + "Private;" << endl; | | |||
2434 | if (hasNonModifySignals) { | | |||
2435 | cpp << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " = 0;" << endl; | | |||
2436 | } | | |||
2437 | } | | |||
2438 | // Needed in case the singleton class is used as baseclass for | | |||
2439 | // another singleton. | | |||
2440 | if (cfg.singleton) { | | |||
2441 | cpp << " Q_ASSERT(!s_global" << cfg.className << "()->q);" << endl; | | |||
2442 | cpp << " s_global" << cfg.className << "()->q = this;" << endl; | | |||
2443 | } | | |||
2444 | | ||||
2445 | group.clear(); | | |||
2446 | | ||||
2447 | if (hasSignals) { | | |||
2448 | // this cast to base-class pointer-to-member is valid C++ | | |||
2449 | // https://stackoverflow.com/questions/4272909/is-it-safe-to-upcast-a-method-pointer-and-use-it-with-base-class-pointer/ | | |||
2450 | cpp << " KConfigCompilerSignallingItem::NotifyFunction notifyFunction =" | | |||
2451 | << " static_cast<KConfigCompilerSignallingItem::NotifyFunction>(&" | | |||
2452 | << cfg.className << "::itemChanged);" << endl << endl; | | |||
2453 | } | | |||
2454 | | ||||
2455 | for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { | | |||
2456 | if ((*itEntry)->group() != group) { | | |||
2457 | if (!group.isEmpty()) { | | |||
2458 | cpp << endl; | | |||
2459 | } | | |||
2460 | group = (*itEntry)->group(); | | |||
2461 | cpp << " setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl; | | |||
2462 | } | | |||
2463 | | ||||
2464 | QString key = paramString((*itEntry)->key(), parameters); | | |||
2465 | if (!(*itEntry)->code().isEmpty()) { | | |||
2466 | cpp << (*itEntry)->code() << endl; | | |||
2467 | } | | |||
2468 | if ((*itEntry)->type() == QLatin1String("Enum")) { | | |||
2469 | cpp << " QList<" + cfg.inherits + "::ItemEnum::Choice> values" | | |||
2470 | << (*itEntry)->name() << ";" << endl; | | |||
2471 | const QList<CfgEntry::Choice> choices = (*itEntry)->choices().choices; | | |||
2472 | QList<CfgEntry::Choice>::ConstIterator it; | | |||
2473 | for (it = choices.constBegin(); it != choices.constEnd(); ++it) { | | |||
2474 | cpp << " {" << endl; | | |||
2475 | cpp << " " + cfg.inherits + "::ItemEnum::Choice choice;" << endl; | | |||
2476 | cpp << " choice.name = QStringLiteral(\"" << (*it).name << "\");" << endl; | | |||
2477 | if (cfg.setUserTexts) { | | |||
2478 | if (!(*it).label.isEmpty()) { | | |||
2479 | cpp << " choice.label = " | | |||
2480 | << translatedString(cfg, (*it).label, (*it).context) | | |||
2481 | << ";" << endl; | | |||
2482 | } | | |||
2483 | if (!(*it).toolTip.isEmpty()) { | | |||
2484 | cpp << " choice.toolTip = " | | |||
2485 | << translatedString(cfg, (*it).toolTip, (*it).context) | | |||
2486 | << ";" << endl; | | |||
2487 | } | | |||
2488 | if (!(*it).whatsThis.isEmpty()) { | | |||
2489 | cpp << " choice.whatsThis = " | | |||
2490 | << translatedString(cfg, (*it).whatsThis, (*it).context) | | |||
2491 | << ";" << endl; | | |||
2492 | } | | |||
2493 | } | | |||
2494 | cpp << " values" << (*itEntry)->name() << ".append( choice );" << endl; | | |||
2495 | cpp << " }" << endl; | | |||
2496 | } | | |||
2497 | } | | |||
2498 | | ||||
2499 | if (!cfg.dpointer) { | | |||
2500 | cpp << itemDeclaration(*itEntry, cfg); | | |||
2501 | } | | |||
2502 | | ||||
2503 | if ((*itEntry)->param().isEmpty()) { | | |||
2504 | // Normal case | | |||
2505 | cpp << " " << itemPath(*itEntry, cfg) << " = " | | |||
2506 | << newItem((*itEntry), key, (*itEntry)->defaultValue(), cfg) << endl; | | |||
2507 | | ||||
2508 | if (!(*itEntry)->minValue().isEmpty()) { | | |||
2509 | cpp << " " << itemPath(*itEntry, cfg) << "->setMinValue(" << (*itEntry)->minValue() << ");" << endl; | | |||
2510 | } | | |||
2511 | if (!(*itEntry)->maxValue().isEmpty()) { | | |||
2512 | cpp << " " << itemPath(*itEntry, cfg) << "->setMaxValue(" << (*itEntry)->maxValue() << ");" << endl; | | |||
2513 | } | | |||
2514 | | ||||
2515 | if (cfg.setUserTexts) { | | |||
2516 | cpp << userTextsFunctions((*itEntry), cfg); | | |||
2517 | } | | |||
2518 | | ||||
2519 | if (cfg.allNotifiers || cfg.notifiers.contains((*itEntry)->name())) { | | |||
2520 | cpp << " " << itemPath(*itEntry, cfg) << "->setWriteFlags(KConfigBase::Notify);" << endl; | | |||
2521 | } | | |||
2522 | | ||||
2523 | cpp << " addItem( " << itemPath(*itEntry, cfg); | | |||
2524 | QString quotedName = (*itEntry)->name(); | | |||
2525 | addQuotes(quotedName); | | |||
2526 | if (quotedName != key) { | | |||
2527 | cpp << ", QStringLiteral( \"" << (*itEntry)->name() << "\" )"; | | |||
2528 | } | | |||
2529 | cpp << " );" << endl; | | |||
2530 | } else { | | |||
2531 | // Indexed | | |||
2532 | for (int i = 0; i <= (*itEntry)->paramMax(); i++) { | | |||
2533 | QString defaultStr; | | |||
2534 | QString itemVarStr(itemPath(*itEntry, cfg) + QStringLiteral("[%1]").arg(i)); | | |||
2535 | | ||||
2536 | if (!(*itEntry)->paramDefaultValue(i).isEmpty()) { | | |||
2537 | defaultStr = (*itEntry)->paramDefaultValue(i); | | |||
2538 | } else if (!(*itEntry)->defaultValue().isEmpty()) { | | |||
2539 | defaultStr = paramString((*itEntry)->defaultValue(), (*itEntry), i); | | |||
2540 | } else { | | |||
2541 | defaultStr = defaultValue((*itEntry)->type()); | | |||
2542 | } | | |||
2543 | | ||||
2544 | cpp << " " << itemVarStr << " = " | | |||
2545 | << newItem((*itEntry), paramString(key, *itEntry, i), defaultStr, cfg, QStringLiteral("[%1]").arg(i)) << endl; | | |||
2546 | | ||||
2547 | if (cfg.setUserTexts) { | | |||
2548 | cpp << userTextsFunctions(*itEntry, cfg, itemVarStr, (*itEntry)->paramName()); | | |||
2549 | } | | |||
2550 | | ||||
2551 | // Make mutators for enum parameters work by adding them with $(..) replaced by the | | |||
2552 | // param name. The check for isImmutable in the set* functions doesn't have the param | | |||
2553 | // name available, just the corresponding enum value (int), so we need to store the | | |||
2554 | // param names in a separate static list!. | | |||
2555 | cpp << " addItem( " << itemVarStr << ", QStringLiteral( \""; | | |||
2556 | if ((*itEntry)->paramType() == QLatin1String("Enum")) { | | |||
2557 | cpp << (*itEntry)->paramName().replace("$(" + (*itEntry)->param() + ')', QLatin1String("%1")).arg((*itEntry)->paramValues()[i]); | | |||
2558 | } else { | | |||
2559 | cpp << (*itEntry)->paramName().replace("$(" + (*itEntry)->param() + ')', QLatin1String("%1")).arg(i); | | |||
2560 | } | | |||
2561 | cpp << "\" ) );" << endl; | | |||
2562 | } | | |||
2563 | } | | |||
2564 | } | | |||
2565 | | ||||
2566 | cpp << "}" << endl << endl; | | |||
2567 | | ||||
2568 | if (cfg.dpointer) { | | |||
2569 | // setters and getters go in Cpp if in dpointer mode | | |||
2570 | for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { | | |||
2571 | QString n = (*itEntry)->name(); | | |||
2572 | QString t = (*itEntry)->type(); | | |||
2573 | | ||||
2574 | // Manipulator | | |||
2575 | if (cfg.allMutators || cfg.mutators.contains(n)) { | | |||
2576 | cpp << "void " << setFunction(n, cfg.className) << "( "; | | |||
2577 | if (!(*itEntry)->param().isEmpty()) { | | |||
2578 | cpp << cppType((*itEntry)->paramType()) << " i, "; | | |||
2579 | } | | |||
2580 | if (cfg.useEnumTypes && t == QLatin1String("Enum")) { | | |||
2581 | cpp << enumType(*itEntry, cfg.globalEnums); | | |||
2582 | } else { | | |||
2583 | cpp << param(t); | | |||
2584 | } | | |||
2585 | cpp << " v )" << endl; | | |||
2586 | // function body inline only if not using dpointer | | |||
2587 | // for BC mode | | |||
2588 | cpp << "{" << endl; | | |||
2589 | cpp << indent(memberMutatorBody(*itEntry, cfg), 6); | | |||
2590 | cpp << "}" << endl << endl; | | |||
2591 | } | | |||
2592 | | ||||
2593 | // Accessor | | |||
2594 | if (cfg.useEnumTypes && t == QLatin1String("Enum")) { | | |||
2595 | cpp << enumType(*itEntry, cfg.globalEnums); | | |||
2596 | } else { | | |||
2597 | cpp << cppType(t); | | |||
2598 | } | | |||
2599 | cpp << " " << getFunction(n, cfg.className) << "("; | | |||
2600 | if (!(*itEntry)->param().isEmpty()) { | | |||
2601 | cpp << " " << cppType((*itEntry)->paramType()) << " i "; | | |||
2602 | } | | |||
2603 | cpp << ")" << Const << endl; | | |||
2604 | // function body inline only if not using dpointer | | |||
2605 | // for BC mode | | |||
2606 | cpp << "{" << endl; | | |||
2607 | cpp << indent(memberAccessorBody(*itEntry, cfg.globalEnums, cfg), 2); | | |||
2608 | cpp << "}" << endl << endl; | | |||
2609 | | ||||
2610 | // Default value Accessor -- written by the loop below | | |||
2611 | | ||||
2612 | // Item accessor | | |||
2613 | if (cfg.itemAccessors) { | | |||
2614 | cpp << endl; | | |||
2615 | cpp << cfg.inherits + "::Item" << itemType((*itEntry)->type()) << " *" | | |||
2616 | << getFunction(n, cfg.className) << "Item("; | | |||
2617 | if (!(*itEntry)->param().isEmpty()) { | | |||
2618 | cpp << " " << cppType((*itEntry)->paramType()) << " i "; | | |||
2619 | } | | |||
2620 | cpp << ")" << endl; | | |||
2621 | cpp << "{" << endl; | | |||
2622 | cpp << indent(itemAccessorBody(*itEntry, cfg), 2); | | |||
2623 | cpp << "}" << endl; | | |||
2624 | } | | |||
2625 | | ||||
2626 | cpp << endl; | | |||
2627 | } | | |||
2628 | } | | |||
2629 | | ||||
2630 | // default value getters always go in Cpp | | |||
2631 | for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { | | |||
2632 | QString n = (*itEntry)->name(); | | |||
2633 | QString t = (*itEntry)->type(); | | |||
2634 | | ||||
2635 | // Default value Accessor, as "helper" function | | |||
2636 | if ((cfg.allDefaultGetters || cfg.defaultGetters.contains(n)) && !(*itEntry)->defaultValue().isEmpty()) { | | |||
2637 | cpp << cppType(t) << " " << getDefaultFunction(n, cfg.className) << "_helper("; | | |||
2638 | if (!(*itEntry)->param().isEmpty()) { | | |||
2639 | cpp << " " << cppType((*itEntry)->paramType()) << " i "; | | |||
2640 | } | | |||
2641 | cpp << ")" << Const << endl; | | |||
2642 | cpp << "{" << endl; | | |||
2643 | cpp << memberGetDefaultBody(*itEntry) << endl; | | |||
2644 | cpp << "}" << endl << endl; | | |||
2645 | } | | |||
2646 | } | | |||
2647 | | ||||
2648 | // Destructor | | |||
2649 | cpp << cfg.className << "::~" << cfg.className << "()" << endl; | | |||
2650 | cpp << "{" << endl; | | |||
2651 | if (cfg.dpointer) { | | |||
2652 | cpp << " delete d;" << endl; | | |||
2653 | } | | |||
2654 | if (cfg.singleton) { | | |||
2655 | cpp << " s_global" << cfg.className << "()->q = nullptr;" << endl; | | |||
2656 | } | | |||
2657 | cpp << "}" << endl << endl; | | |||
2658 | | ||||
2659 | if (hasNonModifySignals) { | | |||
2660 | cpp << "bool " << cfg.className << "::" << "usrSave()" << endl; | | |||
2661 | cpp << "{" << endl; | | |||
2662 | cpp << " const bool res = " << cfg.inherits << "::usrSave();" << endl; | | |||
2663 | cpp << " if (!res) return false;" << endl << endl; | | |||
2664 | for (const Signal &signal : qAsConst(signalList)) { | | |||
2665 | if (signal.modify) { | | |||
2666 | continue; | | |||
2667 | } | | |||
2668 | | ||||
2669 | cpp << " if ( " << varPath(QStringLiteral("settingsChanged"), cfg) << " & " << signalEnumName(signal.name) << " )" << endl; | | |||
2670 | cpp << " Q_EMIT " << signal.name << "("; | | |||
2671 | QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd(); | | |||
2672 | for (it = signal.arguments.constBegin(); it != itEnd;) { | | |||
2673 | SignalArguments argument = *it; | | |||
2674 | bool cast = false; | | |||
2675 | if (cfg.useEnumTypes && argument.type == QLatin1String("Enum")) { | | |||
2676 | for (int i = 0, end = entries.count(); i < end; ++i) { | | |||
2677 | if (entries[i]->name() == argument.variableName) { | | |||
2678 | cpp << "static_cast<" << enumType(entries[i], cfg.globalEnums) << ">("; | | |||
2679 | cast = true; | | |||
2680 | break; | | |||
2681 | } | | |||
2682 | } | | |||
2683 | } | | |||
2684 | cpp << varPath(argument.variableName, cfg); | | |||
2685 | if (cast) { | | |||
2686 | cpp << ")"; | | |||
2687 | } | | |||
2688 | if (++it != itEnd) { | | |||
2689 | cpp << ", "; | | |||
2690 | } | | |||
2691 | } | | |||
2692 | cpp << ");" << endl; | | |||
2693 | } | | |||
2694 | | ||||
2695 | cpp << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " = 0;" << endl; | | |||
2696 | cpp << " return true;" << endl; | | |||
2697 | cpp << "}" << endl; | | |||
2698 | } | | |||
2699 | | ||||
2700 | if (hasSignals) { | | |||
2701 | cpp << endl; | | |||
2702 | cpp << "void " << cfg.className << "::" << "itemChanged(quint64 flags) {" << endl; | | |||
2703 | if (hasNonModifySignals) | | |||
2704 | cpp << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " |= flags;" << endl; | | |||
2705 | | ||||
2706 | if (!signalList.isEmpty()) | | |||
2707 | cpp << endl; | | |||
2708 | | ||||
2709 | for (const Signal &signal : qAsConst(signalList)) { | | |||
2710 | if (signal.modify) { | | |||
2711 | cpp << " if ( flags & " << signalEnumName(signal.name) << " ) {" << endl; | | |||
2712 | cpp << " Q_EMIT " << signal.name << "();" << endl; | | |||
2713 | cpp << " }" << endl; | | |||
2714 | } | | |||
2715 | } | 868 | } | ||
2716 | 869 | | |||
2717 | cpp << "}" << endl; | 870 | KConfigHeaderGenerator headerGenerator(inputFilename, baseDir, cfg, parseResult); | ||
2718 | } | 871 | headerGenerator.start(); | ||
2719 | 872 | headerGenerator.save(); | |||
2720 | if (hasSignals || cfg.generateProperties) { | | |||
2721 | // Add includemoc if they are signals defined. | | |||
2722 | cpp << endl; | | |||
2723 | cpp << "#include \"" << mocFileName << "\"" << endl; | | |||
2724 | cpp << endl; | | |||
2725 | } | | |||
2726 | 873 | | |||
2727 | // clear entries list | 874 | KConfigSourceGenerator sourceGenerator(inputFilename, baseDir, cfg, parseResult); | ||
2728 | qDeleteAll(entries); | 875 | sourceGenerator.start(); | ||
876 | sourceGenerator.save(); | ||||
2729 | 877 | | |||
2730 | implementation.close(); | 878 | qDeleteAll(parseResult.entries); | ||
2731 | } | 879 | } |
Space before & not after