File indexing completed on 2024-05-19 05:05:18

0001 ###########################################################################
0002 #   SPDX-License-Identifier: GPL-2.0-or-later
0003 #                                                                         #
0004 #   SPDX-FileCopyrightText: 2019-2022 Thomas Fischer <fischer@unix-ag.uni-kl.de>
0005 #                                                                         #
0006 #   This script is free software; you can redistribute it and/or modify   #
0007 #   it under the terms of the GNU General Public License as published by  #
0008 #   the Free Software Foundation; either version 2 of the License, or     #
0009 #   (at your option) any later version.                                   #
0010 #                                                                         #
0011 #   This script is distributed in the hope that it will be useful,        #
0012 #   but WITHOUT ANY WARRANTY; without even the implied warranty of        #
0013 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
0014 #   GNU General Public License for more details.                          #
0015 #                                                                         #
0016 #   You should have received a copy of the GNU General Public License     #
0017 #   along with this script; if not, see <https://www.gnu.org/licenses/>.  #
0018 ###########################################################################
0019 
0020 import sys
0021 import json
0022 import datetime
0023 
0024 
0025 def print_copyright_header(outputdevice=sys.stdout):
0026     """Print the default copyright statement to the output device."""
0027 
0028     print("""/***************************************************************************
0029  *   SPDX-License-Identifier: GPL-2.0-or-later
0030  *                                                                         *
0031  *   SPDX-FileCopyrightText: 2004-{year} Thomas Fischer <fischer@unix-ag.uni-kl.de>
0032  *                                                                         *
0033  *   This program is free software; you can redistribute it and/or modify  *
0034  *   it under the terms of the GNU General Public License as published by  *
0035  *   the Free Software Foundation; either version 2 of the License, or     *
0036  *   (at your option) any later version.                                   *
0037  *                                                                         *
0038  *   This program is distributed in the hope that it will be useful,       *
0039  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0040  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0041  *   GNU General Public License for more details.                          *
0042  *                                                                         *
0043  *   You should have received a copy of the GNU General Public License     *
0044  *   along with this program; if not, see <https://www.gnu.org/licenses/>. *
0045  ***************************************************************************/"""
0046           .format(year=datetime.date.today().year), file=outputdevice)
0047     print(file=outputdevice)
0048     print("""/// This file has been automatically generated using the script 'preferences-generator.py'
0049 /// based on configuration data from file 'preferences.json'. If there are any problems or
0050 /// bugs, you need to fix those two files and re-generated both 'preferences.h' and
0051 /// 'preferences.cpp'. Manual changes in this file will be overwritten the next time the
0052 /// script will be run. You have been warned.""", file=outputdevice)
0053     print(file=outputdevice)
0054 
0055 
0056 def needsReference(type):
0057     """Check if given Qt/C++ data type should be passed by reference rather than by value."""
0058     return type in ["QString", "QStringList"] \
0059         or type.startswith(('QPair<', 'QVector<', 'QSet<', 'QList<', 'QLinkedList<', 'QMap<', 'QVector<', 'QHash<'))
0060 
0061 
0062 def rewriteobsoletecode(input, indent):
0063     inputlist = input if isinstance(input, list) else ([input] if isinstance(input, str) else None)
0064     if not isinstance(inputlist, list):
0065         return None
0066 
0067     result = []
0068     for line in inputlist:
0069         if "::KeepEmptyParts" in line or "::SkipEmptyParts" in line:
0070             result.append("#if QT_VERSION >= 0x050e00")
0071             result.append(indent + line.replace("QString::KeepEmptyParts", "Qt::KeepEmptyParts").replace("QString::SkipEmptyParts", "Qt::SkipEmptyParts"))
0072             result.append("#else // QT_VERSION < 0x050e00")
0073             result.append(indent + line.replace("Qt::KeepEmptyParts", "QString::KeepEmptyParts").replace("Qt::SkipEmptyParts", "QString::SkipEmptyParts"))
0074             result.append("#endif // QT_VERSION >= 0x050e00")
0075         else:
0076             result.append(indent + line)
0077     return result
0078 
0079 
0080 def print_header(headerincludes, implementationincludes, enums, settings, outputdevice=sys.stdout):
0081     """Print the header file for the Preferences ('preferences.h')."""
0082 
0083     print_copyright_header(outputdevice)
0084 
0085     # Include guard definition
0086     print("#ifndef KBIBTEX_CONFIG_PREFERENCES_H", file=outputdevice)
0087     print("#define KBIBTEX_CONFIG_PREFERENCES_H", file=outputdevice)
0088     print(file=outputdevice)
0089 
0090     # Include other headers as necessary
0091     for includeline in headerincludes:
0092         if len(includeline) == 0:
0093             print(file=outputdevice)
0094         elif includeline[0] == '#':
0095             print(includeline, file=outputdevice)
0096         else:
0097             print("#include", includeline, file=outputdevice)
0098     if headerincludes:
0099         print(file=outputdevice)
0100     print('#ifdef HAVE_KF', file=outputdevice)
0101     print('#include "kbibtexconfig_export.h"', file=outputdevice)
0102     print('#endif // HAVE_KF', file=outputdevice)
0103     print(file=outputdevice)
0104 
0105     print("class KBIBTEXCONFIG_EXPORT Preferences {", file=outputdevice)
0106     print("public:", file=outputdevice)
0107     print("    static Preferences &instance();", file=outputdevice)
0108     print("    ~Preferences();", file=outputdevice)
0109     print(file=outputdevice)
0110 
0111     for enum in sorted(enums):
0112         print("    enum class " + enum + " {", end="", file=outputdevice)
0113         first = True
0114         for enumvaluepair in enums[enum]:
0115             if not first:
0116                 print(",", end="", file=outputdevice)
0117             print(" ", end="", file=outputdevice)
0118             if isinstance(enumvaluepair, list):
0119                 print(enumvaluepair[0], end="", file=outputdevice)
0120                 if len(enumvaluepair) >= 2 and enumvaluepair[1] != None:
0121                     print(
0122                         " = " + str(enumvaluepair[1]), end="", file=outputdevice)
0123             elif isinstance(enumvaluepair, str):
0124                 print(enumvaluepair, end="", file=outputdevice)
0125             first = False
0126         print(" };", file=outputdevice)
0127     if enums:
0128         print(file=outputdevice)
0129 
0130     for setting in settings:
0131         stem = setting['stem']
0132         type = setting['type']
0133         lowercasestart = stem[0].lower() + stem[1:]
0134         print(file=outputdevice)
0135         print("    /// ***", stem, "of type", type, "***", file=outputdevice)
0136         print(file=outputdevice)
0137         if 'predefined' in setting:
0138             for predefined in setting['predefined']:
0139                 print("    static const " + type + " " +
0140                       lowercasestart + predefined[0] + ";", file=outputdevice)
0141         print("    static const " +
0142               type + " default" + stem + ";", file=outputdevice)
0143         if 'availabletype' in setting:
0144             print("    static const " +
0145                   setting['availabletype'] + " available" + stem + "s;", file=outputdevice)
0146         print(("    const " if needsReference(type) else "    ") + type + (" &" if needsReference(type) else " ") +
0147               lowercasestart + "();", file=outputdevice)
0148         print('#ifdef HAVE_KF', file=outputdevice)
0149         print('    /*!', file=outputdevice)
0150         print('     * @return true if this setting has been changed, i.e. the new value was different from the old value; false otherwise or under error conditions', file=outputdevice)
0151         print('     */', file=outputdevice)
0152         print("    bool set" + stem + "(const " +
0153               type + (" &" if needsReference(type) else " ") + lowercasestart + ");", file=outputdevice)
0154         print('#endif // HAVE_KF', file=outputdevice)
0155         print("", file=outputdevice)
0156 
0157     print("private:", file=outputdevice)
0158     print("    Q_DISABLE_COPY(Preferences)", file=outputdevice)
0159     print(file=outputdevice)
0160     print("    explicit Preferences();", file=outputdevice)
0161     print(file=outputdevice)
0162     print("    class Private;", file=outputdevice)
0163     print("    Private *const d;", file=outputdevice)
0164     print("};", file=outputdevice)
0165     print(file=outputdevice)
0166     if len(enums) > 0:
0167         print("// qHash functions useful if an enum class is used as key in a QHash", file=outputdevice)
0168         print(file=outputdevice)
0169     for enum in sorted(enums):
0170         varName = enum[0].lower() + enum[1:]
0171         print("inline uint qHash(const Preferences::" + enum + " &" + varName + ", uint seed)", file=outputdevice)
0172         print("{", file=outputdevice)
0173         print("    return qHash(static_cast<int>(" + varName + "), seed);", file=outputdevice)
0174         print("}", file=outputdevice)
0175         print(file=outputdevice)
0176     print("#endif // KBIBTEX_CONFIG_PREFERENCES_H", file=outputdevice)
0177 
0178 
0179 def print_implementation(headerincludes, implementationincludes, enums, settings, outputdevice=sys.stdout):
0180     """Print the implementatiom file for the Preferences ('preferences.cpp')."""
0181 
0182     print_copyright_header(outputdevice)
0183 
0184     # Include headers that will always be necessary
0185     print('#include <Preferences>', file=outputdevice)
0186     print(file=outputdevice)
0187     print('#include <QCoreApplication>', file=outputdevice)
0188     print('#ifdef HAVE_KF', file=outputdevice)
0189     print('#include <KLocalizedString>', file=outputdevice)
0190     print('#include <KSharedConfig>', file=outputdevice)
0191     print('#include <KConfigWatcher>', file=outputdevice)
0192     print('#include <KConfigGroup>', file=outputdevice)
0193     print('#else // HAVE_KF', file=outputdevice)
0194     print('#define i18n(text) QStringLiteral(text)', file=outputdevice)
0195     print('#define i18nc(comment,text) QStringLiteral(text)', file=outputdevice)
0196     print('#endif // HAVE_KF', file=outputdevice)
0197     print(file=outputdevice)
0198     print('#ifdef HAVE_KF', file=outputdevice)
0199     print('#include <NotificationHub>', file=outputdevice)
0200     print('#endif // HAVE_KF', file=outputdevice)
0201     print(file=outputdevice)
0202     # Include other headers as necessary
0203     for includeline in implementationincludes:
0204         if len(includeline) == 0:
0205             print(file=outputdevice)
0206         elif includeline[0] == '#':
0207             print(includeline, file=outputdevice)
0208         else:
0209             print("#include", includeline, file=outputdevice)
0210     if implementationincludes:
0211         print(file=outputdevice)
0212     print('class Preferences::Private', file=outputdevice)
0213     print('{', file=outputdevice)
0214     print('public:', file=outputdevice)
0215     print('#ifdef HAVE_KF', file=outputdevice)
0216     print('    KSharedConfigPtr config;', file=outputdevice)
0217     print('    KConfigWatcher::Ptr watcher;', file=outputdevice)
0218     print(file=outputdevice)
0219     for setting in settings:
0220         stem = setting['stem']
0221         type = setting['type']
0222         if type in enums:
0223             type = "Preferences::" + type
0224         print('    bool dirtyFlag' + stem + ';', file=outputdevice)
0225         print('    ' + type + ' cached' + stem + ';', file=outputdevice)
0226     print('#endif // HAVE_KF', file=outputdevice)
0227 
0228     # Constructor for Preferences::Private
0229     print(file=outputdevice)
0230     print('    Private(Preferences *)', file=outputdevice)
0231     print('    {', file=outputdevice)
0232     print('#ifdef HAVE_KF', file=outputdevice)
0233     print('        config = KSharedConfig::openConfig(QStringLiteral("kbibtexrc"));', file=outputdevice)
0234     print('        watcher = KConfigWatcher::create(config);', file=outputdevice)
0235     for setting in settings:
0236         stem = setting['stem']
0237         print('        dirtyFlag' + stem + ' = true;', file=outputdevice)
0238         print('        cached' + stem + ' = Preferences::default' +
0239               stem + ';', file=outputdevice)
0240     print('#endif // HAVE_KF', file=outputdevice)
0241     print('    }', file=outputdevice)
0242 
0243     print(file=outputdevice)
0244     print('#ifdef HAVE_KF', file=outputdevice)
0245     first = True
0246     for setting in settings:
0247         stem = setting['stem']
0248         type = setting['type']
0249         if type in enums:
0250             type = "Preferences::" + type
0251         if first:
0252             first = False
0253         else:
0254             print(file=outputdevice)
0255         print('    inline bool validateValueFor' + stem + '(const ' + type +
0256               (" &" if needsReference(type) else " ") + "valueToBeChecked) {", file=outputdevice)
0257         if 'validationcode' in setting:
0258             if isinstance(setting['validationcode'], list):
0259                 for line in setting['validationcode']:
0260                     print('        ' + line, file=outputdevice)
0261                 if not setting['validationcode'][-1].startswith("return "):
0262                     print('        return false;', file=outputdevice)
0263             elif isinstance(setting['validationcode'], str):
0264                 print('        ' +
0265                       setting['validationcode'], file=outputdevice)
0266         elif 'availabletype' in setting and setting['availabletype'].startswith('QVector<QPair<' + type + ","):
0267             print('        for (' + setting['availabletype'] + '::ConstIterator it = Preferences::available' + stem +
0268                   's.constBegin(); it != Preferences::available' + stem + 's.constEnd(); ++it)', file=outputdevice)
0269             print(
0270                 '            if (it->first == valueToBeChecked) return true;', file=outputdevice)
0271             print('        return false;', file=outputdevice)
0272         elif 'availabletype' in setting and setting['availabletype'] == "QStringList":
0273             print('        return Preferences::available' + stem +
0274                   's.contains(valueToBeChecked);', file=outputdevice)
0275         else:
0276             print('        Q_UNUSED(valueToBeChecked)', file=outputdevice)
0277             print('        return true;', file=outputdevice)
0278         print('    }', file=outputdevice)
0279 
0280         if 'readEntry' in setting:
0281             print(file=outputdevice)
0282             print('    ' + type + ' readEntry' + stem +
0283                   '(const KConfigGroup &configGroup, const QString &key) const', file=outputdevice)
0284             print('    {', file=outputdevice)
0285             readEntryList = rewriteobsoletecode(setting['readEntry'], '        ')
0286             if isinstance(readEntryList, list):
0287                 for line in readEntryList:
0288                     print(line, file=outputdevice)
0289             print('    }', file=outputdevice)
0290 
0291         if 'writeEntry' in setting:
0292             print(file=outputdevice)
0293             print('    void writeEntry' + stem + '(KConfigGroup &configGroup, const QString &key, const ' +
0294                   type + (" &" if needsReference(type) else " ") + 'valueToBeWritten)', file=outputdevice)
0295             print('    {', file=outputdevice)
0296             if isinstance(setting['writeEntry'], list):
0297                 for line in setting['writeEntry']:
0298                     print('        ' + line, file=outputdevice)
0299             elif isinstance(setting['writeEntry'], str):
0300                 print('        ' + setting['writeEntry'], file=outputdevice)
0301             print('    }', file=outputdevice)
0302     print('#endif // HAVE_KF', file=outputdevice)
0303     print('};', file=outputdevice)
0304 
0305     # Singleton function Preferences::instance()
0306     print(file=outputdevice)
0307     print('Preferences &Preferences::instance()', file=outputdevice)
0308     print('{', file=outputdevice)
0309     print('    static Preferences singleton;', file=outputdevice)
0310     print('    return singleton;', file=outputdevice)
0311     print('}', file=outputdevice)
0312     print(file=outputdevice)
0313     # Constructor for class Preferences
0314     print('Preferences::Preferences()', file=outputdevice)
0315     print('        : d(new Preferences::Private(this))', file=outputdevice)
0316     print('{', file=outputdevice)
0317     print('#ifdef HAVE_KF', file=outputdevice)
0318     print(
0319         '    QObject::connect(d->watcher.data(), &KConfigWatcher::configChanged, QCoreApplication::instance(), [this](const KConfigGroup &group, const QByteArrayList &names) {', file=outputdevice)
0320     print('        QSet<int> eventsToPublish;', file=outputdevice)
0321     for setting in settings:
0322         stem = setting['stem']
0323         configgroup = setting['configgroup'] if 'configgroup' in setting else 'General'
0324         print('        if (group.name() == QStringLiteral("' + configgroup +
0325               '") && names.contains("' + stem + '")) {', file=outputdevice)
0326         print('            /// Configuration setting ' + stem +
0327               ' got changed by another Preferences instance";', file=outputdevice)
0328         print('            d->dirtyFlag' +
0329               stem + ' = true;', file=outputdevice)
0330         if 'notificationevent' in setting:
0331             print('            eventsToPublish.insert(' +
0332                   setting['notificationevent'] + ');', file=outputdevice)
0333         print('        }', file=outputdevice)
0334     print(file=outputdevice)
0335     print('        for (const int eventId : eventsToPublish)', file=outputdevice)
0336     print('            NotificationHub::publishEvent(eventId);', file=outputdevice)
0337     print('    });', file=outputdevice)
0338     print('#endif // HAVE_KF', file=outputdevice)
0339     print('}', file=outputdevice)
0340     print(file=outputdevice)
0341     # Destructor for Preferences
0342     print('Preferences::~Preferences()', file=outputdevice)
0343     print('{', file=outputdevice)
0344     print('    delete d;', file=outputdevice)
0345     print('}', file=outputdevice)
0346 
0347     for setting in settings:
0348         stem = setting['stem']
0349         configgroup = setting['configgroup'] if 'configgroup' in setting else 'General'
0350         type = setting['type']
0351         typeInConfig = "int" if type in enums.keys() else type
0352         if 'podtype' in setting:
0353             typeInConfig = setting['podtype']
0354         if type in enums:
0355             type = "Preferences::" + type
0356         lowercasestart = stem[0].lower() + stem[1:]
0357 
0358         print(file=outputdevice)
0359 
0360         if 'predefined' in setting:
0361             for predefined in setting['predefined']:
0362                 print('const ' + type + ' Preferences::' + lowercasestart +
0363                       predefined[0] + " = " + predefined[1] + ";", file=outputdevice)
0364 
0365         if 'available' in setting:
0366             available = setting['available']
0367             print('const ' + setting['availabletype'] + ' Preferences::available' + stem +
0368                   ('s ' if available.startswith("{") else "s = ") + available + ";", file=outputdevice)
0369 
0370         default = "nullptr"
0371         if 'default' in setting:
0372             default = setting['default']
0373             if 'predefined' in setting and default in [pair[0] for pair in setting['predefined']]:
0374                 default = "Preferences::" + lowercasestart + default
0375         elif 'availabletype' in setting:
0376             if setting['availabletype'].startswith("QVector<QPair<"):
0377                 default = 'Preferences::available' + stem + 's.front().first'
0378             elif setting['availabletype'] == "QStringList":
0379                 default = 'Preferences::available' + stem + 's.front()'
0380         print('const ' + type + ' Preferences::default' + stem +
0381               (' ' if default.startswith("{") else " = ") + default + ";", file=outputdevice)
0382 
0383         print(file=outputdevice)
0384 
0385         print(("const " if needsReference(type) else "") + type + (" &" if needsReference(type) else " ") +
0386               "Preferences::" + lowercasestart + "()", file=outputdevice)
0387         print("{", file=outputdevice)
0388         print('#ifdef HAVE_KF', file=outputdevice)
0389         print('    if (d->dirtyFlag' + stem + ') {', file=outputdevice)
0390         print('        d->config->reparseConfiguration();', file=outputdevice)
0391         print('        static const KConfigGroup configGroup(d->config, QStringLiteral("' +
0392               configgroup + '"));', file=outputdevice)
0393         print('        const ' + type +
0394               ' valueFromConfig = ', end="", file=outputdevice)
0395         if 'readEntry' in setting:
0396             print('d->readEntry' + stem + '(configGroup, QStringLiteral("' +
0397                   stem + '"));', file=outputdevice)
0398         else:
0399             if typeInConfig != type:
0400                 print('static_cast<' + type + '>(', end="", file=outputdevice)
0401             print('configGroup.readEntry(QStringLiteral("' +
0402                   stem + '"), ', end="", file=outputdevice)
0403             if typeInConfig != type:
0404                 print('static_cast<' + typeInConfig +
0405                       '>(', end="", file=outputdevice)
0406             print('Preferences::default' + stem, end="", file=outputdevice)
0407             if typeInConfig != type:
0408                 print(')', end="", file=outputdevice)
0409             print(')', end="", file=outputdevice)
0410             if typeInConfig != type:
0411                 print(')', end="", file=outputdevice)
0412             print(';', file=outputdevice)
0413         print('        if (d->validateValueFor' + stem +
0414               '(valueFromConfig)) {', file=outputdevice)
0415         print('            d->cached' + stem +
0416               ' = valueFromConfig;', file=outputdevice)
0417         print('            d->dirtyFlag' +
0418               stem + ' = false;', file=outputdevice)
0419         print('        } else {', file=outputdevice)
0420         print('            /// Configuration file setting for ' + stem +
0421               ' has an invalid value, using default as fallback', file=outputdevice)
0422         print('            set' + stem +
0423               '(Preferences::default' + stem + ');', file=outputdevice)
0424         print('        }', file=outputdevice)
0425         print('    }', file=outputdevice)
0426         print('    return d->cached' + stem + ";", file=outputdevice)
0427         print('#else // HAVE_KF', file=outputdevice)
0428         print('    return default' + stem + ";", file=outputdevice)
0429         print('#endif // HAVE_KF', file=outputdevice)
0430         print("}", file=outputdevice)
0431 
0432         print(file=outputdevice)
0433 
0434         print('#ifdef HAVE_KF', file=outputdevice)
0435         print("bool Preferences::set" + stem + '(const ' + type +
0436               (" &" if needsReference(type) else " ") + 'newValue)', file=outputdevice)
0437         print("{", file=outputdevice)
0438 
0439         if 'sanitizecode' in setting:
0440             newValueVariable = 'sanitizedNewValue'
0441             if isinstance(setting['sanitizecode'], str):
0442                 print('    ' + setting['sanitizecode'], file=outputdevice)
0443             elif isinstance(setting['sanitizecode'], list):
0444                 for line in setting['sanitizecode']:
0445                     print('    ' + line, file=outputdevice)
0446             else:
0447                 newValueVariable = 'newValue'
0448         elif 'availabletype' in setting and setting['availabletype'] == 'QStringList':
0449             newValueVariable = 'sanitizedNewValue'
0450             print('    ' + type + ' sanitizedNewValue = newValue;',
0451                   file=outputdevice)
0452             print('    const ' + type +
0453                   ' lowerSanitizedNewValue = sanitizedNewValue.toLower();', file=outputdevice)
0454             print('    for (const QString &known' + stem +
0455                   ' : available' + stem + 's)', file=outputdevice)
0456             print('        if (known' + stem +
0457                   '.toLower() == lowerSanitizedNewValue) {', file=outputdevice)
0458             print('            sanitizedNewValue = known' +
0459                   stem + ';', file=outputdevice)
0460             print('            break;', file=outputdevice)
0461             print('        }', file=outputdevice)
0462         else:
0463             newValueVariable = 'newValue'
0464 
0465         print('    if (!d->validateValueFor' + stem +
0466               '(' + newValueVariable + ')) return false;', file=outputdevice)
0467         print('    d->dirtyFlag' + stem + ' = false;', file=outputdevice)
0468         print('    d->cached' + stem + ' = ' +
0469               newValueVariable + ';', file=outputdevice)
0470         print('    static KConfigGroup configGroup(d->config, QStringLiteral("' +
0471               configgroup + '"));', file=outputdevice)
0472         print('    const ' + type + ' valueFromConfig = ',
0473               end="", file=outputdevice)
0474         if 'readEntry' in setting:
0475             print('d->readEntry' + stem + '(configGroup, QStringLiteral("' +
0476                   stem + '"));', file=outputdevice)
0477         else:
0478             if typeInConfig != type:
0479                 print('static_cast<' + type + '>(', end="", file=outputdevice)
0480             print('configGroup.readEntry(QStringLiteral("' +
0481                   stem + '"), ', end="", file=outputdevice)
0482             if typeInConfig != type:
0483                 print('static_cast<' + typeInConfig +
0484                       '>(', end="", file=outputdevice)
0485             print('Preferences::default' + stem, end="", file=outputdevice)
0486             if typeInConfig != type:
0487                 print(')', end="", file=outputdevice)
0488             print(')', end="", file=outputdevice)
0489             if typeInConfig != type:
0490                 print(')', end="", file=outputdevice)
0491             print(';', file=outputdevice)
0492         print('    if (valueFromConfig == ' + newValueVariable +
0493               ') return false;', file=outputdevice)
0494         if 'writeEntry' in setting:
0495             print('    d->writeEntry' + stem + '(configGroup, QStringLiteral("' +
0496                   stem + '"), ' + newValueVariable + ');', file=outputdevice)
0497         else:
0498             print('    configGroup.writeEntry(QStringLiteral("' +
0499                   stem + '"), ', end="", file=outputdevice)
0500             if typeInConfig != type:
0501                 print('static_cast<' + typeInConfig +
0502                       '>(', end="", file=outputdevice)
0503             print(newValueVariable, end="", file=outputdevice)
0504             if typeInConfig != type:
0505                 print(')', end="", file=outputdevice)
0506             print(', KConfig::Notify);', file=outputdevice)
0507         print('    d->config->sync();', file=outputdevice)
0508         # NotificationHub::publishEvent(notificationEventId);
0509         print('    return true;', file=outputdevice)
0510         print("}", file=outputdevice)
0511         print('#endif // HAVE_KF', file=outputdevice)
0512 
0513 
0514 jsondata = {}
0515 with open("preferences.json") as jsonfile:
0516     jsondata = json.load(jsonfile)
0517 headerincludes = jsondata['headerincludes'] \
0518     if 'headerincludes' in jsondata else {}
0519 implementationincludes = jsondata['implementationincludes'] \
0520     if 'implementationincludes' in jsondata else {}
0521 enums = jsondata['enums'] \
0522     if 'enums' in jsondata else {}
0523 settings = jsondata['settings'] \
0524     if 'settings' in jsondata else {}
0525 
0526 for setting in settings:
0527     if 'headerincludes' in setting:
0528         headerincludes.extend(setting['headerincludes'])
0529 
0530 with open("/tmp/preferences.h", "w") as headerfile:
0531     print_header(headerincludes, implementationincludes,
0532                  enums, settings, outputdevice=headerfile)
0533 with open("/tmp/preferences.cpp", "w") as implementationfile:
0534     print_implementation(headerincludes, implementationincludes,
0535                          enums, settings, outputdevice=implementationfile)