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

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 1999 Waldo Bastian <bastian@kde.org>
0004     SPDX-FileCopyrightText: David Faure <faure@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-only
0007 */
0008 
0009 #include "kservicetype.h"
0010 #include "kservice.h"
0011 #include "kservicefactory_p.h"
0012 #include "kservicetype_p.h"
0013 #include "kservicetypefactory_p.h"
0014 #include "kservicetypeprofile.h"
0015 #include "ksycoca.h"
0016 #include "ksycoca_p.h"
0017 #include "servicesdebug.h"
0018 #include <KConfigGroup>
0019 #include <KDesktopFile>
0020 #include <assert.h>
0021 
0022 extern int servicesDebugArea();
0023 
0024 template QDataStream &operator>><QString, QVariant>(QDataStream &, QMap<QString, QVariant> &);
0025 template QDataStream &operator<< <QString, QVariant>(QDataStream &, const QMap<QString, QVariant> &);
0026 
0027 KServiceType::KServiceType(KDesktopFile *config)
0028     : KSycocaEntry(*new KServiceTypePrivate(config->fileName()))
0029 {
0030     Q_D(KServiceType);
0031     d->init(config);
0032 }
0033 
0034 void KServiceTypePrivate::init(KDesktopFile *config)
0035 {
0036     //    Q_Q(KServiceType);
0037 
0038     KConfigGroup desktopGroup = config->desktopGroup();
0039     m_strName = desktopGroup.readEntry("X-KDE-ServiceType");
0040     m_strComment = desktopGroup.readEntry("Comment");
0041     deleted = desktopGroup.readEntry("Hidden", false);
0042 
0043     // We store this as property to preserve BC, we can't change that
0044     // because KSycoca needs to remain BC between KDE 2.x and KDE 3.x
0045     QString sDerived = desktopGroup.readEntry("X-KDE-Derived");
0046     m_bDerived = !sDerived.isEmpty();
0047     if (m_bDerived) {
0048         m_mapProps.insert(QStringLiteral("X-KDE-Derived"), sDerived);
0049     }
0050 
0051     const QStringList lst = config->groupList();
0052 
0053     for (const auto &groupName : lst) {
0054         if (QLatin1String marker("Property::"); groupName.startsWith(marker)) {
0055             KConfigGroup cg(config, groupName);
0056 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0057             QVariant variant = QVariant::nameToType(cg.readEntry("Type").toLatin1().constData());
0058 #else
0059             QVariant variant(QMetaType::fromName(cg.readEntry("Type").toLatin1().constData()));
0060 #endif
0061             variant = cg.readEntry("Value", variant);
0062 
0063             if (variant.isValid()) {
0064                 m_mapProps.insert(groupName.mid(marker.size()), variant);
0065             }
0066         } else if (QLatin1String marker("PropertyDef::"); groupName.startsWith(marker)) {
0067             KConfigGroup cg(config, groupName);
0068 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0069             m_mapPropDefs.insert(groupName.mid(marker.size()), QVariant::nameToType(cg.readEntry("Type").toLatin1().constData()));
0070 #else
0071             m_mapPropDefs.insert(groupName.mid(marker.size()),
0072                                  static_cast<QVariant::Type>(QMetaType::fromName(cg.readEntry("Type").toLatin1().constData()).id()));
0073 #endif
0074         }
0075     }
0076 }
0077 
0078 KServiceType::KServiceType(QDataStream &_str, int offset)
0079     : KSycocaEntry(*new KServiceTypePrivate(_str, offset))
0080 {
0081     Q_D(KServiceType);
0082     d->load(_str);
0083 }
0084 
0085 void KServiceTypePrivate::load(QDataStream &_str)
0086 {
0087     qint8 b;
0088     QString dummy;
0089     _str >> m_strName >> dummy >> m_strComment >> m_mapProps >> m_mapPropDefs >> b >> m_serviceOffersOffset;
0090     m_bDerived = m_mapProps.contains(QLatin1String("X-KDE-Derived"));
0091 }
0092 
0093 void KServiceTypePrivate::save(QDataStream &_str)
0094 {
0095     KSycocaEntryPrivate::save(_str);
0096     // !! This data structure should remain binary compatible at all times !!
0097     // You may add new fields at the end. Make sure to update the version
0098     // number in ksycoca.h
0099     _str << m_strName << QString() /*was icon*/ << m_strComment << m_mapProps << m_mapPropDefs << qint8(1) << m_serviceOffersOffset;
0100 }
0101 
0102 KServiceType::~KServiceType()
0103 {
0104 }
0105 
0106 QString KServiceType::parentServiceType() const
0107 {
0108     const QVariant v = property(QStringLiteral("X-KDE-Derived"));
0109     return v.toString();
0110 }
0111 
0112 bool KServiceType::inherits(const QString &servTypeName) const
0113 {
0114     if (name() == servTypeName) {
0115         return true;
0116     }
0117     QString st = parentServiceType();
0118     while (!st.isEmpty()) {
0119         KServiceType::Ptr ptr = KServiceType::serviceType(st);
0120         if (!ptr) {
0121             return false; // error
0122         }
0123         if (ptr->name() == servTypeName) {
0124             return true;
0125         }
0126         st = ptr->parentServiceType();
0127     }
0128     return false;
0129 }
0130 
0131 QVariant KServiceTypePrivate::property(const QString &_name) const
0132 {
0133     QVariant v;
0134 
0135     if (_name == QLatin1String("Name")) {
0136         v = QVariant(m_strName);
0137     } else if (_name == QLatin1String("Comment")) {
0138         v = QVariant(m_strComment);
0139     } else {
0140         v = m_mapProps.value(_name);
0141     }
0142 
0143     return v;
0144 }
0145 
0146 QStringList KServiceTypePrivate::propertyNames() const
0147 {
0148     QStringList res = m_mapProps.keys();
0149     res.append(QStringLiteral("Name"));
0150     res.append(QStringLiteral("Comment"));
0151     return res;
0152 }
0153 
0154 QVariant::Type KServiceType::propertyDef(const QString &_name) const
0155 {
0156     Q_D(const KServiceType);
0157     return d->m_mapPropDefs.value(_name, QVariant::Invalid);
0158 }
0159 
0160 QStringList KServiceType::propertyDefNames() const
0161 {
0162     Q_D(const KServiceType);
0163     return d->m_mapPropDefs.keys();
0164 }
0165 
0166 KServiceType::Ptr KServiceType::serviceType(const QString &_name)
0167 {
0168     KSycoca::self()->ensureCacheValid();
0169     return KSycocaPrivate::self()->serviceTypeFactory()->findServiceTypeByName(_name);
0170 }
0171 
0172 KServiceType::List KServiceType::allServiceTypes()
0173 {
0174     KSycoca::self()->ensureCacheValid();
0175     return KSycocaPrivate::self()->serviceTypeFactory()->allServiceTypes();
0176 }
0177 
0178 KServiceType::Ptr KServiceType::parentType()
0179 {
0180     Q_D(KServiceType);
0181     if (d->m_parentTypeLoaded) {
0182         return d->parentType;
0183     }
0184 
0185     d->m_parentTypeLoaded = true;
0186 
0187     const QString parentSt = parentServiceType();
0188     if (parentSt.isEmpty()) {
0189         return KServiceType::Ptr();
0190     }
0191 
0192     KSycoca::self()->ensureCacheValid();
0193     d->parentType = KSycocaPrivate::self()->serviceTypeFactory()->findServiceTypeByName(parentSt);
0194     if (!d->parentType) {
0195         qCWarning(SERVICES) << entryPath() << "specifies undefined MIME type/servicetype" << parentSt;
0196     }
0197     return d->parentType;
0198 }
0199 
0200 void KServiceType::setServiceOffersOffset(int offset)
0201 {
0202     Q_D(KServiceType);
0203     Q_ASSERT(offset != -1);
0204     d->m_serviceOffersOffset = offset;
0205 }
0206 
0207 int KServiceType::serviceOffersOffset() const
0208 {
0209     Q_D(const KServiceType);
0210     return d->serviceOffersOffset();
0211 }
0212 
0213 QString KServiceType::comment() const
0214 {
0215     Q_D(const KServiceType);
0216     return d->comment();
0217 }
0218 
0219 bool KServiceType::isDerived() const
0220 {
0221     Q_D(const KServiceType);
0222     return d->m_bDerived;
0223 }
0224 
0225 QMap<QString, QVariant::Type> KServiceType::propertyDefs() const
0226 {
0227     Q_D(const KServiceType);
0228     return d->m_mapPropDefs;
0229 }