File indexing completed on 2024-05-12 05:46:52

0001 /******************************************************************************
0002  *  Copyright 2013 Sebastian Kügler <sebas@kde.org>                           *
0003  *  Copyright 2014 Alex Richardson <arichardson.kde@gmail.com>                *
0004  *                                                                            *
0005  *  This library is free software; you can redistribute it and/or             *
0006  *  modify it under the terms of the GNU Lesser General Public                *
0007  *                                                                            *
0008  *  License as published by the Free Software Foundation; either              *
0009  *  version 2.1 of the License, or (at your option) version 3, or any         *
0010  *  later version accepted by the membership of KDE e.V. (or its              *
0011  *  successor approved by the membership of KDE e.V.), which shall            *
0012  *  act as a proxy defined in Section 6 of version 3 of the license.          *
0013  *                                                                            *
0014  *  This library is distributed in the hope that it will be useful,           *
0015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of            *
0016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
0017  *  Lesser General Public License for more details.                           *
0018  *                                                                            *
0019  *  You should have received a copy of the GNU Lesser General Public          *
0020  *  License along with this library.  If not, see                             *
0021  *  <http://www.gnu.org/licenses/>.                                           *
0022  *                                                                            *
0023  ******************************************************************************/
0024 
0025 #include "desktoptojson.h"
0026 #include "../lib/plugin/desktopfileparser_p.h"
0027 
0028 
0029 #include <QFile>
0030 #include <QFileInfo>
0031 #include <QJsonDocument>
0032 #include <QJsonObject>
0033 #include <QJsonArray>
0034 
0035 DesktopToJson::DesktopToJson(QCommandLineParser *parser, const QCommandLineOption &i,
0036                              const QCommandLineOption &o, const QCommandLineOption &v,
0037                              const QCommandLineOption &c, const QCommandLineOption &s)
0038     : m_parser(parser),
0039       input(i),
0040       output(o),
0041       verbose(v),
0042       compat(c),
0043       serviceTypesOption(s)
0044 {
0045 }
0046 
0047 bool DesktopFileParser::s_verbose = false;
0048 bool DesktopFileParser::s_compatibilityMode = false;
0049 
0050 
0051 int DesktopToJson::runMain()
0052 {
0053     if (!m_parser->isSet(input)) {
0054         m_parser->showHelp(1);
0055         return 1;
0056     }
0057     if (m_parser->isSet(verbose)) {
0058         DesktopFileParser::s_verbose = true;
0059     }
0060     if (m_parser->isSet(compat)) {
0061         DesktopFileParser::s_compatibilityMode = true;
0062     }
0063     if (!resolveFiles()) {
0064         qCCritical(DESKTOPPARSER) << "Failed to resolve filenames" << m_inFile << m_outFile << endl;
0065         return 1;
0066     }
0067 
0068 #pragma message("TODO: make it an error if one of the service type files is invalid or not found")
0069     const QStringList serviceTypes = m_parser->values(serviceTypesOption);
0070     return convert(m_inFile, m_outFile, serviceTypes) ? EXIT_SUCCESS : EXIT_FAILURE;
0071 }
0072 
0073 bool DesktopToJson::resolveFiles()
0074 {
0075     if (m_parser->isSet(input)) {
0076         m_inFile = m_parser->value(input);
0077         const QFileInfo fi(m_inFile);
0078         if (!fi.exists()) {
0079             qCCritical(DESKTOPPARSER) << "File not found: " << m_inFile << endl;
0080             return false;
0081         }
0082         if (!fi.isAbsolute()) {
0083             m_inFile = fi.absoluteFilePath();
0084         }
0085     }
0086 
0087     if (m_parser->isSet(output)) {
0088         m_outFile = m_parser->value(output);
0089     } else if (!m_inFile.isEmpty()) {
0090         m_outFile = m_inFile;
0091         m_outFile.replace(QStringLiteral(".desktop"), QStringLiteral(".json"));
0092     }
0093 
0094     return m_inFile != m_outFile && !m_inFile.isEmpty() && !m_outFile.isEmpty();
0095 }
0096 
0097 void DesktopFileParser::convertToCompatibilityJson(const QString &key, const QString &value, QJsonObject &json, int lineNr)
0098 {
0099     // XXX: Hidden=true doesn't make sense with json plugins since the metadata is inside the .so
0100     static const QStringList boolkeys = QStringList {
0101         QStringLiteral("Hidden"),
0102         QStringLiteral("X-KDE-PluginInfo-EnabledByDefault"),
0103     };
0104     static const QStringList stringlistkeys = QStringList {
0105         QStringLiteral("X-KDE-ServiceTypes"),
0106         QStringLiteral("X-KDE-PluginInfo-Depends"),
0107     };
0108     if (boolkeys.contains(key)) {
0109         // should only be lower case, but be tolerant here
0110         if (value.toLower() == QLatin1String("true")) {
0111             json[key] = true;
0112         } else {
0113             if (value.toLower() != QLatin1String("false")) {
0114                 qCWarning(DESKTOPPARSER).nospace() << "Expected boolean value for key \"" << key
0115                     << "\" at line " << lineNr << "but got \"" << value << "\" instead.";
0116             }
0117             json[key] = false;
0118         }
0119     } else if (stringlistkeys.contains(key)) {
0120         json[key] = QJsonArray::fromStringList(DesktopFileParser::deserializeList(value));
0121     } else {
0122         json[key] = value;
0123     }
0124 }
0125 
0126 bool DesktopToJson::convert(const QString &src, const QString &dest, const QStringList& serviceTypes)
0127 {
0128 
0129     QJsonObject json;
0130     DesktopFileParser::convert(src, serviceTypes, json, nullptr);
0131 
0132     if (DesktopFileParser::s_compatibilityMode) {
0133         Q_ASSERT(json.value(QStringLiteral("KPlugin")).toObject().isEmpty());
0134         json.remove(QStringLiteral("KPlugin"));
0135     }
0136     QJsonDocument jdoc;
0137     jdoc.setObject(json);
0138 
0139     QFile file(dest);
0140     if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
0141         qCCritical(DESKTOPPARSER) << "Failed to open " << dest << endl;
0142         return false;
0143     }
0144 
0145     file.write(jdoc.toJson());
0146     qCDebug(DESKTOPPARSER) << "Generated " << dest << endl;
0147     return true;
0148 }