File indexing completed on 2024-04-28 15:29:53

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 1999 David Faure <faure@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 
0008 #include "kbuildservicetypefactory_p.h"
0009 #include "ksycoca.h"
0010 #include "ksycocadict_p.h"
0011 #include "ksycocaresourcelist_p.h"
0012 #include "sycocadebug.h"
0013 
0014 #include <KConfigGroup>
0015 #include <KDesktopFile>
0016 #include <QDebug>
0017 #include <QFileInfo>
0018 #include <QHash>
0019 #include <QStandardPaths>
0020 #include <assert.h>
0021 
0022 KBuildServiceTypeFactory::KBuildServiceTypeFactory(KSycoca *db)
0023     : KServiceTypeFactory(db)
0024 {
0025     m_resourceList.emplace_back("servicetypes", QStringLiteral("kservicetypes5"), QStringLiteral("*.desktop"));
0026 }
0027 
0028 KBuildServiceTypeFactory::~KBuildServiceTypeFactory()
0029 {
0030 }
0031 
0032 KServiceType::Ptr KBuildServiceTypeFactory::findServiceTypeByName(const QString &_name)
0033 {
0034     assert(sycoca()->isBuilding());
0035     // We're building a database - the service type must be in memory
0036     KSycocaEntry::Ptr servType = m_entryDict->value(_name);
0037     return KServiceType::Ptr(static_cast<KServiceType *>(servType.data()));
0038 }
0039 
0040 KSycocaEntry *KBuildServiceTypeFactory::createEntry(const QString &file) const
0041 {
0042     QString name = file;
0043     int pos = name.lastIndexOf(QLatin1Char('/'));
0044     if (pos != -1) {
0045         name.remove(0, pos + 1);
0046     }
0047 
0048     if (name.isEmpty()) {
0049         return nullptr;
0050     }
0051 
0052     QString filePath = QLatin1String("kservicetypes5/") + file;
0053     const QString qrcFilePath = QLatin1String(":/") + filePath;
0054     if (QFileInfo::exists(qrcFilePath)) {
0055         filePath = qrcFilePath;
0056     }
0057     KDesktopFile desktopFile(QStandardPaths::GenericDataLocation, filePath);
0058     const KConfigGroup desktopGroup = desktopFile.desktopGroup();
0059 
0060     if (desktopGroup.readEntry("Hidden", false) == true) {
0061         return nullptr;
0062     }
0063 
0064     const QString type = desktopGroup.readEntry("Type");
0065     if (type != QLatin1String("ServiceType")) {
0066         qCWarning(SYCOCA) << "The service type config file " << desktopFile.fileName() << " has Type=" << type << " instead of Type=ServiceType";
0067         return nullptr;
0068     }
0069 
0070     const QString serviceType = desktopGroup.readEntry("X-KDE-ServiceType");
0071 
0072     if (serviceType.isEmpty()) {
0073         qCWarning(SYCOCA) << "The service type config file " << desktopFile.fileName() << " does not contain a ServiceType=... entry";
0074         return nullptr;
0075     }
0076 
0077     KServiceType *e = new KServiceType(&desktopFile);
0078 
0079     if (e->isDeleted()) {
0080         delete e;
0081         return nullptr;
0082     }
0083 
0084     if (!(e->isValid())) {
0085         qCWarning(SYCOCA) << "Invalid ServiceType : " << file;
0086         delete e;
0087         return nullptr;
0088     }
0089 
0090     return e;
0091 }
0092 
0093 void KBuildServiceTypeFactory::saveHeader(QDataStream &str)
0094 {
0095     KSycocaFactory::saveHeader(str);
0096     str << qint32(m_propertyTypeDict.count());
0097     for (auto it = m_propertyTypeDict.cbegin(); it != m_propertyTypeDict.cend(); ++it) {
0098         str << it.key() << static_cast<qint32>(it.value());
0099     }
0100 }
0101 
0102 void KBuildServiceTypeFactory::save(QDataStream &str)
0103 {
0104     KSycocaFactory::save(str);
0105 }
0106 
0107 void KBuildServiceTypeFactory::addEntry(const KSycocaEntry::Ptr &newEntry)
0108 {
0109     KSycocaFactory::addEntry(newEntry);
0110 
0111     KServiceType::Ptr serviceType(static_cast<KServiceType *>(newEntry.data()));
0112 
0113     const QMap<QString, QVariant::Type> &pd = serviceType->propertyDefs();
0114     for (auto pit = pd.cbegin(); pit != pd.cend(); ++pit) {
0115         const QString &property = pit.key();
0116         const QVariant::Type &type = pit.value();
0117         auto dictit = m_propertyTypeDict.constFind(property);
0118         if (dictit == m_propertyTypeDict.cend()) {
0119             m_propertyTypeDict.insert(property, type);
0120         } else if (dictit.value() != static_cast<int>(type)) {
0121             qCWarning(SYCOCA) << "Property '" << property << "' is defined multiple times (" << serviceType->name() << ")";
0122         }
0123     }
0124 }